Créé en 2024 par Onozaty, et même si le plugin ne fait pas parti des 10 meilleurs plugins notés sur Redmine, il fait parti, pour moi, d’un indispensable à avoir pour ceux qui veulent personnaliser leur Redmine et commencer à mettre les mains dedans.

En gros, il va vous permettre de rajouter du code HTML, JavaScript, CSS un peu partout dans le site Redmine, à la volée, c’est-à-dire sans rechargement de l’application. Les scripts seront stockés en base et chargés à la volée sur chaque page. Il faut se rappeler que l’on est dans un cas où l’on veut surcharger des petits points d’interface de Redmine, sans vouloir créer tout un plugin.

Alors certes, il n’est pas à la portée de n’importe qui, mais si vous avez déjà réussi à installer votre Redmine chez vous, vous ne devez pas être loin d’avoir les compétences pour utiliser ce plugin.

La documentation

Chose à noter, il est très bien documenté, avec une première documentation très complète sur son utilisation : https://github.com/onozaty/redmine-view-customize

J’insiste là-dessus, car c’est quand même assez rare, pour un plugin Redmine, d’avoir une belle documentation d’utilisation.

Et deuxième point important, il y a un ensemble de « scripts » qui sont livrés de base pour être utilisés directement avec le plugin : https://github.com/onozaty/redmine-view-customize-scripts

Quelques exemples :

Il s’agit souvent des premières choses que l’on me demande de personnalisés sur un nouveau Redmine pour aider à la prise en main de l’outil.

Donc, on clique, on récupère le code depuis un exemple, et on le colle dans… « Code », ça va, il y a plus dur. Et pouf, ça marche !

Après, on peut filtrer pour que le script ne se lance que sur certains projets ou certaines pages. Par exemple, si vous voulez voir le script uniquement sur les tickets et pas le reste, une petite règle :

	/issues/[0-9]+

Développer votre propre script

Premiers pas

Bon, par contre, le côté un peu moins pratique, c’est de devoir développer dans l’interface. Impossible !

Première étape, ouvrez l’inspecteur de code et commencez par tester vos petits bouts de code par là, je sais c’est bête, mais ça marche.

Utilisation de l'inspecteur de code

Sinon, moi je me permets une petite modification de Redmine pour ajouter un fichier JavaScript qui va contenir ma « view customize » en cours de dev.

  • On commence par ouvrir le fichier : app/views/layouts/base.html.erb, dans lequel on va copier la petite ligne de code suivante :
    <script src="/custom_view_development.js" type="text/javascript"></script>
    
  • Et ensuite je crée le fichier comme suit :
    public/custom_view_development.js
    

    Et voilà, pas très propre mais pratique.

Un template de script

Une autre chose, quand je fais une view customize sur le formulaire des tickets, qui va potentiellement se recharger dès que l’on change le statut ou le tracker, j’utilise ce genre de script pour observer le div qui bouge et un debounce pour ne pas le faire trop souvent : https://laconsole.dev/blog/debounce-js

class ViewCustomizeTest {
  constructor() {
    this.setup();
  }

  setup(){
    let observer = null;
    let debounceTimer = null;

    if (document.getElementById('all_attributes')){
      observer = new MutationObserver(() => {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => { this.show(); }, 100); // Délai de 100ms
      });

      observer.observe(document.getElementById('all_attributes'), {childList: true});
    }

    this.show();
  }

  show() {
    console.log("show view customize test")
  }
}

$(function() { 
  try {
    new ViewCustomizeTest(); 
  } catch (error) {
    console.error("Erreur lors de l'initialisation de la vue customize de test", error);
  }
});

Quelques petites views customizes perso

La vue mobile de Redmine

Souvent, je me retrouve à devoir scroller horizontalement, et ce n’est pas toujours pratique. Donc, je me suis fait une petite ViewCustomize pour masquer tous les champs sauf le sujet.

@media (max-width: 768px) {
    /* Par défaut, cacher les colonnes sauf celles avec .subject ou .id */
    table.issues td:not(.subject):not(.id),
    table.issues th:not(.subject):not(.id) {
        display: none;
    }

    /* Si une ligne a la classe .group, ses colonnes ne sont pas affectées */
    table.list.issues tr.group td,
    table.list.issues tr.group th {
        display: table-cell;
    }
}

L’amélioration des liens externes

Comme il m’arrive de travailler avec d’autres outils que Redmine, si si, je me retrouve à mettre des liens partout dans les tickets et on s’habitue vite à avoir des petites URLs pour les liens. Donc, encore une petite ViewCustomize pour afficher les liens avec une belle forme style gitlab#129, github#292.

document.addEventListener("DOMContentLoaded", function(){
  $(".link_cf.cf_9.attribute a").each(function(){
    const link = $(this);
    
    if (link.attr("href").startsWith("https://app.rollbar.com/")){
      const parts = link.attr("href").split('/');
      const issueNumber = parts[parts.length - 1];
      link.text(`Rollbar#${issueNumber}`);
    }

    else if (link.attr("href").startsWith("https://gitlab.com/")){
      const parts = link.attr("href").split('/');
      const issueNumber = parts[parts.length - 1];
      link.text(`Gitlab#${issueNumber}`);
    }

    else if (link.attr("href").startsWith("https://contacts.google.com/")){
      const parts = link.attr("href").split('/');
      const issueNumber = parts[parts.length - 1];
      link.text(`GoContact#${issueNumber}`);
    }

    else if (link.attr("href").startsWith("https://github.com/")){
      const parts = link.attr("href").split('/');
      const issueNumber = parts[parts.length - 1];
      link.text(`Github#${issueNumber}`);
    }
  })
});

Bon je viens de voir qu’il y a maintenant un plugin qui fait ce genre de chose. Bon, je viens de voir qu’il y a maintenant un plugin qui fait ce genre de chose. Je laisse ça là pour l’exemple, mais je vais quand même voir pour utiliser ce plugin. https://www.redmine.org/plugins/autolinks

Le mot de la fin

Le plugin ViewCustomize est un plugin indispensable une fois qu’on a commencé à mettre les mains dedans. Une petite alerte néanmoins : quand vous avez plusieurs scripts pour apporter une fonctionnalité, ou un script plus long, commencez à regarder pour faire un plugin, la maintenance sera plus simple.