Widget

Actions du panneau

Ajouter vos propres boutons et liens à la vue détail d'un feedback — créer un ticket, confier un feedback à un agent, l'ouvrir dans votre outil de suivi.

panelActions ajoute vos propres contrôles à la vue détail d'un feedback, sur une ligne sous Résoudre et Supprimer. Servez-vous-en pour faire passer un feedback dans les outils que vous utilisez déjà, sans forker le panneau.

initSiteping({
  endpoint: "/api/siteping",
  projectName: "mon-projet",
  panelActions: [
    {
      id: "create-ticket",
      label: "Créer un ticket",
      visible: (feedback) => feedback.type === "bug",
      onAction: async (feedback, { refresh }) => {
        await fetch("/api/tickets", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ feedbackId: feedback.id, message: feedback.message }),
        });
        await refresh(); // votre endpoint a passé le feedback en in_progress — affichez-le
      },
    },
    {
      id: "github-issue",
      label: "Ouvrir une issue GitHub",
      href: (feedback) =>
        `https://github.com/acme/site/issues/new?title=${encodeURIComponent(feedback.message.slice(0, 80))}`,
    },
  ],
});

Boutons et liens

Chaque action est soit un bouton (onAction), soit un lien (href). TypeScript refuse une action qui a les deux, ou aucun des deux :

ChampTypeCe que ça fait
idstringObligatoire et unique. Exposé en data-action-id sur le contrôle
labelstringObligatoire. Rendu en texte brut, jamais en HTML. Non traduit par le widget : localisez-le vous-même
iconstringBalisage SVG facultatif affiché avant le libellé — voir Icônes
visible(feedback) => booleanFacultatif. Renvoyez false pour masquer l'action sur ce feedback
onAction(feedback, context) => void | Promise<void>Bouton. Exécuté au clic
hrefstring ou (feedback) => stringLien. Sa cible — uniquement http:, https: ou mailto:

Les types sont exportés par @siteping/widget : SitepingPanelAction (l'union), SitepingPanelButtonAction, SitepingPanelLinkAction, SitepingPanelActionContext et SitepingPanelActionFeedback.

Exécution d'une action

Tant que la promesse renvoyée par onAction est en attente, le bouton cliqué affiche un spinner et tous les autres boutons de la vue — Résoudre et Supprimer compris — sont désactivés. Le spinner conserve le nom accessible du bouton et pose aria-busy. La vue reste verrouillée jusqu'à ce que la promesse aboutisse, même quand refresh() la réaffiche ou que l'utilisateur revient sur ce feedback : une action ne s'exécute jamais deux fois en même temps sur le même feedback. La vue détail reste ouverte quelle que soit l'issue.

Le second argument vous donne deux utilitaires :

  • refresh() recharge la liste et les marqueurs, puis réaffiche la vue détail avec le feedback à jour — ou revient à la liste s'il ne correspond plus aux filtres du panneau. Appelez-le quand votre action a modifié le feedback côté serveur.
  • close() ferme le panneau.

Les callbacks reçoivent une copie gelée du feedback, typée SitepingPanelActionFeedback : en lecture seule à tous les niveaux, tableaux et objets imbriqués compris. Lisez tout ce dont vous avez besoin. Les écritures sont refusées — TypeScript les signale, et à l'exécution elles lèvent une erreur en mode strict (et sont ignorées sans bruit sinon) — et ne pourraient de toute façon pas changer ce qu'affiche le panneau. Typez vos propres fonctions avec SitepingPanelActionFeedback : un paramètre FeedbackResponse n'accepte pas la copie gelée.

Liens

Les liens sont de vrais éléments <a> : clic molette, « ouvrir dans un nouvel onglet » et lecteurs d'écran se comportent comme on s'y attend. Les liens web s'ouvrent dans un nouvel onglet avec rel="noopener noreferrer", donc la page en recette ne fuit jamais en referrer. Les liens mailto: ouvrent le client mail sur place. Les URL relatives sont résolues par rapport à la page courante.

Tout autre schéma — javascript:, data:, file:… — n'est jamais rendu. Un href statique écarte l'action avec un avertissement dans la console ; un href calculé masque l'action pour ce feedback et est signalé via onError.

Erreurs

Tout ce que onAction lève ou rejette, ainsi qu'une fonction visible ou href qui lève, est toujours journalisé dans la console sous [siteping] Panel action failed:, puis part dans onError si vous en définissez un — les valeurs qui ne sont pas des Error sont enveloppées — et les boutons reviennent. Le widget n'a pas d'interface à lui pour ces erreurs : l'entrée de console garantit qu'un bug dans votre handler n'échoue jamais en silence. Ce sont des échecs de votre code, pas de l'API de feedback : ils ne sont donc pas émis sur l'événement public feedback:error, et ne peuvent jamais être pris pour un envoi échoué dans la popup de commentaire.

initSiteping({
  endpoint: "/api/siteping",
  projectName: "mon-projet",
  onError: (error) => showToast(error.message),
  panelActions: [
    {
      id: "send-to-agent",
      label: "Confier à l'agent",
      onAction: async (feedback) => {
        const res = await fetch("/api/agent", { method: "POST", body: JSON.stringify(feedback) });
        if (!res.ok) throw new Error(`L'agent a refusé la tâche (${res.status})`); // → onError
      },
    },
  ],
});

Validation

panelActions est lu une seule fois, au chargement du panneau. Une entrée sans id ni label non vides, sans exactement un de onAction / href, avec un href statique dangereux, ou qui réutilise un id précédent est écartée avec un avertissement [siteping] dans la console. Les autres actions s'affichent quand même.

Icônes

icon prend du balisage SVG, dessiné en 15 px avant le libellé et masqué des technologies d'assistance (le libellé nomme déjà le contrôle). Le balisage est analysé dans un document inerte et réduit à des formes simples — path, circle, rect, g, dégradés, masques de découpe — dont seuls les attributs de géométrie et de peinture sont conservés. Scripts, foreignObject, styles, animations, liens, gestionnaires d'événements et toute valeur d'attribut capable de charger une ressource sont supprimés ; les références url(#id) internes à l'icône sont conservées. Traitez-le malgré tout comme du balisage statique que vous maîtrisez. Une chaîne qui n'est pas un <svg> est ignorée avec un avertissement, et l'action garde son libellé.

React

Avec useSiteping, onAction, visible et un href fonction sont lus au moment de l'appel : ils peuvent capturer un état frais (un jeton d'authentification, l'utilisateur courant) sans réinitialiser le widget. La liste elle-même — ids, libellés, icônes, href statiques — est lue au montage, comme toutes les autres options structurelles.

Modifier sur GitHub

Sur cette page