Créer des interfaces d'administration cohérentes

Ces lignes directrices visent à créer une interface d’administration cohérente, en mettant l’accent sur l’utilisabilité, l’accessibilité et une mise en page structurée. Consultez la table des matières pour voir ce qui est inclus et pour naviguer facilement vers chaque section.

Remarque : La terminologie utilisée ici est définie dans le glossaire de l’interface d’administration.

0. Préface - Structure des pages de configuration et liens de la barre latérale

Lors de l’ajout de nouvelles pages de configuration dans l’interface d’administration, chaque page aura besoin d’un lien pour la barre latérale, et chaque page aura besoin à la fois d’un titre et d’une description d’en-tête. Cela permet de maintenir une cohérence partout, et les améliorations futures de la recherche d’administration peuvent afficher la structure complète de l’interface d’administration.

En général, la structure de l’interface d’administration ressemble à ceci :

  • Interface d’administration
    • Page de configuration (affichée dans la barre latérale)
      • Onglet Paramètres
      • Autres onglets de troisième niveau en option
        • Page de troisième niveau Éditer/Nouveau pour les ressources

Éventuellement, un “aperçu de la section” sera inséré entre l’interface racine et les pages de configuration.

Liens de la barre latérale

Toutes les pages d’administration doivent être ajoutées à ADMIN_NAV_MAP dans discourse/frontend/discourse/app/lib/sidebar/admin-nav-map.js at main · discourse/discourse · GitHub . Chaque élément doit avoir au moins ces clés :

  • name - Un identifiant unique pour le lien, doit être en snake_case
  • route OU href - Le route est un identifiant de route Ember, comme adminUsers. Pour les administrateurs, ceux-ci sont définis dans la carte des routes d’administration . Un href peut être utilisé à la place, mais route est préféré.
  • label OU text - Label est une clé I18n, qui doit généralement être admin.config.page_name.title (voir la section traductions ci-dessous). Si text est utilisé, il s’agira de texte déjà traduit.

Ces clés optionnelles peuvent également être fournies :

  • description - Il est recommandé de la fournir également. C’est une clé I18n, elle doit généralement être admin.config.page_name.header_description.
  • icon - Également recommandé, cela est affiché à côté du lien dans la barre latérale.
  • routeModels - Tableau de données URL pour le cas des paramètres de route. Par exemple, adminCustomizeThemes a un paramètre de route :type, donc vous pouvez passer routeModels: ["components"]. Les éléments du tableau sont utilisés dans le même ordre que l’apparition des paramètres de route.
  • moderator : Définissez ceci sur true si les modérateurs doivent voir cette page dans la barre latérale.
  • keywords : Une clé I18n, avec une liste de mots-clés séparés par | pour le lien de la barre latérale, utilisée pour un “poids de recherche” supplémentaire lors du filtrage/recherche de pages.
  • links : Une liste de routes de 3ème niveau qui se trouvent sous la page dans la barre latérale. Ceux-ci ne sont pas affichés dans la barre latérale elle-même. Cela sera utilisé pour les futures fonctionnalités de recherche d’administration.
  • settings_area et settings_category : Si la page affiche uniquement une liste de paramètres de site filtrés, alors l’un de ceux-ci doit être rempli. Si le paramètre de site a une area définie, qui est utilisée dans AdminAreaSettings, alors settings_area doit être utilisé. Si une catégorie entière de paramètres est affichée sur la page, et également utilisée sur AdminAreaSettings, alors settings_category doit être utilisé.
  • multi_tabbed : Si la page a un onglet de paramètres et d’autres onglets, alors cela doit être défini sur true. Cela aide à générer des liens pour le système de recherche d’administration.

Traductions

Le titre et la description d’en-tête pour chaque page de configuration doivent être sous :

  • admin
    • config
      • page_name
        • title : “Titre de la page”
        • header_description : “Cette page est pour xyz”

Vous pouvez voir des exemples de ceci ici :

1. Fil d’Ariane (Breadcrumbs)

Le fil d’Ariane sert d’outil de navigation, aidant les utilisateurs à comprendre leur emplacement actuel, la structure du contenu et la hiérarchie au sein de l’interface d’administration.

Admin > Fil d’Ariane > Chemin
Titre de la page

:art: Conception

Structure

  1. Admin : préfixe fixe qui apparaît au début de chaque fil d’Ariane, liant à /admin
  2. Lien : ouvre la page dans la même fenêtre
  3. Séparateur : une icône angle-right sépare chaque lien

Utilisation

Quand utiliser :

  • Présent sur chaque page d’administration
  • Situé au-dessus du contenu (titre, description, onglets)
  • Affiche la page actuellement sélectionnée

Quand ne pas utiliser :

  • Lors de la visite d’une nouvelle route ou d’une route d’édition

Contenu

  • Chaque élément inclut un lien vers sa page associée
  • Affiche la page actuellement sélectionnée

Accessibilité

  • Un élément nav avec aria-label="Breadcrumb" entoure une liste ordonnée pour fournir un repère de navigation
  • Appliquez aria-current="page" sur le dernier lien pour indiquer qu’il s’agit de la page actuelle
  • Pour plus de détails, voir Exemple de fil d’Ariane des pratiques d’auteur WAI-ARIA

:hammer_and_wrench: Implémentation

Le composant DBreadcrumbsContainer doit être placé quelque part sur la page :

<DBreadcrumbsContainer />

Ensuite, chaque élément DBreadcrumbsItem ajouté à un composant sur une route ou une route enfant sera rendu dans ce conteneur. Chaque DBreadcrumbsItem a un @label et un @path qui doivent être fournis :

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

Comment cela ressemble avec un exemple visuel, en utilisant le plugin Discourse AI :

2. En-tête de page et titre

La section supérieure d’une page d’administration, contenant le titre de la page, ainsi que des actions et une description en option.

:art: Conception

Structure

  • Titre de la page : Titre de la page

  • Description de la page : Introduction ou description de ce que couvre le contenu (en option)

  • Action principale : Action principale du titre de la page (en option)

  • Action secondaire : Paramètres du bouton d’action secondaire du titre de la page (en option)

Utilisation et contenu

  • Titre de la page : Utilisez le niveau de titre 1 pour expliquer le sujet principal de la page en casse de phrase. Habituellement, la traduction I18n doit être sous admin.config.your_page.title.

  • Description de la page : Prend en charge les nœuds Markdown de base tels que _italique_, **gras**, et [nom du lien](url)

  • Action principale : Utilisez btn-primary. N’incluez pas d’icône. Habituellement, la traduction I18n doit être sous admin.config.your_page.header_description.

  • Action secondaire : Utilisez les paramètres de bouton btn-default, visibles uniquement si une action principale existe. N’incluez pas d’icône.

    :point_right: Soyez clair avec les boutons d’action. Par exemple, utilisez des libellés descriptifs comme “Ajouter un emoji” au lieu de simplement “Ajouter” pour réduire l’ambiguïté.

:hammer_and_wrench: Implémentation

Le composant DPageHeader est utilisé ici. Cela accepte des arguments pour @titleLabel, @descriptionLabel, @learnMoreUrl, et @shouldDisplay. Cela utilise des yields nommés dans Ember pour fournir 5 blocs nommés pour le contenu :

  1. breadcrumbs - Tous les composants DBreadcrumbsItem supplémentaires pour la page doivent être placés ici.
  2. actions - Utilisé pour définir les boutons à droite du titre. Cela rend un objet appelé actions qui peut être utilisé pour rendre des boutons Default, Primary, Danger, et Wrapped.
  3. title - Une alternative à @titleLabel, permettant un balisage personnalisé à l’intérieur du titre.
  4. drawer - Une section tiroir rétractable en option, affichée lorsque @showDrawer est true.
  5. tabs - Utilisé pour définir les onglets de la page en utilisant des composants NavItem. @hideTabs peut être utilisé pour supprimer cette partie de l’en-tête si elle n’est pas nécessaire.

Un exemple complet est ci-dessous :

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

Les titres de page pour l’onglet du navigateur sont gérés dans les routes Ember en utilisant la fonctionnalité titleToken. Chaque fois que cela est utilisé dans une route, il ajoute le jeton à la fin du titre de l’onglet du navigateur. Sachez que vous devez utiliser la classe DiscourseRoute pour étendre votre route, et non la Route normale d’ember pour que cela fonctionne :

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

:point_right: L’en-tête de page est automatiquement masqué pour les chemins /new et /edit pour prendre en charge les routes de troisième niveau. Cela peut être annulé en utilisant l’argument @shouldDisplay.

3. Onglets

Une navigation en option qui fournit un accès à des niveaux plus profonds de paramètres ou de fonctionnalités. Nous appelons également cela des pages ou navigations de “troisième niveau”.

:art: Conception

Nous utilisons des onglets pour basculer entre différentes vues liées dans le même contexte.

Utilisation

  • Non utilisé pour la navigation principale
  • Un seul actif à la fois

:hammer_and_wrench: Implémentation

Voir les détails de l’En-tête de page, les onglets sont définis dans le composant 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. Page d’accueil Aperçu/section

Permet aux utilisateurs de voir le contenu d’une section, en particulier lorsque la barre latérale est réduite ou sur mobile.

:art: Conception

Structure
Utilisez une mise en page à trois colonnes égales en utilisant un système de grille. Sur les petits écrans, ces colonnes s’empileront verticalement.

Conception et utilisation

  • Peut être accédé via le fil d’Ariane (Admin > Communauté > Aperçu)
  • Chaque section doit en avoir une, à l’exception des plugins (qui montrent les installés) et des rapports (une seule page)
  • L’élément a un :
    • nom - même que le lien de la section
    • description - une courte description de ce dont il s’agit la page
    • icône - même icône utilisée pour la barre latérale

:hammer_and_wrench: Implémentation

Extraits de code ou lien vers un sujet/GitHub

5. Contenu de la page

La zone principale d’une page d’administration où les paramètres, les configurations et autres contenus sont affichés et avec lesquels on interagit.

:art: Conception

Structure
Utilisez une mise en page 2/3 + 1/3 en utilisant un système de grille. La section principale occupe deux tiers et la section secondaire occupe un tiers de l’espace. Sur les petits écrans, ces colonnes s’empileront verticalement.

  • Zone de configuration : Une section spécifique au sein du contenu de la page dédiée aux paramètres et configurations.
  • Aide/référence/incrustation : Une zone au sein du contenu de la page fournissant des guides, de la documentation ou des informations contextuelles supplémentaires. (en option)

Conception et utilisation

  • Regroupez les paramètres et actions similaires dans des cartes
  • Structurez les mises en page primaire/secondaire de sorte que la section primaire (2/3) soit utilisée pour les paramètres principaux, et la section secondaire (1/3) pour des informations supplémentaires ou un contexte utile
  • Si la section secondaire n’est pas disponible, maintenez la largeur de la section primaire identique

Contenu

:hammer_and_wrench: Implémentation

Extraits de code ou liens GitHub

5.a. Sous-titre

Un sous-titre est un titre secondaire utilisé pour diviser le contenu sous une section, généralement sous les onglets.

Structure

  • Sous-titre : Sous-titre de ce que couvre le contenu (en option)
  • Action principale : Action principale du sous-titre (en option)
  • Action secondaire : Paramètres du bouton d’action secondaire du sous-titre (en option)

Utilisation et contenu

  • Sous-titre : Utilisez le niveau de titre 2 pour expliquer le sujet principal du contenu associé. Incluez uniquement si :

    • Il y a un bouton d’action principal, ou
    • Il y a une description expliquant la section.
  • Action principale : Utilisez btn-primary. N’incluez pas d’icône.

  • Action secondaire : Utilisez les paramètres de bouton btn-default, visibles uniquement si une action principale existe. N’incluez pas d’icône.

    :point_right: Soyez clair avec les boutons d’action. Par exemple, utilisez des libellés descriptifs comme “Ajouter un emoji” au lieu de simplement “Ajouter” pour réduire l’ambiguïté.

:hammer_and_wrench: Implémentation

Ceci est similaire à DPageHeader, il y a un composant DPageSubheader. La principale différence est qu’il n’y a qu’un seul yield nommé pour actions.

  1. actions - Utilisé pour définir les boutons à droite du titre. Cela rend un objet appelé actions qui peut être utilisé pour rendre des boutons Default, Primary, Danger, et 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. Zone de configuration

La zone de configuration est composée de cartes ou de sections. Les cartes sont excellentes pour regrouper les informations et tâches liées, aidant les utilisateurs à scanner et à prioriser le contenu plus facilement.

:art: Conception

Carte

Les cartes sont configurées avec un rayon de bordure de 2px et utilisent un arrière-plan de --secondary. Elles ont également une bordure solide de 1px avec --primary-low et un remplissage de 20px autour du contenu.

Variation par défaut

Variation Accordéon

Conception et utilisation

  • Regroupez les informations liées
  • Affichez les informations de sorte que les administrateurs et modérateurs voient les éléments les plus importants en premier
  • Utilisez des titres qui expliquent clairement à quoi sert la carte
  • Divisez les complexes en plusieurs sections, si nécessaire

variation par défaut

  • Limitez-vous à un appel à l’action principal par carte
  • Placez l’appel à l’action principal en bas de la carte pour les étapes suivantes

variation accordéon

  • Utilisez le coin supérieur droit de la carte pour les actions en option comme “Voir tout”

Contenu

  • Tous les formulaires doivent utiliser les composants ember FormKit dans le noyau décrits dans la documentation

  • Les en-têtes de carte doivent être en casse de phrase

    :white_check_mark: Faire :cross_mark: Ne pas faire
    Paramètres généraux Paramètres Généraux
    Informations de contact INFORMATIONS DE CONTACT

:hammer_and_wrench: Implémentation

Nous avons un composant AdminConfigAreaCard qui doit être utilisé pour toutes ces cartes. Pour l’instant, cela n’a que les arguments @translatedHeading et @heading, à l’avenir nous pouvons ajouter des actions et les rendre rétractables, 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>

Paramètres de site intégrés

Cette section est en cours de réalisation.

5.c. Incrustation d’aide

Cette section fournit des conseils, de la documentation ou un contexte supplémentaires au sein du contenu de la page.

v1

:art: Conception

Conception et utilisation

  • Affichez la documentation ou les guides liés au contenu de la page pour fournir des informations utiles
  • Incluez une icône dans l’en-tête pour le rendre facilement reconnaissable
  • Placez cette section dans la zone de mise en page secondaire (1/3)

Contenu

  • Les en-têtes doivent être en casse de phrase

:hammer_and_wrench: Implémentation

Extraits de code ou lien vers un sujet/GitHub

5.d. Tableau

Les tableaux affichent les informations dans une grille de cellules, colonnes et lignes, permettant aux administrateurs de scanner rapidement les éléments et de prendre des mesures.

:art: Conception

Utilisation

  • Utilisez des tableaux pour afficher du contenu structuré où chaque entrée partage les mêmes attributs.
  • Permettez aux administrateurs de revoir, activer/désactiver, éditer et supprimer des ensembles de données.
  • Convient aux ensembles de données qui continueront à croître avec le temps.

Conception

  • Utilisez des lignes horizontales entre les lignes pour séparer visuellement le contenu, y compris la dernière ligne. Évitez d’utiliser des bordures ou des cadres autour du tableau pour éviter qu’il ne ressemble à un filet.
  • N’appliquez pas de lignes verticales entre les colonnes. Les tableaux sans lignes verticales sont généralement plus faciles à scanner et à lire.

Actions supplémentaires

  • Actions de ligne : Incluez des actions supplémentaires dans la colonne la plus à droite de chaque ligne de tableau.
    • S’il y a deux éléments interactifs ou plus, l’action principale (par exemple, “Éditer”) doit être un bouton texte, et toutes les autres actions de ligne, y compris “Supprimer”, doivent être regroupées dans un menu déroulant [...]. Les icônes dans les menus déroulants sont encouragées pour diviser visuellement les éléments.
    • S’il n’y a qu’une action “Supprimer” et aucune action principale, utilisez un bouton texte “Supprimer” en ligne stylisé comme btn-default.
    • Vous devez envelopper le texte de la colonne principale (généralement d-table__cell --overview) avec un lien dirigeant l’administrateur directement vers la page Afficher/Éditer correspondant à la ligne pour un accès rapide.
  • Confirmation de suppression : Tous les boutons “Supprimer” doivent afficher une confirmation avant d’exécuter l’action.

Contenu

  • En-tête : L’en-tête du tableau est la ligne supérieure qui identifie les colonnes ci-dessous. Il apporte de la clarté, surtout si les données sont non descriptives ou ambiguës. Les en-têtes doivent être courts, descriptifs et pertinents, en utilisant la casse de titre. Évitez les en-têtes trop longs par rapport au contenu des lignes ci-dessous.
  • Colonnes : Ordonnez les colonnes par priorité ou d’une manière qui raconte une histoire cohérente avec les données. Dimensionnez les colonnes selon leur contenu, avec des colonnes étroites pour le petit contenu et des colonnes plus larges pour les paragraphes.
  • Lignes : Les lignes doivent prendre en charge le texte, les boutons, les liens et les icônes pour améliorer la présentation des données.
  • Aucune donnée : Les listes vides doivent utiliser le composant AdminConfigAreaEmptyList avec un bouton CTA et un libellé pour guider l’utilisateur vers la création de nouveaux enregistrements

:hammer_and_wrench: Implémentation

Il existe une petite collection de classes CSS qui doivent être utilisées avec les tableaux pour qu’ils fonctionnent bien sur mobile et desktop.

Les éléments <table> doivent avoir la classe d-table appliquée.

Les éléments <thead> doivent avoir la classe d-table__header appliquée.

Les éléments <tr> doivent avoir la classe d-table__row appliquée.

Les éléments <td> contenant beaucoup de texte descriptif (généralement la colonne la plus à gauche) doivent utiliser les classes d-table__cell --overview. Toutes les autres cellules doivent utiliser d-table__cell --detail.

Les éléments <td> avec les classes d-table__cell --overview peuvent envelopper le contenu interne de la ligne dans un lien dirigeant l’administrateur directement vers la page Éditer/Afficher pour la ligne. Ce lien doit suivre cette structure et avoir la classe CSS d-table__overview-link appliquée. Idéalement, le composant LinkTo doit être utilisé, mais <a> va aussi bien que getURL est utilisé avec.

La classe d-table__overview-name doit être appliquée à la partie nom ici, mais pas à la description.

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

Les éléments <td> qui enveloppent les boutons sur chaque ligne doivent avoir les classes CSS d-table-cell --controls appliquées. Cela assure l’alignement des boutons. Chaque bouton doit également avoir la classe btn-small appliquée.

Pour mobile, chaque élément <td> sauf le d-table-cell --overview doit également inclure un <div> avec la classe d-table__mobile-label, qui contient un libellé I18n qui est le même que celui dans le <th> pour cette colonne :

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

Cela affiche la ligne du tableau dans un format basé sur des cartes plus facile à lire sur mobile :

Pour les menus déroulants [...], DMenu doit être utilisé avec DropdownMenu, voici un exemple :

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

Les bascules dans la ligne du tableau sont gérées en utilisant le composant DToggleSwitch :

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

En mettant tout cela ensemble, voici un exemple minimal d’un tableau d’administration :

 <table class="d-table">
    <thead class="d-table__header">
      <tr>
        <th>Nom</th>
        <th>Description</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">Exemple d'élément</span>
            <span class="d-table__overview-about">Une courte description</span>
          </LinkTo>
        </td>
        <td class="d-table__cell --detail">
          <span class="d-table__mobile-label">Description</span>
          Du contenu détaillé ici
        </td>
        <td class="d-table__cell --controls">
          <div class="d-table__cell-actions">
            <button class="btn btn-default btn-small">Éditer</button>
          </div>
        </td>
      </tr>
    </tbody>
  </table>

5.e Route de troisième niveau

Une route de troisième niveau est une route qui ne peut être atteinte que depuis une zone de configuration. Ceux-ci prennent généralement la forme de routes éditer/nouveau comme celle-ci pour les drapeaux :

C’est là que les formulaires utilisant FormKit seront placés dans la plupart des cas.

Utilisez les routes RESTful standard pour celles-ci :

Action Chemin
Nouveau <resource>/new
Éditer <resource>/:id/edit

et assurez-vous que les routes sont également acheminées dans le back-end. (Le rechargement de la page nouvelle ou édition ne doit pas entraîner une erreur.)

:art: Conception

Utilisation

  • Préférez avoir ces routes de troisième niveau plutôt que d’avoir des formulaires en ligne sur la route principale ou dans un tableau. Les routes d’édition et de création autonomes sont les meilleures, car elles peuvent facilement être liées.
  • N’affichez pas la partie supérieure de l’interface utilisateur de la page (fil d’Ariane, en-tête de page et sous-en-tête)
  • Au lieu de cela, affichez un seul lien “Retour à X” qui permet à l’administrateur d’accéder à la zone de configuration principale
  • Le contenu de la page doit être enveloppé dans au moins un AdminConfigAreaCard
  • Tous les sous-titres sur la page doivent être faits avec des cartes de zone de configuration

:hammer_and_wrench: Implémentation

Il y a un simple composant BackButton qui peut être utilisé en haut de la page pour revenir en arrière :

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

6. Pages de configuration de paramètres filtrés

Beaucoup de nos pages de configuration d’interface d’administration sont de simples listes de paramètres de site filtrés. Cela permet aux administrateurs de trouver des groupes de paramètres liés sans être submergés par la liste complète de “Tous les paramètres de site”, jusqu’à ce que nous créions des pages de configuration plus spécialisées comme /admin/config/about/.

:hammer_and_wrench: Implémentation

Il y a quelques choses que vous devez ajouter pour l’une de ces routes. D’abord, vous pouvez soit afficher une category entière de paramètres de site qui sont les clés de premier niveau dans site_settings.yml (par exemple branding:), ou vous pouvez utiliser une area de paramètre.

Les paramètres de site peuvent vivre dans plusieurs areas, et vous pouvez afficher une ou plusieurs sur la même page.

  1. Ajoutez une route à la carte des routes d’administration sous adminConfig, par exemple :
this.route("trustLevels", { path: "/trust-levels" }, function () {
  this.route("settings", {
    path: "/",
  });
});
  1. Ajoutez un nouveau fichier de route .js, le fichier correspondra à un chemin comme frontend/discourse/admin/routes/admin-config/localization.js selon le nom de votre nouvelle route. Cela doit hériter de AdminConfigWithSettingsRoute et inclure 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. Ajoutez un contrôleur, cela est principalement pour activer la recherche et le filtrage des paramètres. Il doit hériter de AdminAreaSettingsBaseController :
import AdminAreaSettingsBaseController from "discourse/admin/controllers/admin-area-settings-base";

export default class AdminConfigLocalizationSettingsController extends AdminAreaSettingsBaseController {}
  1. Enfin, ajoutez un fichier de modèle de route au format .gjs, à un chemin comme frontend/discourse/admin/templates/admin-config/localization/settings.gjs. Cela doit contenir le DPageHeader et le fil d’Ariane normaux, mais pour afficher les paramètres, vous avez besoin 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>

Les choses importantes à changer ici sont @path et @area (ou alternativement utiliser @categories). Comme mentionné précédemment, remplissez ceci avec soit la zone de paramètre de site que vous souhaitez afficher, soit les catégories.

7. Lignes directrices générales

  • Les slugs d’URL doivent utiliser des tirets (-) pour indiquer les espaces dans les mots, plutôt que des underscores (_).

  • Tout le texte dans les interfaces d’administration doit suivre les lignes directrices de formatage de texte décrites ici :

8. Plugins

Certains plugins ont besoin d’une interface de configuration approfondie pour leur plugin (par exemple AI, Automation, Gamification) plutôt que d’avoir uniquement une collection de paramètres de site. Par exemple, voici Discourse AI :

Quelques exemples de plugins utilisant ceci sont :

:art: Conception

Utilisation

  • Les lignes directrices générales de l’interface utilisateur d’administration doivent être suivies lors de la création d’interfaces utilisateur de plugin indépendantes.

:hammer_and_wrench: Implémentation

Routage Ember

  • Tous les modèles de route seront sous
    admin/assets/javascripts/discourse/templates/admin-plugins/show/
  • Tous les fichiers js de route seront sous admin/assets/javascripts/discourse/routes/ et
    préfixés par admin-plugins-show-
  • La carte des routes d’administration doit être dans un fichier comme admin-NOM-PLUGIN-plugin-route-map.js
  • La carte des routes doit avoir une structure comme celle-ci. La partie importante est que
    nous utilisons admin.adminPlugins.show comme 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" });
    });
  },
};
  • L’exemple actuel de comment tout cela fonctionne est vu dans le plugin Discourse AI, si vous allez à /admin/plugins/discourse-ai/ai-personas
  • Si vous n’avez qu’une route “de premier niveau”, par exemple une qui ne définit pas de sous-routes, alors le chemin du modèle sera quelque chose comme admin/assets/javascripts/discourse/templates/admin-plugins/show/your-route-name.gjs. S’il y a des sous-routes, alors vous entrez dans le territoire nécessitant des modèles index.gjs, show.gjs, et new.gjs, etc.

Navigation

Les plugins peuvent soit afficher leur navigation dans une barre latérale intérieure, soit sur la barre de navigation à onglets en haut. Ce dernier est fortement recommandé, et à l’avenir, la prise en charge de la barre latérale intérieure peut être abandonnée.

  • Tous les liens qui seront affichés soit dans la barre supérieure soit dans la barre latérale intérieure pour
    la page d’affichage du plugin doivent être définis dans un initialiseur (par exemple
    assets/javascripts/initializers/admin-plugin-configuration-nav.js) en utilisant
    api.addAdminPluginConfigurationNav . Les liens ont besoin d’un label, route, et description (qui est utilisé pour la recherche d’administration)
  • Cet initialiseur ne doit s’exécuter que si l’utilisateur est administrateur.
  • Le lien des paramètres de site pour le plugin est généré automatiquement, pas besoin de l’inclure ici.
  • Un exemple peut être vu ici discourse-ai/assets/javascripts/initializers/admin-plugin-configuration-nav.js at ab4544d8977ec0e9d6aa42b4551df8317aa9b365 · discourse/discourse-ai · GitHub .

Côté Serveur

  • add_admin_route est toujours utilisé pour afficher les routes d’administration personnalisées dans la barre latérale d’administration et depuis l’index /plugins avec les onglets en haut. En gros, cela définit la page racine de votre interface utilisateur de plugin.
    • use_new_show_route: true doit être passé comme argument supplémentaire ici pour que la nouvelle page d’affichage du plugin soit utilisée.

Conventions UI

  • Chaque route d’index pour le plugin doit afficher un composant DPageSubheader pour décrire l’intention de cette route et pour ajouter tous les boutons d’action associés.
  • Les boutons d’action qui doivent être rendus dans l’en-tête de la page principale du plugin doivent utiliser la sortie admin-plugin-config-page-actions avec un composant dédié. Le meilleur endroit pour faire cela est dans le même initialiseur où addAdminPluginConfigurationNav est utilisé.
    • plugin et actions sont passés comme outletArgs. plugin est la représentation du modèle du plugin actuel, donc le nom du plugin et d’autres choses peuvent être accédés, actions sont les composants de boutons d’action rendus depuis DPageHeader.
api.renderInOutlet(
  "admin-plugin-config-page-actions",
  ChatAdminPluginActions
);

Sujets connexes :

10 « J'aime »

Et

ne fonctionnent toujours pas. Je pense que le second est -23 au lieu de -24.

5 « J'aime »

Ravi de voir enfin cela sur meta. Des mois de travail y ont été consacrés, et nous allons l’utiliser pour standardiser l’interface utilisateur et la navigation de chaque page de l’interface d’administration.

Devrions-nous peut-être simplement supprimer cette table des matières et nous fier à discotoc à la place ? Je pense que ce serait moins fragile, bien que j’aime voir la table des matières en haut de la publication.

7 « J'aime »

Merci @Moin - tout est réparé !

J’ai apporté cette modification, sinon c’est simplement une table des matières dupliquée.

4 « J'aime »

Un message a été divisé en un nouveau sujet : Afficher le nom d’utilisateur dans l’onglet du navigateur lors de l’administration des utilisateurs