Capacité d'ajouter une section personnalisée de liens à la barre latérale

Nous voulons permettre aux utilisateurs d’ajouter une section personnalisée de liens à leur barre latérale.

Dans une première passe pour cette fonctionnalité, nous prévoyons de nous appuyer sur la page existante des préférences de la barre latérale et de permettre à un utilisateur d’ajouter une seule section personnalisée pour ces liens.

Nous pensons que cela pourrait fonctionner à peu près comme suit :

  1. case à cocher pour « Afficher la section personnalisée ».
    Si elle est cochée, la Section personnalisée apparaît au-dessus de la Section des catégories et les valeurs doivent avoir un Nom valide et au moins un Lien valide pour « Enregistrer les modifications ».
  2. zone de texte pour le Nom de la section personnalisée (par défaut : Mes liens, ne peut pas être vide)
  3. bouton pour « Ajouter un lien ». lorsqu’il est cliqué, afficher la boîte de dialogue pour ajouter un lien
  4. les liens ajoutés montrent un bouton pour les supprimer

Boîte de dialogue Ajouter un lien

  1. La boîte de dialogue Ajouter un lien a deux zones de texte : Nom, URL
  2. Le nom ne peut pas être vide, peut inclure des emoji (qui devraient être rendus dans la barre latérale)
  3. L’URL doit être un lien vers le même site Discourse*.
  4. Enregistrer ajoute le lien, Annuler le rejette

Lorsqu’une section personnalisée valide est configurée et enregistrée, la barre latérale affichera cette section au-dessus de « Catégories ».

* Pourquoi ?

  1. Nous aimerions pouvoir « mettre en surbrillance » / « mettre en gras » le lien dans la barre latérale lorsque vous êtes sur la page correspondante.
  2. Nous aimerions stocker la partie « chemin », afin que les renommages de site fonctionnent comme prévu.

Nous pensons que l’ajout de liens aujourd’hui sera précieux car il permettra aux gens d’accéder facilement à des éléments tels que « Bugs ouverts de la barre latérale » et nous permettra de tirer parti des futures améliorations pour les listes de sujets, telles que des filtres de liste de sujets améliorés. Tant que les éléments ont une URL, les gens peuvent les ajouter à leur barre latérale.

Nous pensons que les utilisateurs voudront pouvoir ajouter plusieurs sections et les réorganiser, mais nous laisserons cela hors de portée initialement.

16 « J'aime »

Une question à ce sujet, @mcwumbly. Cela ressemble à une stratégie pour permettre à un utilisateur d’ajouter des liens personnels à la barre latérale. Cette approche permettrait-elle aux propriétaires de sites d’ajouter des liens que tous les utilisateurs verraient ?

Spoiler - Je pense que oui. :slight_smile:

5 « J'aime »

Ouais, je pense que ça pourrait certainement être étendu pour faire quelque chose comme ça, et je vois comment ce serait une fonctionnalité plus utile pour certains sites que celle de l’utilisateur.

8 « J'aime »

J’aime beaucoup cette idée. :+1:

Juste quelques questions :

  1. Y aura-t-il une limite au nombre de liens personnalisés qu’un utilisateur sera autorisé à ajouter ?

  2. La fin des liens (dans la barre latérale) sera-t-elle tronquée comme dans la maquette suivante ? (Cela me conviendrait).
    Et s’ils le seront, l’utilisateur pourra-t-il lire leur texte en entier dans une infobulle (si le curseur de la souris survole les liens) ?

Bonne question. Nous aurons probablement besoin de certaines limites, mais ce n’est pas quelque chose dont nous avons discuté en détail. Quel genre de limites espérez-vous voir (ou éviter) ?

1 « J'aime »

Au début, je pensais que 10 liens pourraient suffire, mais je suppose que d’autres membres du forum en voudront plus. Peut-être 20. C’est pourquoi j’essaierais avec 20 et j’attendrais les commentaires des utilisateurs pour voir s’ils en demandent plus (mais je pense que 20 est déjà un bon nombre).

1 « J'aime »

Pour étendre la « convivialité » de cette fonctionnalité, ce serait vraiment bien de permettre à l’utilisateur de faire glisser et déposer des liens (n’importe quel lien de la page Discourse actuelle) directement dans la barre latérale.

Un pointeur (entre les liens qui ont été précédemment ajoutés à la DIV « Mes liens ») indiquerait où le lien serait placé.

Maquette (clic droit > « ouvrir l’image dans un nouvel onglet » pour voir l’animation en taille réelle) :

anim01

Peut-être que la page suivante pourrait aider à implémenter le glisser-déposer ?

7 « J'aime »

J’aimerais pouvoir définir des liens par défaut pour mon site, que les utilisateurs pourraient ignorer. Cela rendrait les choses strictement meilleures que les liens d’en-tête personnalisés que j’utilise actuellement, selon moi.

3 « J'aime »

+1 pour l’ajout de liens personnalisés. Nous avions quelques liens personnalisés ajoutés au menu déroulant d’origine. Ce serait bien de les rajouter, de la même manière que Discourse lui-même a des “Anniversaires” et des “Docs” sous l’option “Plus”.

4 « J'aime »

Salut à tous !

Je me demande comment je pourrais ajouter des liens à la nouvelle barre latérale.

Il ne semble pas y avoir de connecteur dans cette zone…

Quelle serait la manière la plus efficace de le faire ?


Édition

Ma question a été déplacée ici… Je ne sais pas pourquoi, car je demande vraiment la même chose.

Dans tous les cas, voici ce que j’ai fait pour résoudre le problème. Ce n’est PAS une solution élégante et il serait beaucoup mieux s’il existait un moyen de s’intégrer au système de templates de Discourse.

Voici comment :

<script>
    let logo = "" // J'ai supprimé les chemins SVG car vous n'en avez pas besoin.
    const div = document.createElement('div') // Crée le lien à ajouter
    div.className = 'sidebar-section-link-wrapper' // Ajoute les classes pertinentes
    div.innerHTML = `
          <a title="Tous les sujets" href="https://www.latranchee.com" id="ember12" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
            <span class="sidebar-section-link-prefix icon">
              <svg viewBox="0 0 100 100" class="logoIcon" xmlns="http://www.w3.org/2000/svg">${logo}</svg>
            </span>
            <span class="sidebar-section-link-content-text"> Accueil </span>
          </a>
    ` // Remplit le lien
    
    $( document ).ready(() => { // Ceci est nécessaire pour attendre que Ember ait terminé son travail
        // Ajoute la navigation sur ordinateur
        let desktop = document.getElementsByClassName('sidebar-section-content')[0];
        if(desktop) desktop.prepend(div)
        
        // Ajoute la navigation sur mobile
        let hamburger = document.getElementById('toggle-hamburger-menu').addEventListener("click", addMobileNav);
        function addMobileNav () {
            setTimeout(function(){ // Force à attendre que la navigation soit chargée
                document.getElementsByClassName('sidebar-section-content')[0].prepend(div);
            }, 0);
        }
    })
</script>

Résultat sur ordinateur…

& Résultat sur mobile :

En attendant une meilleure solution, cela fera l’affaire !

Édition #2

J’ai nettoyé le code pour que les navigations soient chargées à partir d’un tableau d’objets.

<script>
  let rss = `<path d="M5,3H19A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5A2,2 0 0,1 3,19V5A2,2 0 0,1 5,3M7.5,15A1.5,1.5 0 0,0 6,16.5A1.5,1.5 0 0,0 7.5,18A1.5,1.5 0 0,0 9,16.5A1.5,1.5 0 0,0 7.5,15M6,10V12A6,6 0 0,1 12,18H14A8,8 0 0,0 6,10M6,6V8A10,10 0 0,1 16,18H18A12,12 0 0,0 6,6Z"></path>`
  let mdiSchool = `<path d="M12,3L1,9L12,15L21,10.09V17H23V9M5,13.18V17.18L12,21L19,17.18V13.18L12,17L5,13.18Z"></path>`
  let logo = `<g xmlns="http://www.w3.org/2000/svg" fill="#0e1e2b">
    <path d="M77.4 196.2 c-8 -6.9 -11.4 -16.9 -11.4 -33.2 0.1 -20.9 2.4 -30.2 6.7 -27.4 2.9 1.8 4.3 9.4 5.4 28.9 0.9 16.5 1.4 19.8 3.6 25 1.3 3.3 2.5 6.7 2.6 7.5 0.3 2.6 -3.6 2.1 -6.9 -0.8z"/>
    <path d="M2.9 167.3 c-5.1 -6.1 11.2 -24.2 21.9 -24.3 2.6 0 2.7 1.1 0.6 5.5 -1.4 3 -12.6 13.5 -14.3 13.5 -0.4 0 -1.4 1.2 -2.1 2.6 -2 3.6 -4.5 4.8 -6.1 2.7z"/>
    <path d="M87.4 160.5 c-1.9 -1.9 -2.4 -3.4 -2.2 -5.8 0.4 -4.5 3.2 -4.7 7.4 -0.6 3.9 3.8 4.1 4.9 1.6 7.2 -2.5 2.3 -3.9 2.1 -6.8 -0.8z"/>
    <path d="M126.5 158.9 c-6 -3 -10 -7.4 -17 -18.6 -7.6 -12.2 -8.2 -13.8 -5.8 -15.2 2.8 -1.5 7.3 1.8 21.3 15.4 6.9 6.8 13.5 12.6 14.7 12.9 2.7 0.8 3.9 4.2 2.3 6.1 -1.8 2.2 -10.7 1.8 -15.5 -0.6z"/>
    <path d="M36.2 156.7 c-1.5 -1.8 -1.8 -7.8 -0.4 -10.3 1.9 -3.6 3.8 -4.7 6.1 -3.4 1.7 0.9 2.1 2 2.1 6.1 0 2.8 -0.5 5.9 -1 7 -1.2 2.2 -5.2 2.5 -6.8 0.6z"/>
    <path d="M121.5 116 c-0.8 -2.5 1.1 -5.1 3 -4.4 2 0.8 2.7 3.4 1.4 5 -1.7 2 -3.7 1.7 -4.4 -0.6z"/>
    <path d="M4.3 113 c-2.6 -1.1 -2.8 -1.9 -1 -4.4 1.5 -2 7.5 -2.9 9.5 -1.4 1.8 1.5 1.5 4.6 -0.7 5.8 -2.3 1.2 -4.8 1.2 -7.8 0z"/>
    <path d="M32.7 82 c-6.3 -4 -10.3 -9.9 -13.2 -19.4 -2.5 -8.8 -4 -24 -2.7 -29.5 0.9 -4.2 3.4 -6.1 6 -4.5 1.7 1.1 1.9 2 4.6 17.9 1.8 10.8 7.3 22.5 14.1 30.3 2.8 3.1 4.5 5.8 4.1 6.7 -1 2.6 -7.7 1.8 -12.9 -1.5z"/>
    <path d="M133.6 80.4 c-2.1 -2.1 -2 -2.9 0.6 -5.4 2.8 -2.6 6.6 -3.6 8.6 -2.3 2.5 1.5 2.4 2.9 -0.3 6.2 -2.9 3.4 -6.4 4 -8.9 1.5z"/>
    <path d="M93.3 73.3 c-2 -0.8 -1.6 -2.8 2.6 -11.1 7.1 -14.1 10.8 -19.4 22.7 -31.9 9.8 -10.5 12.1 -12.4 14.3 -12.1 1.5 0.2 2.7 1 2.9 2 0.6 3.2 -18 29.9 -29.4 42.1 -6 6.5 -11.1 11.7 -11.4 11.6 -0.3 0 -1.1 -0.3 -1.7 -0.6z"/>
    <path d="M61.7 56.2 c-2.7 -3 -3.3 -7.9 -1.2 -10.2 1 -1.1 2.4 -2 3.1 -2 2.1 0 4.4 4.2 4.4 8 0 5.6 -3.1 7.7 -6.3 4.2z"/>
    <path d="M96.2 18.8 c-4.2 -4.2 4 -19.3 8.8 -16.3 1.8 1.1 1 6.9 -1.7 12.2 -2.6 5.3 -4.7 6.5 -7.1 4.1z"/>
    </g>`

  const div = document.createElement("div")
  div.className = "sidebar-section-link-wrapper"
  div.innerHTML = `
            <a href="https://www.latranchee.com" class="sidebar-section-link sidebar-section-link-everything sidebar-row">
              <span class="sidebar-section-link-prefix icon">
                <svg viewBox="0 0 100 100" class="logoIcon" xmlns="http://www.w3.org/2000/svg">${logo}</svg>
              </span>
              <span class="sidebar-section-link-content-text"> Accueil </span>
            </a>
      `

  const customHeader = document.createElement("div")
  customHeader.className = "sidebar-section-wrapper sidebar-section-community"
  customHeader.innerHTML = `
            <div class="sidebar-section-header-wrapper sidebar-row">
              <button id="ember11" class="sidebar-section-header sidebar-section-header-collapsable btn-flat btn no-text" type="button">
                <span class="sidebar-section-header-text"> Camp d'entraînement </span>
              </button>
          </div>
          <div class="sidebar-section-content" id="customNavigation"></div>
      `

  $(document).ready(function () {
    // Crée les liens
    const links = [
      { title: "Accueil", src: "https://www.latranchee.com", svg: logo, viewbox: "0 0 100 100" },
      { title: "Formations", src: "https://www.latranchee.com/formations", svg: mdiSchool, viewbox: "2 -2 16 16" },
      { title: "Blogue", src: "https://www.latranchee.com/blogue", viewbox: "1 -3 16 16", svg: rss },
    ]

    // Mobile
    let hamburger = document.getElementById("toggle-hamburger-menu")
    if (hamburger) {
      hamburger.addEventListener("click", addCustomLinks)
    } else {
      addCustomLinks()
    }
    
    let bool = false;
    function addCustomLinks() {
      setTimeout(function () {
        // Force à attendre que la navigation soit chargée
        const sidebar = document.getElementsByClassName("sidebar-sections")[0]
        if (sidebar) {
          sidebar.prepend(customHeader)
          if (bool) return;
          // Obtient l'ID de customNav
          const customNavigation = document.getElementById("customNavigation")
          if (customNavigation) {
            links.filter(function (link) {
              let linkDiv = document.createElement("div")
              linkDiv.className = "sidebar-section-link-wrapper"
              linkDiv.innerHTML = `<a href="${link.src}" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
                        <span class="sidebar-section-link-prefix icon" id="link_${link.title}"></span>
                        <span class="sidebar-section-link-content-text"> ${link.title} </span>
                    </a>
                  `
              customNavigation.append(linkDiv)
              let linkIcon = document.getElementById("link_" + link.title)
              if (linkIcon && link.svg) {
                linkIcon.innerHTML = `<svg viewBox="${link.viewbox}" class="logoIcon" xmlns="http://www.w3.org/2000/svg"> ${link.svg}</svg>`
              }
            })
          }
        }
        bool = true
      }, 0)
      
    }
  })
</script>

J’espère que cela pourra aider quelqu’un !

2 « J'aime »

+1 de mon côté. Un peu plus de personnalisation pour la barre latérale, comme des liens personnalisés ou même plus de boutons en haut, serait bien !

Merci d’avoir pris cela en considération, je pense que pour les utilisateurs de mon forum, c’est une fonctionnalité assez importante. Les utilisateurs sont généralement nuls pour découvrir même des informations légèrement cachées, et je dois ajouter des liens bien visibles pour des choses comme « Contacter l’administrateur » et « Règles du forum ». Cela ne me dérange pas s’ils vont directement sous l’en-tête Communauté, mais ils ne seront certainement pas découverts sous le menu Plus. La flexibilité d’avoir des liens internes et externes serait également importante, les liens externes sont actuellement cassés dans le menu hamburger personnalisé :

1 « J'aime »

Voici un autre exemple qui, je l’espère, sera utile à quelqu’un, basé en grande partie sur les exemples ci-dessus. Ce code n’ajoute pas une section entièrement nouvelle, mais ajoute des liens supplémentaires en bas du panneau « Plus » dans la section Communauté (mais avant les liens FAQ et À propos dans le pied de page). Il prend en charge les icônes FontAwesome (en supposant qu’elles sont ajoutées dans les paramètres du site) et les liens externes. Il gère les cas limites où la barre latérale est fermée et rouverte, et/ou la section Communauté est réduite et agrandie. Il fonctionne sur ordinateur et sur mobile.

Je ne suis pas un expert en JavaScript, je m’excuse donc pour tout code incorrect ou non optimal. Sur mon site, du moins, cela semble fonctionner comme prévu.

Il suffit de placer ce code dans l’onglet En-tête d’un composant de thème et de le personnaliser si nécessaire :

<script>
const links = [
    // Les icônes FontAwesome peuvent devoir être ajoutées dans les paramètres du site si elles n'apparaissent pas correctement
    { title: "Mon Compte", src: "/my/billing/subscriptions", icon: "file-invoice-dollar" },
    { title: "Annuaire des utilisateurs", src: "/u?asc=true&cards=yes&order=username&period=all", icon: "address-book" },
    { title: "Docs", src: "/docs", icon: "book-reader" },
    { title: "Site externe", src: "https://google.com/", icon: "globe" }
]

$(document).ready(function () {
    if (document.getElementById("toggle-hamburger-menu")) {
        // Nous sommes en vue mobile
        addToggleListener(document.getElementById("toggle-hamburger-menu"))
    } else {
        // Nous sommes en vue bureau
        addToggleListener(document.getElementsByClassName("btn-sidebar-toggle")[0])
        addHeaderListener()
        addMoreListener()
    }

    function addToggleListener(toggleEl) {
        if (toggleEl) {
            toggleEl.addEventListener("click", function () {
                // Attendre un peu que la barre latérale se charge
                setTimeout(function() {
                    let sidebar = document.getElementsByClassName("sidebar-section-header").length
                    if (sidebar) {
                        addHeaderListener()
                        addMoreListener()
                    }
                }, 100)
            })
        }
    }

    function addHeaderListener() {
        let communityHeader = document.getElementsByClassName("sidebar-section-header")[0]
        if (communityHeader) {
            communityHeader.addEventListener("click", function () {
                // Attendre un peu que la section s'agrandisse
                setTimeout(function() {
                    let communitySection = document.getElementById("sidebar-section-content-community")
                    if (communitySection) {
                        addMoreListener()
                    }
                }, 100)
            })
        }
    }
    
    function addMoreListener() {
        let buttonMore = document.getElementsByClassName("sidebar-more-section-links-details")[0]
        if (buttonMore) {
            buttonMore.addEventListener("click", addCustomLinks)
        }
    }
    
    function addCustomLinks() {
        // Attendre un peu que la navigation soit chargée
        setTimeout(function () {
            const parentEl = document.getElementsByClassName("sidebar-more-section-links-details-content-main")[0]
            let linksAlreadyAdded = document.getElementsByClassName("sidebar-section-custom-link").length
        
            if (parentEl && !linksAlreadyAdded) {
                links.filter(function (link) {
                    let linkDiv = document.createElement("li")
                    let linkTitleTrim = link.title.replace(/\s+/g, '')
                    linkDiv.className = "sidebar-section-link-wrapper sidebar-section-custom-link"
                    linkDiv.innerHTML = `<a href="${link.src}" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
                            <span class="sidebar-section-link-prefix icon" id="link_${linkTitleTrim}"></span>
                            <span class="sidebar-section-link-content-text"> ${link.title} </span>
                        </a>
                      `
                    parentEl.append(linkDiv)
                    
                    let linkIcon = document.getElementById("link_" + linkTitleTrim)
                    if (linkIcon && link.icon) {
                        linkIcon.innerHTML = `<svg viewBox="0 0 640 512" class="fa d-icon svg-icon prefix-icon svg-string d-icon-${link.icon}" xmlns="http://www.w3.org/2000/svg">
                                <use xlink:href="#${link.icon}"></use>
                            </svg>
                        `
                    }
                })
            }
        }, 100)
    }
})
</script>
4 « J'aime »

@Ryan_Hyer Très bien ! Vous avez trouvé le moyen de faire apparaître (ou continuer à faire apparaître) les éléments après l’événement de bascule du hamburger, ce qui était le problème que je rencontrais ici :

Votre code est également très ordonné et propre. Grâce à cela, j’ai pu l’adapter pour afficher ce que je voulais dans le menu Communauté sans qu’il soit caché sous Plus :

En-tête :

<script>

const links = [
    // Les icônes FontAwesome devront peut-être être ajoutées dans les paramètres du site si elles n'apparaissent pas correctement
    { title: "Annuaire des utilisateurs", src: "/u?asc=true&cards=yes&order=username&period=all", icon: "address-book" },
    { title: "Docs", src: "/docs", icon: "book-reader" },
    { title: "Site externe", src: "https://google.com/", icon: "globe" }
]

$(document).ready(function () {
    if (document.getElementById("toggle-hamburger-menu")) {
        // Nous sommes en vue mobile
        addToggleListener(document.getElementById("toggle-hamburger-menu"))
    } else {
        // Nous sommes en vue de bureau
        addToggleListener(document.getElementsByClassName("btn-sidebar-toggle")[0])
        addCustomLinks()
    }

    function addToggleListener(toggleEl) {
        if (toggleEl) {
            toggleEl.addEventListener("click", function () {
                // Attendre un peu que la barre latérale se charge
                setTimeout(function() {
                    let sidebar = document.getElementsByClassName("sidebar-section-header").length
                    if (sidebar) {
                        addCustomLinks()
                    }
                }, 100)
            })
        }
    }
    
    function addCustomLinks() {
        // Attendre un peu que la navigation soit chargée
        setTimeout(function () {
            const parentEl = document.getElementsByClassName("sidebar-section-content")[0]
            let linksAlreadyAdded = document.getElementsByClassName("sidebar-section-custom-link").length
        
            if (parentEl && !linksAlreadyAdded) {
                links.filter(function (link) {
                    let linkDiv = document.createElement("li")
                    let linkTitleTrim = link.title.replace(/\s+/g, '')
                    linkDiv.className = "sidebar-section-link-wrapper sidebar-section-custom-link"
                    linkDiv.innerHTML = `<a href="${link.src}" class="sidebar-section-link sidebar-section-link-everything sidebar-row ember-view">
                            <span class="sidebar-section-link-prefix icon" id="link_${linkTitleTrim}"></span>
                            <span class="sidebar-section-link-content-text"> ${link.title} </span>
                        </a>
                      `
                    parentEl.append(linkDiv)
                    
                    let linkIcon = document.getElementById("link_" + linkTitleTrim)
                    if (linkIcon && link.icon) {
                        linkIcon.innerHTML = `<svg viewBox="0 0 640 512" class="fa d-icon svg-icon prefix-icon svg-string d-icon-${link.icon}" xmlns="http://www.w3.org/2000/svg">
                                <use xlink:href="#${link.icon}"></use>
                            </svg>
                        `
                    }
                })
            }
        }, 100)
    }
})
</script>

Et le CSS complémentaire :

.sidebar-section-content {
  display: flex; /* Configure une disposition flex pour pouvoir réorganiser les éléments */
  flex-direction: column;
  .sidebar-more-section-links-details {
    order: +1;
  }
}

.sidebar-wrapper li a.sidebar-section-link-about {
    display: none;
}

.sidebar-wrapper li a.sidebar-section-link-faq {
    display: none;
}

.sidebar-more-section-links-details-content-secondary .sidebar-section-link.sidebar-section-link-about {
    display: none;
}

.sidebar-more-section-links-details-content-secondary .sidebar-section-link.sidebar-section-link-faq {
    display: none;
}
2 « J'aime »

Je voulais juste attirer votre attention sur ce sujet qui vient de paraître :

Veuillez fournir vos commentaires dans ce sujet !

6 « J'aime »

Ce sujet a été automatiquement fermé après 42 heures. Les nouvelles réponses ne sont plus autorisées.