Mantis BugTracker : Création d’un plugin « Suivi du temps »

Edit 29/04/2013 :  Dernière informations sur le plugin : https://www.h-hennes.fr/blog/plugin-suivi-de-temps-pour-mantis-bugtracker/

J’utilise au quotidien la plateforme Mantis Bugtracker pour gérer mes tâches en cours, et suivre le temps que je passe sur les différents projets.

A ce titre j’ai customisé l’installation de base avec l’ajout de nouvelles fonctionnalités  tels que la mise en place d’un éditeur wysywig(TinyMce) ou la possibilité de créer un bug directement via l’envoi d’un email.

Aujourd’hui je vais vous présenter un plugin que je viens de développer pour afficher le temps que je passe sur chaque intervention.
Nous allons voir ensemble toutes les étapes de son développement.
( Ma version de mantis est la 1.2.4)

Voici un apperçu du rendu final du plugin :

Calendrier Mantis
Avant toute chose pour que ce plugin fonctionne il est nécessaire d’activer la gestion du temps dans Mantis.

Pour ce faire il est nécessaire de rajouter la ligne suivante dans le fichier « config.inc.php »

$g_time_tracking_enabled = ON;

Suivi du temps avec Mantis bugtracker

 

 

 

 

Cette ligne rajoute l’option “Suivi du temps (HH::MM) dans l’ajout des commentaires sur les bugs.

Une fois cette option mise en place nous allons procéder au développement du « plugin », pour la gestion du calendrier, nous allons nous baser sur le script opensource « fullcallendar » disponible à l’adresse suivante : http://arshaw.com/fullcalendar/ .
Ce script est bien documenté et facile à utiliser, et il propose directement un mode qui récupère des données json. C’est ce mode que nous allons utiliser.

Création de la structure de base du plugin.

Nous allons nommer ce plugin « Agenda » et sa structure contiendra les fichiers suivants :

  • Calendrier
    • Css
      • Fullcalendar.css
      • Fullcalendar.print.css
      • Agenda.css
  • Js
    • Fullcalendar.min.js
    • Fullcalendar_init.js
    • Jquery-1.5.2.min.js
    • Jquery-ui-1.8.11.custom.min.js
  • Lang
    • Strings_french.txt
    • String_english.txt
  • Pages
    • Agenda_page.php
    • Json-events.php
  • Agenda.php

 

Création de la classe du module

Nous allons à présent passer à l’édition du fichier « Agenda_inc.php »

Voici le code qui le compose :

<?php /* Plugin Agenda pour Mantis BugTracker : - Affichage du temps passé sur les bugs dans un calendrier (Nécessite l'activation de la fonctionnalité $g_time_tracking_enabled) - Basé sur le script de Calendrier "FullCalendar" disponible à l'adresse suivante : http://arshaw.com/fullcalendar/download/ Version 0.1 © Hennes Hervé - 2011 */
class AgendaPlugin extends MantisPlugin {   function register() {
      $this->name        = 'AgendaPlugin';
     $this->description = 'Affichage du temps passé sur les bugs dans un calendrier';
     $this->version     = '0.1';
     $this->requires    = array('MantisCore'       => '1.2.0',);
     $this->;author      = 'Hennes Hervé';
     $this->;url         = 'http://www.h-hennes.fr';
 }
 
 function init() {
    plugin_event_hook( 'EVENT_MENU_SUMMARY', 'agendamenu' );
 }
 
 function agendamenu() {
   return array('<a href="' . plugin_page('Agenda_page.php') . '">' .lang_get('see_agenda') . '</a>');
 }
}
?>

Le fichier est composé de 3 fonctions :

Register() : enregistrement des informations du plugin, pas de consignes particulières

Init() :
Initialisation du plugin, c’est ici qu’on va rattacher le plugin au hook souhaité et définir la fonction qui doit être effectuée pour son initialisation à savoir « Agendamenu »
Dans notre cas je souhaite que le plugin soit visible sur la page de synthèse de mantis « summary_page.php ».
Cependant si vous souhaitez l’afficher sur une autre page, la liste complète des event menu est disponible sur la page : http://www.mantisforge.org/dev/manual/master/en/developers.html#DEV.EVENTREF.OUTPUT.MENU

AgendaMenu :
Fonction effectuée à l’initialisation du plugin.Dans notre cas, cette fonction renvoie uniquement un lien à rajouter dans le menu.

Pour pouvoir l’afficher correctement et avec la gestion de la langue, il est nécessaire d’ajouter le contenu suivant dans le fichier lang/strings_french.txt

<?php

$s_see_agenda = "Voir agenda";

Création des pages du module :

Plaçons nous maintenant dans le dossier « pages », nous allons commencer par éditer le contenu de la page « Agenda_page.php »

Voici le contenu de cette page

&lt;?php
/*
Plugin Agenda pour Mantis BugTracker :
- Page d'affichage du calendrier
Version 0.
© Hennes Hervé - 2011
*/
 
html_page_top1( lang_get( 'see_agenda' ) );
html_page_top2();
print_summary_menu( 'summary_page.php' );
print_summary_submenu();
?&gt;
 
&lt;link rel='stylesheet' type='text/css' href='plugins/Agenda/css/fullcalendar.css' /&gt;
&lt;link rel='stylesheet' type='text/css' href='plugins/Agenda/css/Agenda.css' /&gt;
&lt;link rel='stylesheet' type='text/css' href='plugins/Agenda/css/fullcalendar.print.css' media='print' /&gt;
&lt;script type='text/javascript' src='plugins/Agenda/javascript/jquery-1.5.2.min.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' src='plugins/Agenda/javascript/jquery-ui-1.8.11.custom.min.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' src='plugins/Agenda/javascript/fullcalendar.min.js'&gt;&lt;/script&gt;
&lt;script type='text/javascript' src='plugins/Agenda/javascript/fullcalendar_init.js'&gt;&lt;/script&gt;
 
&lt;div id='loading' style='display:none'&gt;loading...&lt;/div&gt;
&lt;div id="event_details"&gt;
 &lt;p&gt;&lt;a id="event_details_close" href="#event_details" name="event_details"&gt;Fermer le détail &lt;/a&gt;&lt;/p&gt;
 &lt;div id="event_details_content"&gt;&lt;/div&gt;
&lt;/div&gt;
 
&lt;div id='calendar'&gt;&lt;/div&gt;
 
&lt;??php
html_page_bottom1( __FILE__ );

Rien de très compliqué dans cette page, on inclut tout d’abord l’ensemble des css et des javascript nécessaires au bon fonctionnement de l’application.
Le calendrier apparaitra automatiquement dans la div « calendar » et j’ai créé une div « event_details » qui affichera via jquery le contenu des détails des événements.

Récupération des évènements du calendrier : json-events.php

&lt;?php 
/* Connexion à la BDD et récupération des bugs avec leurs horraires */ 
include('../../../config_inc.php');
 try {  $db = new PDO('mysql:host='.$g_hostname.';dbname='.$g_database_name,$g_db_username,$g_db_password); } 
catch (Exception $e) {  die($e-&gt;getMessage()); } 
//Recherche des informations sur les bugs
 $query = $db-&gt;query('SELECT mbt.time_tracking, mbt.date_submitted, mbtt.note, mbug.description,mbg.summary title, mbg.id bug_id, mbt.id, mpt.name, mut.realname
                     FROM mantis_bug_table mbg
                     LEFT JOIN mantis_project_table mpt ON ( mpt.id = mbg.project_id)
                     LEFT JOIN  mantis_bugnote_table mbt ON (mbt.bug_id = mbg.id)
                     LEFT JOIN mantis_bugnote_text_table mbtt ON (mbtt.id = mbt.bugnote_text_id)
                     LEFT JOIN mantis_user_table mut ON (mbt.reporter_id = mut.id)
                     LEFT JOIN mantis_bug_text_table mbug ON (mbug.id = mbt.bug_id)
                   ');
 
while ( $result = $query-&gt;fetch() ) {
 
 if ( $result['id'] != NULL ) {
  $date_deb = date('Y-m-d H:i:s',$result['date_submitted']);
  $temps_deb = date('d-m-Y à H:i:s',$result['date_submitted']);
 
  if ( $result['time_tracking'] != 0 ){
   $date_fin = date('Y-m-d H:i:s',mktime(substr($date_deb,11,2),($result['time_tracking']+substr($date_deb,14,2)),0,substr($date_deb,5,2),substr($date_deb,8,2),substr($date_deb,0,4)));
   $temps_fin = date('d-m-Y à H:i:s',mktime(substr($date_deb,11,2),(substr($date_deb,14,2)-$result['time_tracking']),0,substr($date_deb,5,2),substr($date_deb,8,2),substr($date_deb,0,4)));
  }
 
  $results[] = array(
                'id' =&gt; $result['id'],
                'title' =&gt;; utf8_encode($result['name']).' : '.utf8_encode($result['title']),
                'start' =&gt; $date_deb,
                'end' =&gt; $date_fin,
                'temps_deb' =&gt; $temps_deb,
                'temps_fin' =&gt; $temps_fin,
                'auteur' =&gt;; utf8_encode($result['realname']),
                'note' =&gt; utf8_encode($result['note']),
                'description' =&gt; utf8_encode($result['description']),
                'time_tracking' =&gt; $result['time_tracking'],
                'allDay' =&gt; false
             );
 
 }
 
}
 
//Affichage des données en Ajax
echo json_encode($results);
?&gt;

Ce script peut être séparé en 3 parties :

  • Connexion à la base de données
  • Récupération et traitement des infos
  • Affichage des informations

Si vous souhaitez ajouter des informations complémentaires, il est aisé de rajouter des critères à la requête initiale.

Initialisation javascript du plugin

Pour terminer ce plugin il est à présent nécessaire d’initialiser le plugin « fullcalendar » à l’aide du fichier « js/fullcalendar_init.js »

Voici le contenu de ce fichier :

$(document).ready(function() {
 $('#calendar').fullCalendar({
 
 editable: true,
 
 //En tête
 header: {
       left: 'prev,next today',
       center: 'title',
       right: 'month,agendaWeek,agendaDay'
 },
 //Format des colonnes
 columnFormat: {
 month: 'ddd',
 week: 'ddd d/M',
 day: 'dddd d/M'
 },
//Premier jour de la semaine : Lundi
firstDay: 1,
//Pas besoin d'afficher les weeks ends
weekends : false,
//Affichage différent selon les mois
weekMode: 'variable',
//Configuration des variables Jours et mois en FR
 monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Aout','Septembre','Octobre','Novembre','Decembre'],
monthNamesShort: ['Jan','Fev','Mar','Avr','Mai','Jun','Jul','Aou','Sep','Oct','Nov','Dec'],
dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
buttonText: {
          prev: '&amp;nbsp;&amp;#9668;&amp;nbsp;',
          next: '&amp;nbsp;&amp;#9658;&amp;nbsp;',
          prevYear: '&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;',
          nextYear: '&amp;nbsp;&amp;gt;&amp;gt;&amp;nbsp;',
          today: 'Aujourd\'hui',
          month: 'Mois',
          week: 'Semaine',
          day: 'Jour'
},
events: "plugins/Agenda/pages/json-events.php",
 
/
Affichage des informations au click :
- On mets une div avec le détails
*/
 eventClick: function(calEvent, jsEvent, view) {
 
  //On affiche le block d'infos
  $('#event_details').css('display','block');
 
  //Contenu html du block
  var content = '&lt;h2&gt;'+calEvent.title+'&lt;/h2&gt;&lt;p&gt;Début action:'+calEvent.temps_deb+'&lt;br /&gt;Durée : '+calEvent.time_tracking+' min&lt;br /&gt;'
  +'Fin de l\'action : '+calEvent.temps_fin+'&lt;/p&gt;'
  +'&lt;b&gt;Détails de la note :&lt;/b&gt;'+calEvent.note+'&lt;br /&gt;'
  +'Auteur : '+calEvent.auteur+'&lt;br /&gt;'
  +'&lt;a href="#" id="event_details_description_bug_show"&gt;Voir le descriptif du bug &lt;/a&gt;&lt;br /&gt;&lt;div id="event_details_description_bug"&gt;'+calEvent.description+'&lt;/div&gt;';
 
  $('#event_details_content').html('').html(content);
 },
 
 /*
 Au survol on change l'apparence du bloc pour pouvoir tout consulter en mode semaine ou Jour
 On stocke les hauteurs et largeurs initiales dans les propriétés min-width et min-height pour pouvoir les réutiliser avec l'event MouseOut
 */
 eventMouseover: function( event, jsEvent, view ) {
  if ( view.name == 'agendaWeek' || view.name == 'agendaDay' ) {
   $(this).css({
               'min-width':$(this).css('width'),
               'width':'auto',
               'min-height': $(this).css('height'),
               'height':'auto',
               'z-index':40
   });
  }
 },
 
 /*
 A la fin du survol on réduit de nouveau l'affichage
 */
 eventMouseout: function( event, jsEvent, view ) {
 if ( view.name == 'agendaWeek' || view.name == 'agendaDay' ) {
  $(this).css({
              'width':$(this).css('min-width'),
              'height':$(this).css('min-height'),
              'z-index':10
   });
 }
 
 },
loading: function(bool) {
if (bool) $('#loading').show();
else $('#loading').hide();
}
});
 
// Bouton pour fermer le détails
$('#event_details_close').live('click',function(){
 $('#event_details').css('display','none');
});
 
//Bouton pour afficher le détail du bug
$('#event_details_description_bug_show').live('click',function() {
 $('#event_details_description_bug').toggle('slow');
});
});

Nous arrivons à présent à la fin de la création de ce plugin.
Pour l’installer, il faut encore l’uploader dans le dossier “Plugins” de mantis, et procéder à son activation 🙂

Si vous souhaitez vous pouvez télécharger directement l’archive ici : PluginMantisAgenda

Edit 29/04/2013 : Une nouvelle version du plugin de suivi de temps pour mantis bugtracker est disponible.