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

- Etes-vous yOS compatible ? (2/3) : la nouvelle plateforme Yammer–Office 365–SharePoint par Le blog de Patrick [MVP SharePoint] le 04-22-2014, 09:27

- [ #Yammer ] [ #Office365 ] Quelques précisions sur l’activation de Yammer Entreprise par Le blog de Patrick [MVP SharePoint] le 04-22-2014, 09:03

- Après Montréal, ce sera Barcelone, rendez-vous à la European SharePoint Conference 2014 ! par Le blog de Patrick [MVP SharePoint] le 04-19-2014, 09:21

- Emportez votre sélection de la MSDN dans la poche ? par Blog de Jérémy Jeanson le 04-17-2014, 22:24

- [ #Office365 ] Pb de connexion du flux Yammer ajouté à un site SharePoint par Le blog de Patrick [MVP SharePoint] le 04-17-2014, 17:03

- NFluent & Data Annotations : coder ses propres assertions par Fathi Bellahcene le 04-17-2014, 16:54

- Installer un site ASP.net 32bits sur un serveur exécutant SharePoint 2013 par Blog de Jérémy Jeanson le 04-17-2014, 06:34

- [ SharePoint Summit Montréal 2014 ] Tests de montée en charge SharePoint par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 20:44

- [ SharePoint Summit Montréal 2014 ] Bâtir un site web public avec Office 365 par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 18:30

- Kinect + Speech Recognition + Eedomus = Dommy par Aurélien GALTIER le 04-16-2014, 17:17