Criando interfaces de administração consistentes

Estas diretrizes visam criar uma interface de administração coesa, focando na usabilidade, acessibilidade e um layout estruturado. Consulte o índice para ver o que está incluído e navegar facilmente para cada seção.

Nota: A terminologia usada aqui é definida no glossário da interface de administração.

0. Prefácio - Estrutura da página de configuração e links da barra lateral

Ao adicionar novas páginas de configuração na interface de administração, cada página precisará de um link para a barra lateral, e cada página precisará de um título e uma descrição de cabeçalho. Isso é para que sejamos consistentes em todos os lugares, e melhorias futuras na pesquisa de administração possam exibir todo o layout da interface de administração.

Geralmente, a estrutura da interface de administração parece com isso:

  • Interface de administração
    • Página de configuração (exibida na barra lateral)
      • Aba de configurações
      • Abas opcionais de terceiro nível
        • Editar/Novo recurso de terceiro nível

Eventualmente, uma “visão geral da seção” será inserida entre a interface raiz e as páginas de configuração.

Links da barra lateral

Todas as páginas de administração devem ser adicionadas ao ADMIN_NAV_MAP em discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub . Cada item deve ter, no mínimo, estas chaves:

  • name - Um identificador único para o link, deve estar em snake_case
  • route OU href - O route é um identificador de rota Ember, como adminUsers. Para administradores, estes são definidos no mapa de rotas de administração . Um href pode ser usado no lugar, mas route é preferível.
  • label OU text - Label é uma chave I18n, que geralmente deve ser admin.config.page_name.title (veja a seção de traduções abaixo). Se text for usado, será texto já traduzido.

Estas chaves opcionais também podem ser fornecidas:

  • description - É recomendado que você também forneça isso. É uma chave I18n, geralmente deve ser admin.config.page_name.header_description.
  • icon - Também recomendado, isso é exibido ao lado do link na barra lateral.
  • routeModels - Matriz de dados de URL para o caso de parâmetros de rota. Por exemplo, adminCustomizeThemes tem um parâmetro de rota :type, então você pode passar routeModels: ["components"]. Os itens da matriz são usados na mesma ordem em que os parâmetros de rota aparecem.
  • moderator: Defina isso como true se moderadores devem ver esta página na barra lateral.
  • keywords: Uma chave I18n, com uma lista de palavras-chave separadas por | para o link da barra lateral, usada para “peso extra de pesquisa” ao filtrar/pesquisar páginas.
  • links: Uma lista de rotas de 3º nível que estão abaixo da página na barra lateral. Estes não são exibidos na própria barra lateral. Isso será usado para recursos futuros de pesquisa de administração.
  • settings_area e settings_category: Se a página mostrar apenas uma lista de configurações do site filtradas, então uma destas deve ser preenchida. Se a configuração do site tiver uma area definida, que é usada em AdminAreaSettings, então settings_area deve ser usada. Se uma categoria inteira de configurações for exibida na página, e também usada em AdminAreaSettings, então settings_category deve ser usada.
  • multi_tabbed: Se a página tiver uma aba de configuração e outras abas, então isso deve ser definido como true. Ajuda a gerar links para o sistema de pesquisa de administração.

Traduções

O título e a descrição do cabeçalho para cada página de configuração devem estar sob:

  • admin
    • config
      • page_name
        • title: “Título da página”
        • header_description: “Esta página é para xyz”

Você pode ver exemplos disso aqui:

1. Migalhas (Breadcrumbs)

As migalhas servem como uma ferramenta de navegação, ajudando os usuários a entender sua localização atual, estrutura de conteúdo e hierarquia dentro da interface de administração.

Admin > Migalha > Rastro
Título da página

:art: Design

Estrutura

  1. Admin: prefixo fixo que aparece no início de cada rastro de migalhas, vinculando a /admin
  2. Link: abre a página na mesma janela
  3. Separador: um ícone angle-right separa cada link

Uso

Quando usar:

  • Presente em todas as páginas de administração
  • Situado acima do conteúdo (título, descrição, abas)
  • Mostra a página atualmente selecionada

Quando não usar:

  • Ao visitar uma nova rota ou de edição

Conteúdo

  • Cada item inclui um link para sua página relacionada
  • Mostra a página atualmente selecionada

Acessibilidade

  • Um elemento nav com aria-label="Breadcrumb" envolve uma lista ordenada para fornecer um marco de navegação
  • Aplique aria-current="page" no último link para indicar que é a página atual
  • Para mais detalhes, veja Exemplo de Migalhas das Práticas de Autoria WAI-ARIA

:hammer_and_wrench: Implementação

O componente DBreadcrumbsContainer deve ser colocado em algum lugar na página:

<DBreadcrumbsContainer />

Em seguida, cada elemento DBreadcrumbsItem adicionado a qualquer componente em uma rota ou rota filha será renderizado neste container. Cada DBreadcrumbsItem tem um @label e @path que devem ser fornecidos:

<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}}
/>

Como isso parece com um exemplo visual, usando o plugin Discourse AI:

2. Cabeçalho e título da página

A seção superior de uma página de administração, contendo o título da página, junto com ações e descrição opcionais.

:art: Design

Estrutura

  • Título da página: Título da página

  • Descrição da página: Introdução ou descrição do que o conteúdo abrange (opcional)

  • Ação primária: Ação primária do título da página (opcional)

  • Ação secundária: Configurações do botão de ação secundária do título da página (opcional)

Uso e conteúdo

  • Título da página: Utilize o nível de cabeçalho 1 para explicar o assunto principal da página em caixa de frases. Geralmente, a tradução I18n deve estar sob admin.config.your_page.title.

  • Descrição da página: Suporta nós básicos de markdown como _itálico_, **negrito** e [nome do link](url)

  • Ação primária: Utilize btn-primary. Não inclua um ícone. Geralmente, a tradução I18n deve estar sob admin.config.your_page.header_description.

  • Ação secundária: Utilize as configurações do botão btn-default, visível apenas se existir uma ação primária. Não inclua um ícone.

    :point_right: Seja claro com os botões de ação. Por exemplo, use rótulos descritivos como “Adicionar emoji” em vez de apenas “Adicionar” para reduzir a ambiguidade.

:hammer_and_wrench: Implementação

O componente DPageHeader é usado aqui. Isso aceita argumentos para @titleLabel, @descriptionLabel, @learnMoreUrl e @shouldDisplay. Isso usa yields nomeados no Ember para fornecer 5 blocos nomeados para o conteúdo:

  1. breadcrumbs - Quaisquer componentes adicionais DBreadcrumbsItem para a página devem ser colocados aqui.
  2. actions - Usado para definir os botões à direita do título. Isso rende um objeto chamado actions que pode ser usado para renderizar botões Default, Primary, Danger e Wrapped.
  3. title - Uma alternativa ao @titleLabel, permitindo marcação personalizada dentro do cabeçalho.
  4. drawer - Uma seção de gaveta colapsável opcional, exibida quando @showDrawer é true.
  5. tabs - Usado para definir as abas da página usando componentes NavItem. @hideTabs pode ser usado para remover esta parte do cabeçalho se não for necessária.

Um exemplo completo está abaixo:

<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>

Os títulos das páginas para a aba do navegador são tratados nas rotas Ember usando a funcionalidade titleToken. Cada vez que isso é usado em uma rota, ele adiciona o token ao final do título da aba do navegador. Esteja ciente de que você deve usar a classe DiscourseRoute para estender sua rota, não a Route normal do ember para que isso funcione:

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

:point_right: O cabeçalho da página é automaticamente ocultado para caminhos /new e /edit para suportar Rotas de terceiro nível. Pode ser substituído usando o argumento @shouldDisplay.

3. Abas

Uma navegação opcional que fornece acesso a níveis mais profundos de configurações ou recursos. Também nos referimos a isso como páginas ou navegação de “terceiro nível”.

:art: Design

Estamos usando abas para alternar entre visualizações diferentes, mas relacionadas, dentro do mesmo contexto.

Uso

  • Não usado para navegação primária
  • Apenas uma ativa por vez

:hammer_and_wrench: Implementação

Veja os detalhes do Cabeçalho da Página, as abas são definidas no 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 destino de visão geral/seção

Permite que os usuários vejam o conteúdo de uma seção, especialmente quando a barra lateral está recolhida ou em dispositivos móveis.

:art: Design

Estrutura
Use um layout de três colunas iguais usando um sistema de grade. Em telas pequenas, essas colunas serão empilhadas verticalmente.

Design e uso

  • Pode ser acessado através de migalhas (Admin > Comunidade > Visão geral)
  • Cada seção deve ter uma, exceto plugins (que mostram instalados) e relatórios (apenas uma página)
  • O item tem:
    • nome - igual ao link da seção
    • descrição - uma breve descrição do que a página trata
    • ícone - mesmo ícone usado para a barra lateral

:hammer_and_wrench: Implementação

Fragmentos de código ou link para um tópico/GitHub

5. Conteúdo da página

A área principal de uma página de administração onde configurações, configurações e outros conteúdos são exibidos e interagidos.

:art: Design

Estrutura
Use um layout 2/3 + 1/3 usando um sistema de grade. A seção primária ocupa dois terços e a seção secundária ocupa um terço do espaço. Em telas pequenas, essas colunas serão empilhadas verticalmente.

  • Área de configuração: Uma seção específica dentro do conteúdo da página dedicada a configurações e ajustes.
  • Ajuda/referência/inserção: Uma área dentro do conteúdo da página fornecendo guias, documentação ou informações contextuais adicionais. (opcional)

Design e uso

  • Agrupe configurações e ações semelhantes em cartões
  • Estruture layouts primário/secundário para que a seção primária (2/3) seja usada para configurações principais, e a seção secundária (1/3) seja para informações adicionais ou contexto útil
  • Se a seção secundária não estiver disponível, mantenha a largura da seção primária a mesma

Conteúdo

:hammer_and_wrench: Implementação

Fragmentos de código ou links do GitHub

5.a. Subcabeçalho

Um subcabeçalho é um cabeçalho secundário usado para dividir o conteúdo sob uma seção, geralmente abaixo das abas.

Estrutura

  • Subcabeçalho: Subcabeçalho do que o conteúdo abrange (opcional)
  • Ação primária: Ação primária do subcabeçalho (opcional)
  • Ação secundária: Configurações do botão de ação secundária do subcabeçalho (opcional)

Uso e conteúdo

  • Subcabeçalho: Utilize o nível de cabeçalho 2 para explicar o assunto principal do conteúdo relacionado. Inclua apenas se:

    • Houver um botão de ação primário, ou
    • Houver uma descrição explicando a seção.
  • Ação primária: Utilize btn-primary. Não inclua um ícone.

  • Ação secundária: Utilize as configurações do botão btn-default, visível apenas se existir uma ação primária. Não inclua um ícone.

    :point_right: Seja claro com os botões de ação. Por exemplo, use rótulos descritivos como “Adicionar emoji” em vez de apenas “Adicionar” para reduzir a ambiguidade.

:hammer_and_wrench: Implementação

Isso é semelhante ao DPageHeader, há um componente DPageSubheader. A principal diferença é que há apenas um yield nomeado para actions.

  1. actions - Usado para definir os botões à direita do título. Isso rende um objeto chamado actions que pode ser usado para renderizar botões Default, Primary, Danger e 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 configuração

A área de configuração é composta por cartões ou seções. Os cartões são ótimos para agrupar informações e tarefas relacionadas, ajudando os usuários a escanear e priorizar o conteúdo mais facilmente.

:art: Design

Cartão

Os cartões são configurados com um raio de borda de 2px e usam um fundo de --secondary. Eles também têm uma borda sólida de 1px com --primary-low e 20px de preenchimento ao redor do conteúdo.

Variação padrão

Variação de acordeão

Design e uso

  • Agrupe informações relacionadas
  • Exiba informações para que administradores e moderadores vejam as coisas mais importantes primeiro
  • Use cabeçalhos que expliquem claramente para que serve o cartão
  • Divida os complicados em várias seções, se necessário

variação padrão

  • Mantenha uma chamada primária para ação por cartão
  • Coloque a chamada primária para ação na parte inferior do cartão para próximos passos

variação de acordeão

  • Use o canto superior direito do cartão para ações opcionais como “Ver tudo”

Conteúdo

  • Todos os formulários devem usar os componentes ember FormKit no núcleo descritos na documentação

  • Os cabeçalhos dos cartões devem estar em caixa de frases

    :white_check_mark: Faça :cross_mark: Não faça
    Configurações gerais Configurações Gerais
    Informações de contato INFORMAÇÕES DE CONTATO

:hammer_and_wrench: Implementação

Temos um componente AdminConfigAreaCard que deve ser usado para todos esses cartões. Por enquanto, isso só tem argumentos @translatedHeading e @heading, no futuro podemos adicionar ações e torná-los colapsáveis e assim por diante:

<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>

Configurações do site embutidas

Esta seção está em andamento.

5.c. Inserção de ajuda

Esta seção fornece orientação adicional, documentação ou contexto dentro do conteúdo da página.

v1

:art: Design

Design e uso

  • Mostre documentação ou guias relacionados ao conteúdo da página para fornecer informações úteis
  • Inclua um ícone no cabeçalho para torná-lo facilmente reconhecível
  • Coloque esta seção na área de layout secundário (1/3)

Conteúdo

  • Os cabeçalhos devem estar em caixa de frases

:hammer_and_wrench: Implementação

Fragmentos de código ou link para um tópico/GitHub

5.d. Tabela

As tabelas exibem informações em uma grade de células, colunas e linhas, facilitando para os administradores escanear rapidamente itens e tomar medidas.

:art: Design

Uso

  • Use tabelas para exibir conteúdo estruturado onde cada entrada compartilha os mesmos atributos.
  • Permita que os administradores revisem, habilitem/desabilitem, editem e excluam conjuntos de dados.
  • Adequado para conjuntos de dados que continuarão a crescer com o tempo.

Design

  • Use linhas horizontais entre as linhas para separar visualmente o conteúdo, incluindo a última linha. Evite usar bordas ou molduras ao redor da tabela para evitar que pareça uma rede.
  • Não aplique linhas verticais entre as colunas. Tabelas sem linhas verticais são geralmente mais fáceis de escanear e ler.

Ações adicionais

  • Ações de linha: Inclua ações adicionais na coluna mais à direita de cada linha da tabela.
    • Se houver dois ou mais elementos interativos, a ação primária (por exemplo, “Editar”) deve ser um botão de texto, e todas as outras ações de linha, incluindo “Excluir”, devem ser agrupadas em uma lista suspensa [...]. Ícones nos menus suspensos são encorajados para separar visualmente as coisas.
    • Se houver apenas uma ação “Excluir” e nenhuma ação primária, use um botão de texto “Excluir” em linha estilizado como btn-default.
    • Você deve envolver o texto da coluna principal (geralmente d-table__cell --overview) com um link levando o administrador diretamente à página Mostrar/Editar correspondente à linha para acesso rápido.
  • Confirmação de exclusão: Todos os botões “Excluir” devem mostrar uma confirmação antes de executar a ação.

Conteúdo

  • Cabeçalho: O cabeçalho da tabela é a linha superior que identifica as colunas abaixo. Ele fornece clareza, especialmente se os dados forem não descritivos ou ambíguos. Os cabeçalhos devem ser curtos, descritivos e relevantes, usando caixa de título. Evite cabeçalhos que sejam muito longos para o conteúdo nas linhas abaixo.
  • Colunas: Ordene as colunas por prioridade ou de uma maneira que conte uma história coerente com os dados. dimensione as colunas de acordo com seu conteúdo, com colunas estreitas para conteúdo pequeno e colunas mais largas para parágrafos.
  • Linhas: As linhas devem suportar texto, botões, links e ícones para aprimorar a apresentação de dados.
  • Sem dados: Listas vazias devem usar o componente AdminConfigAreaEmptyList com um botão CTA e rótulo para orientar o usuário a criar novos registros

:hammer_and_wrench: Implementação

Há uma pequena coleção de classes CSS que devem ser usadas com tabelas para fazê-las funcionar bem em dispositivos móveis e desktop.

Elementos <table> devem ter a classe d-table aplicada.

Elementos <thead> devem ter a classe d-table__header aplicada.

Elementos <tr> devem ter a classe d-table__row aplicada.

Elementos <td> contendo muito texto descritivo (geralmente a coluna mais à esquerda) devem usar as classes d-table__cell --overview. Todas as outras células devem usar d-table__cell --detail.

Elementos <td> com as classes d-table__cell --overview podem envolver o conteúdo interno da linha em um link levando o administrador diretamente à página Editar/Mostrar para a linha. Este link deve seguir esta estrutura e ter a classe CSS d-table__overview-link aplicada. Idealmente, o componente LinkTo deve ser usado, mas <a> também é aceitável, desde que getURL seja usado com ele.

A classe d-table__overview-name deve ser aplicada à parte do nome aqui, mas não à descrição.

<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>

Elementos <td> que envolvem os botões em cada linha devem ter as classes CSS d-table-cell --controls aplicadas. Isso garante que os botões estejam alinhados. Cada botão também deve ter a classe btn-small aplicada.

Para dispositivos móveis, cada elemento <td> exceto o d-table-cell --overview deve também incluir um <div> com a classe d-table__mobile-label, que contém um rótulo I18n que é o mesmo do <th> para essa coluna:

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

Isso exibe a linha da tabela em um formato baseado em cartões mais fácil de ler em dispositivos móveis:

Para menus suspensos [...], DMenu deve ser usado com DropdownMenu, aqui está um exemplo:

<DMenu
  @identifier="backup-item-menu"
  @title={{i18n "more_options"}}
  @icon="ellipsis-vertical"
  class="btn-small"
>
  <:content>
    <DropdownMenu as |dropdown|>
      <dropdown.item>
        <DButton ...[args do botão aqui] />
      </dropdown.item>
      <dropdown.item>
        <DButton ...[args do botão aqui] />
      </dropdown.item>
    </DropdownMenu>
  </:content>
</DMenu>

As alternâncias na linha da tabela são tratadas usando o componente DToggleSwitch:

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

Juntando tudo, aqui está um exemplo mínimo de uma tabela de administração:

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>Nome</th>
        <th>Descrição</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">Item de Exemplo</span>
            <span class="d-table__overview-about">Uma breve descrição</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">Descrição</span>
          Algum conteúdo detalhado aqui
        </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 Rota de terceiro nível

Uma rota de terceiro nível é aquela que só pode ser acessada a partir de uma área de configuração. Estas geralmente vêm na forma de rotas de edição/nova como esta para bandeiras:

É aqui que os formulários usando FormKit serão colocados na maioria dos casos.

Use as rotas RESTful padrão para estas:

Ação Caminho
Novo <recurso>/new
Editar <recurso>/:id/edit

e certifique-se de que as rotas também sejam roteadas no back-end. (Recarregar a página nova ou de edição não deve resultar em erro.)

:art: Design

Uso

  • Prefira ter essas rotas de terceiro nível em vez de ter formulários inline na rota principal ou dentro de uma tabela. Rotas de edição e nova independentes são as melhores, pois podem ser facilmente vinculadas.
  • Não mostre a parte superior da UI da página (migalhas, cabeçalho da página e subcabeçalho)
  • Em vez disso, mostre um único link “Voltar para X” que permita ao administrador chegar à área de configuração principal
  • O conteúdo da página deve ser envolvido em pelo menos um AdminConfigAreaCard
  • Quaisquer subtítulos na página devem ser feitos com cartões de área de configuração

:hammer_and_wrench: Implementação

Há um simples componente BackButton que pode ser usado no topo da página para voltar:

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

6. Páginas de configuração de configurações filtradas

Muitas de nossas páginas de configuração da interface de administração são listas simples de configurações do site filtradas. Isso permite que os administradores encontrem grupos relacionados de configurações sem serem sobrecarregados pela lista completa de “Todas as configurações do site”, até que criemos páginas de configuração mais especializadas como /admin/config/about/.

:hammer_and_wrench: Implementação

Há algumas coisas que você precisa adicionar a uma dessas rotas. Primeiro, você pode exibir uma category inteira de configurações do site que são as chaves de nível superior em site_settings.yml (por exemplo, branding:), ou você pode usar uma area de configuração.

As configurações do site podem viver em várias areas, e você pode exibir uma ou mais na mesma página.

  1. Adicione uma rota ao mapa de rotas de administração abaixo de adminConfig, por exemplo:
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. Adicione um novo arquivo .js de rota, o arquivo corresponderá a um caminho como frontend/discourse/admin/routes/admin-config/localization.js dependendo do nome da sua nova rota. Isso deve herdar de AdminConfigWithSettingsRoute e incluir um 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. Adicione um controlador, isso é principalmente para habilitar a pesquisa e filtragem de configurações. Deve herdar de AdminAreaSettingsBaseController:
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. Finalmente, adicione um arquivo de modelo de rota no formato .gjs, em um caminho como frontend/discourse/admin/templates/admin-config/localization/settings.gjs. Isso deve conter o DPageHeader e migalhas normais, mas para exibir as configurações você precisa de AdminAreaSettings.
<div class="admin-config-page__main-area">
  <AdminAreaSettings
    @showBreadcrumb={{false}}
    @area="localization"
    @path="/admin/config/localization"
    @filter={{@controller.filter}}
    @adminSettingsFilterChangedCallback={{@controller.adminSettingsFilterChangedCallback}}
  />
</div>

As coisas importantes a mudar aqui são o @path e @area (ou alternativamente use @categories). Como mencionado anteriormente, preencha isso com a área de configuração do site que você deseja exibir, ou as categorias.

7. Orientação geral

  • Os slugs de URL devem usar hífens (-) para indicar espaços em palavras, em vez de underscores (_).

  • Todo o texto nas interfaces de administração deve seguir as diretrizes de formatação de texto descritas aqui:

8. Plugins

Alguns plugins precisam de uma UI de configuração aprofundada para seu plugin (por exemplo, AI, Automação, Gamificação) em vez de apenas ter uma coleção de configurações do site. Por exemplo, aqui está o Discourse AI:

Alguns exemplos de plugins usando isso são:

:art: Design

Uso

  • As diretrizes gerais da UI de administração devem ser seguidas ao criar UIs de plugin independentes.

:hammer_and_wrench: Implementação

Roteamento Ember

  • Todos os modelos de rota estarão sob
    admin/assets/javascripts/discourse/templates/admin-plugins/show/
  • Todos os arquivos js de rota estarão sob admin/assets/javascripts/discourse/routes/ e
    prefixados com admin-plugins-show-
  • O mapa de rotas de administração deve estar em um arquivo como admin-NOME-DO-PLUGIN-plugin-route-map.js
  • O mapa de rotas deve ter uma estrutura como esta. A parte importante é 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" });
    });
  },
};
  • O exemplo atual de como tudo isso funciona é visto no plugin Discourse AI, se você for para /admin/plugins/discourse-ai/ai-personas
  • Se você tiver apenas uma rota de “nível superior”, por exemplo, uma que não define sub-rotas, então o caminho do modelo será algo como admin/assets/javascripts/discourse/templates/admin-plugins/show/seu-nome-de-rota.gjs. Se houver sub-rotas, então você entra no território de precisar de modelos index.gjs, show.gjs e new.gjs e assim por diante.

Navegação

Os plugins podem mostrar sua navegação em uma barra lateral interna, ou na barra de navegação por abas no topo. Esta última é altamente recomendada, e no futuro o suporte à barra lateral interna pode ser descartado.

Lado do Servidor

  • add_admin_route ainda é usado para mostrar as rotas de administração personalizadas na barra lateral de administração e do índice /plugins com as abas ao longo do topo. Basicamente, isso define a página raiz da UI do seu plugin.
    • use_new_show_route: true deve ser passado como um argumento adicional aqui para que a nova página de exibição do plugin seja usada.

Convenções de UI

  • Cada rota de índice para o plugin deve exibir um componente DPageSubheader para descrever a intenção dessa rota e adicionar quaisquer botões de ação relacionados.
  • Botões de ação que precisam ser renderizados no cabeçalho principal da página do plugin devem usar o outlet admin-plugin-config-page-actions com um componente dedicado. O melhor lugar para fazer isso é no mesmo inicializador onde addAdminPluginConfigurationNav é usado.
    • plugin e actions são passados como outletArgs. plugin é a representação do modelo do plugin atual, então o nome do plugin e outras coisas podem ser acessados, actions são os componentes de botão de ação renderizados de DPageHeader.
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

Tópicos relacionados:

10 Curtiram

E

ainda não funcionam. Acho que o segundo é -23 em vez de -24

5 Curtiram

Tão feliz em finalmente ver isso no meta. Meses de trabalho foram dedicados a isso, e vamos usá-lo para padronizar a UI e a navegação de todas as páginas na interface de administração.

Deveríamos talvez apenas remover essa tabela de conteúdos e confiar no discotoc em vez disso? Acho que seria menos frágil, embora eu goste de ver a tabela de conteúdos no topo da postagem.

7 Curtiram

Obrigado @Moin - tudo corrigido!

Fiz essa alteração, caso contrário, é simplesmente uma tabela de conteúdos duplicada.

4 Curtiram

Uma postagem foi dividida em um novo tópico: Exibir nome de usuário na aba do navegador ao acessar o admin do usuário