1. ERYEM
CAMPS
Dashboard Yammer sous SharePoint
Partie 2/2
1
Présenté par :
Barbar MITRI bmitri@eryem.com
Philippe SFEIR psfeir@eryem.com
Levallois 15/01/2015
2. Plan
1. Présentation du sujet
1. Concept de Single Page Application
2. Architecture applicative
2. Démo et architecture projet
3. Conclusion
4. Références
2
3. Single Page Application
3
Une nouvelle façon d’envisager la navigation web
Serveur Web
Cloud
navigateur client
Chargement de la
page d’accueil:
charge une fois pour
toutes l’ensemble
des fichiers html, js,
css
Action utilisateur: insertion dynamique de
données dans la page, jamais de
rechargement complet de la page
4. 4
Architecture applicative
4
Un niveau de portabilité inédit !!
1°)
2°)
3°)
6°)
Serveur
SharePoint
Poste client
1 => Connexion à l’application
SharePoint
2 => Sharepoint renvoie le contenu
Statique au client : html + CSS + JS
3=> avec l’autorisation de
Sharepoint on redirige le client
vers le serveur Proxy (NodeJS)
4=> proxy solicite le serveur de
base de données
5=> réponse de la base
6=> le proxy retourne les données
vers le client
proxy nodeJS
SQL Server
4°)
5°)
9. 9
Architecture du projet Durandal
dossier « app » lui-même composé d’un
dossier « services » contenant le fichier
avec les méthodes de service, d’un dossier
« viewmodels », d’un dossier « views »
dossier « css » contenant les feuilles de
style
dossier « lib » contenant les librairies js
Durandal et les plugins js
10. 10
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Durandal</title>
<!– références vers fichiers css -->
<script type="text/javascript"
src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['c
orechart']}]}"></script>
</head>
<body>
<div id="applicationHost">
<div class="splash">
<div class="message">
Je charge le contenu statique: pages html, scripts js, fichier css, <b> UNE FOIS POUR TOUTES
!!</b>
</div>
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
<script src="lib/require/require.js" data-main="app/main"></script>
</body>
</html>
référence l’api
google utilisée pour
dessiner les
graphiques
charge require.js et
l’attribut data-main
indique le fichier js
servant de point
d’entrée, ici main.js
11. 11
main.js requirejs.config({
paths: {
'text': '../lib/require/text',
'durandal':'../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '../lib/durandal/js/transitions',
'knockout': '../lib/knockout/knockout-3.1.0',
'bootstrap': '../lib/bootstrap/js/bootstrap',
'jquery': '../lib/jquery/jquery-1.9.1',
'services': '../app/services',
'async': '../lib/durandal/js/plugins/async',
'propertyParser': '../lib/durandal/js/plugins/propertyParser',
'goog': '../lib/durandal/js/plugins/goog'
}
});
define('gmaps', ['async!http://maps.google.com/maps/api/js?sensor=false'],
function () {
console.log('Google maps loaded');
return window.google.maps;
});
define(['durandal/system', 'durandal/app', 'durandal/viewLocator'], function (system, app, viewLocator) {
//>>excludeStart("build", true);
system.debug(true);
//>>excludeEnd("build");
app.title = 'Durandal Starter Kit';
app.configurePlugins({
router:true,
dialog: true
});
app.start().then(function() {
viewLocator.useConvention();
app.setRoot('viewmodels/shell', 'entrance');
});
});
permet d’enregistrer un
raccourci pour chaque fichier
javascript ou dossier utilisé
permet de charger les fichiers
js référencés de manière
asynchrone et d’exécuter le
code personnalisé dans le
callback, avec un espace de
nommage isolé de l’espace de
nommage global de javascript
app.setRoot définit la page
d’accueil de l’application, ici
shell.html
12. 12
shell.js
define(['plugins/router', 'durandal/app'], function (router, app) {
return {
router: router,
search: function() {
//It's really easy to show a message box.
//You can add custom options too. Also, it returns a promise for the user's response.
app.showMessage('Search not yet implemented...');
},
activate: function () {
router.map([
{ route: '', title:'Welcome', moduleId: 'viewmodels/welcome', nav: true },
{ route: 'flickr', moduleId: 'viewmodels/flickr', nav: true },
{ route: 'yamhisto', moduleId: 'viewmodels/yamhisto', nav: true },
{ route: 'map', moduleId: 'viewmodels/mapgoogle', nav: false },
{ route: 'chart', moduleId: 'viewmodels/chart', nav: true },
{ route: 'userStats/:UserId', moduleId: 'viewmodels/userStats', nav: false }
]).buildNavigationModel();
return router.activate();
}
};
});
shell.js est le viewmodel
javascript associé à la
page d’accueil.
La fonction activate
s’exécute à chaque fois
que la page est atteinte.
router.map permet de
définir des routes pour la
navigation côté client.
Lorsque le client requête
une route, commençant
par #, le fichier javascript
correspondant est
exécuté et la page html
chargée. Aucun appel
serveur n’est effectué,
l’ensemble des fichiers
étant déjà chargés dans
le navigateur client.
13. 13
chart.js
var activate = function () {
jQuery.when(services.getStatMsgByUser(), services.getStatFileByUser()).then(function
(msgByUser, fileByUser) {
msgArray[0] = ['Nom', 'Nombre de messages'];
fileArray[0] = ['Nom', 'Nombre de fichiers partagés'];
jQuery.each(msgByUser[0], function (index, item) {
msgArray[index + 1] = [item.name, item.number_msg];
});
jQuery.each(fileByUser[0], function (index, item) {
fileArray[index + 1] = [item.name, item.number_file];
});
});
};
var compositionComplete = function (view, parent) {
var msgData = google.visualization.arrayToDataTable(msgArray);
var fileData = google.visualization.arrayToDataTable(fileArray);
var msgOptions = {
title: 'Nombre de messages par utilisateur'
};
var fileOptions = {
title: 'Nombre de fichiers partagés par utilisateur'
};
var msgChart = new
google.visualization.PieChart(document.getElementById('msgChart'));
msgChart.draw(msgData, msgOptions);
var fileChart = new
google.visualization.PieChart(document.getElementById('fileChart'));
fileChart.draw(fileData, fileOptions);
};
chart.js est le fichier
associé à la route #chart.
La fonction activate est
exécutée en premier
chaque fois que la page
est requêtée. Elle
construit un tableau avec
les données Yammer
récupérées par les web
services.
La fonction
compositionComplete
est exécutée après
activate, une fois que
l’ensemble des éléments
HTML du DOM a été
chargé dans le
navigateur. C’est dans
cette fonction que sont
réalisées les
manipulation sur le DOM
permettant d’afficher les
graphiques grâce aux
APIs de google.
14. 14
Chart.html
<section>
<h2 data-bind="html: displayName"></h2>
<table>
<tr>
<td>
<div id="msgChart" style="width: 900px; height: 500px;"></div>
</td>
<td>
<div id="fileChart" style="width: 900px; height: 500px;"></div>
</td>
</tr>
</table>
</section>
Le fichier chart.html contient le squelette html de la page. Les méthodes google appelées dans le
viewmodel vont insérer les graphes dans les deux div.
15. Conclusion
15
Avec DurandalJS on peut construire des applications
JavaScript dynamiques et simples.
Inclus : JQuery , Knockout et RequireJS
Riche en fonctionnalités et multiplateforme
1 => connexion à l’application Sharepoint
2 => Sharepoint renvoie le contenu Statique au client : html + CSS + JS
3=> avec l’autorisation de Sharepoint on redirige le client vers le serveur Proxy (NodeJS)
4=> proxy solicite le serveur de base de données
5=> réponse de la base
6=> le proxy retourne les données vers le client
Le code suivant: <script type="text/javascript" src="https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1','packages':['corechart']}]}"></script>
référence l’api google utilisée pour dessiner les graphiques.
Le code suivant: <script src="lib/require/require.js" data-main="app/main"></script> charge require.js et l’attribut data-main indique le fichier js servant de point d’entrée, ici main.js
requirejs.config permet d’enregistrer un raccourci pour chaque fichier javascript ou dossier utilisé
define permet de charger les fichiers js référencés de manière asynchrone et d’exécuter le code personnalisé dans le callback, avec un espace de nommage isolé de l’espace de nommage global de javascript.
app.setRoot définit la page d’accueil de l’application, ici shell.html
shell.js est le viewmodel javascript associé à la page d’accueil.
La fonction activate s’exécute à chaque fois que la page est atteinte.
router.map permet de définir des routes pour la navigation côté client. Lorsque le client requête une route, commençant par #, le fichier javascript correspondant est exécuté et la page html chargée. Aucun appel serveur n’est effectué, l’ensemble des fichiers étant déjà chargés dans le navigateur client.
chart.js est le fichier associé à la route #chart.
La fonction activate est exécutée en premier chaque fois que la page est requêtée. Elle construit un tableau avec les données Yammer récupérées par les web services.
La fonction compositionComplete est exécutée après activate, une fois que l’ensemble des éléments HTML du DOM a été chargé dans le navigateur. C’est dans cette fonction que sont réalisées les manipulation sur le DOM permettant d’afficher les graphiques grâce aux APIs de google.