Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Etendre le Team Web Access de TFS 2012 – Step 1: Création du plugin

 

Dans cet article nous allons créer un plugin installable sur le Team Web Access qui s'intègrera dans l'architecture du site et se chargera au moment où on le décidera. 


Avant de lire ce billet et si cela n'est pas encore fait je vous conseille la lecture de l'article précédent introduisant les étapes préliminaires au développement du plugin:

Etendre le Team Web Access de TFS 2012 – Step 0


C'est parti!

Pour rendre notre plugin installable sur le Web Access de TFS c'est très simple il nous faut 3 fichiers :

  • Le fichier manifest.xml qui définit les metadata requises pour la définition du plugin
  • Un fichier Javascript monplugin.debug.js contenant le code en version « debug » de notre extension
  • Un fichier Javascript monplugin.min.js contenant le code en version minifiée de notre extension

 

Le fichier manifeste

 

Voici le contenu du fichier manifest.xml :

 

<WebAccess version="11.0">

<plugin name="My Team Web Access Plugin" vendor="Philippe Didiergeorges" moreinfo="http://blogs.developpeur.org/Philess" version="1.0">

<modules >

<module namespace="TFS.MyTWAPlugin" loadAfter="TFS.Agile.TaskBoard.View"/>

</modules>

</plugin>

</WebAccess>

 

Nous déclarons un nouveau plugin, avec les attributs suivants :

  • name : le nom du plugin tel qu'il sera affiché dans l'interface d'administration
  • vendor : Identité du développeur
  • moreinfo : URL du site du plugin
  • version : numéro de version du plugin

Ensuite viens la déclaration de nos modules. Pour rappel un module doit être un fichier Javascript… et même deux car l'on fourni le code debug et minifié. Dans notre plugin, nous allons déclarer un seul module avec les attributs suivants :

  • namespace : la valeur doit impérativement correspondre au nom des fichier JS que l'on fourni. Si namespace="toto" alors les fichiers seront toto.debug.js et toto.min.js
  • loadAfter : permet de déterminer quand le module doit être chargé par rapport à un autre : ici je lui dis de se charger impérativement après le module TaskBoard. Cela fait partie des attributs optionnels tels que loadBefore et kind qui permet de déterminer le type de module.

 

Le code Javascript

 

Il est important de comprendre que toute la structure du Team Web Access est construite sur un modèle modulaire utilisant l'API Javascript AMD (pour Asynchronous Module Definition).

L'API AMD permet de définir des modules (écris en Javascript) qui pourront être chargés en parallèle et de façon asynchrone dans leur propre scope tout en embarquant automatiquement les dépendances que l'on leur aura défini. Pour ceux qui découvre ce modèle pas de panique : l'API défini deux fonction define et require qui s'utilisent très simplement.

 

La fonction plugin s'utilise de la façon suivante :

define(id?, dependencies?, factory)

 

La déclaration de notre plugin TFS et de ses dépendances fait l'impasse sur l'id et se présente donc comme suit :

 

define(

// dependencies

["require", "exports",

"Presentation/Scripts/TFS/TFS",

"Presentation/Scripts/TFS/TFS.UI.Controls"],

 

//factory

function (require, exports, __TFS__, __Controls__) {

var TFS = __TFS__;

var Controls = __Controls__;

}

)

 

require et exports sont obligatoires, le module TFS est le module de base qui nous sera indispensable et enfin le module Controls va nous servir pour déclarer notre module qui va étendre la classe Controls.BaseControl.

 

On récupère les modules chargé dans des variables de notre module afin de les garder à disposition.

 

Il est temps de déclarer notre nouvel objet étendant le type BaseControl. Voici le code de base minimum pour étendre un contrôle :

var MyTWAPlugin = (function (_super) {

__extends(MyTWAPlugin, _super);

 

function MyTWAPlugin(options) {

_super.call(this, options);

}

 

MyTWAPlugin.prototype.initializeOptions = function (options) {

_super.prototype.initializeOptions.call(this, $.extend({

}, options));

};

 

MyTWAPlugin.prototype.initialize = function () {

};

 

MyTWAPlugin._typeName = "TFS.MyTWAPlugin";

 

return MyTWAPlugin;

})(Controls.BaseControl);

 

On déclare une variable MyTWAPlugin que l'on charge avec un objet étendant Controls.BaseControl.

 

Note : Dans notre code il faut bien comprendre que le paramètre _super contient le type d'objet BaseControl car c'est celui-ci qui est passé en paramètre en dernière ligne !

Dans l'ordre :

  • on appelle la fonction __extends qui va cloner le type d'objet _super dans MyTWAPlugin en copiant sont prototype et son custructor
  • on déclare notre constructeur : la fonction MyTWAPlugin
  • on redéfini les fonctions initialize et initializeOptions pour ajouter le code que l'on souhaite exécuter à l'initialisation du module

     

Par exemple, afin que notre plugin puisse dire bonjour lorsque le contrôle sera chargé, nous ajoutons le code suivant à la méthode initialize :

MyTWAPlugin.prototype.initialize = function () {

alert("My Plugin says Hello TaskBoard");

};

 

Notre variable contient maintenant le nouveau type d'objet et pour que TFS prenne en compte notre nouveau type d'objet il faut encore lui demander :

TFS.initClassPrototype(MyTWAPlugin, {});

 

 

Notre plugin devra dire « Hello TaskBoard » lorsque nous afficheront le taskboard de TFS. Pour cela, nous allons référencer MyTWAPlugin en tant qu'« Enhancement » du taskboard TFS. Cela se fait très simplement en identifiant le taskboard par un sélecteur CSS :

Controls.Enhancement.registerEnhancement(MyTWAPlugin, ".taskboard");

 

 

Voilà, si l'on récapitule, le code complet est le suivant:

 

var __extends = this.__extends || function (d, b) {

function __() { this.constructor = d; }

__.prototype = b.prototype;

d.prototype = new __();

};

 

 

define(["require", "exports",

"Presentation/Scripts/TFS/TFS",

"Presentation/Scripts/TFS/TFS.UI.Controls"],

 

function (require, exports, __TFS__, __Controls__) {

var TFS = __TFS__;

var Controls = __Controls__;

 

var MyTWAPlugin = (function (_super) {

__extends(MyTWAPlugin, _super);

 

function MyTWAPlugin(options) {

_super.call(this, options);

}

 

MyTWAPlugin.prototype.initializeOptions = function (options) {

_super.prototype.initializeOptions.call(this, $.extend({

}, options));

};

 

MyTWAPlugin.prototype.initialize = function () {

alert("My Plugin says Hello TaskBoard");

};

 

MyTWAPlugin._typeName = "TFS.MyTWAPlugin";

 

return MyTWAPlugin;

})(Controls.BaseControl);

 

TFS.initClassPrototype(MyTWAPlugin, {});

 

Controls.Enhancement.registerEnhancement(MyTWAPlugin, ".taskboard");

})

 

 

Génération du package

 

Avant de créer le package, nous devons copier le code Javascript dans le fichier .min.js et le minifier. Pour cela, plusieurs solutions s'offrent à nous mais ma préférée est d'utiliser l'excellent plugin Web Essentials pour Visual Studio qui vous permet de faire cela avec un simple clic droit :

 

 

Une fois le code minifié, il suffit pour générer le package de zipper l'ensemble des fichiers :

 


Installation du plugin

 

Rendez-vous sur l'interface d'administration des extensions du Team Web Access :

http://localhost:8080/tfs/_admin/_extensions

 

Cliquez sur installer puis sélectionnez votre package :

Une fois le plugin installé il suffit de l'activer pour le rendre disponible à tous vos utilisateurs.

Comme vous pouvez le voir on retrouve toutes les informations définies dans le manifeste.

 

Pour tester notre plugin, rendez-vous sur le site d'un projet puis affichez le board (tableau) d'un sprint et vous devriez vois apparaitre le message suivant :

 

On a étendu le taskboard de TFS ! Cool

Il ne s'agit pas encore d'une amélioration qui va révolutionner son utilisation mais on dispose maintenant d'une base solide pour commencer à lui faire faire des choses vraiment utiles.


Dans le prochain article nous verrons comment accéder aux services de TFS et récupérer les instances des modules du Team Web Access afin de les manipuler.

Publié lundi 3 juin 2013 07:30 par Philess
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

Pas de commentaires
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- SharePoint 2013: Préparation de la migration - Création des site Templates dans 2010 et 2013 par Blog Technique de Romelard Fabrice le 08-20-2014, 16:31

- [ #Yammer ] How to change interface language ? Comment changer la langue de l’interface ? par Le blog de Patrick [MVP SharePoint] le 08-20-2014, 14:21

- Onedrive Sync Engine Host : CPU à 100% par Le petit blog de Pierre / Pierre's little blog le 08-06-2014, 22:22

- SharePoint : Bug sur la gestion des permissions et la synchronisation Office par Blog Technique de Romelard Fabrice le 07-10-2014, 11:35

- SharePoint 2007 : La gestion des permissions pour les Workflows par Blog Technique de Romelard Fabrice le 07-08-2014, 11:27

- TypeMock: mock everything! par Fathi Bellahcene le 07-07-2014, 17:06

- Coding is like Read par Aurélien GALTIER le 07-01-2014, 15:30

- Mes vidéos autour des nouveautés VS 2013 par Fathi Bellahcene le 06-30-2014, 20:52

- Recherche un passionné .NET par Tkfé le 06-16-2014, 12:22

- [CodePlex] Projet KISS Workflow Foundation lancé par Blog de Jérémy Jeanson le 06-08-2014, 22:25