Afficher une barre de statut persistante sur SharePoint 2013

Admettons que vous voulez afficher une barre en haut de page indiquant un statut ou une information sur votre site SharePoint 2013, et que vous voulez procéder en jQuery, cet article a été écrit pour vous, si je puis dire. Tout d’abord il faut savoir que nous allons faire un peu d’ECMA Scripting (c’est du Javascript mais standardisé par une entreprise, Ecma international (possède ses propres normes et formats). Je vous rassure tout de suite, c’est du javascript, pour moi c’est juste un nom. La notification en elle même ressemblera à cela :

status_barMais elle pourra également être affichée en tant que :

  • Erreur critique (en rouge avec un logo de croix rouge)
  • Avertissement (en jaune avec un panneau de danger)
  • Succès (en vert avec un symbole coché vert)

En tout donc, 4 types de messages (avec celui du dessus étant l’information, en gris).

Nous allons donc utiliser le fichier sp.js, qui est la librairie « principale » des méthodes fournies par SharePoint, afin de générer nos notifications. Et pour que ces dernières soient persistantes, nous allons devoir créer une source de données : j’ai opté pour un fichier .json, qui va être lu par mon script.

On commence !

Commencez par créer un fichier .json dans lequel vous allez faire une structure de ce type :

{
    « activated »: « 1 »,
    « type »: « information »,
    « title »: « Information »,
    « text »: « Le site intranet est actuellement en cours de construction »
}

IMPORTANT : Par défaut, les sites SharePoint n’autorisent pas l’extension de fichier .json. Mais même après s’être rendu dans l’Administration centrale de la ferme, dans l’onglet Sécurité puis dans Définir les types de fichiers bloqués et après avoir supprimé l’extension « .json » de la liste, cela ne suffira pas. Il faudra donc renommer votre fichier en .jso, sans le « n » donc.

Puis enregistrez ce fichier au format .jso donc, et uploadez le sur une bibliothèque de documents partagés sur votre site SharePoint. Attribue-lui les droits en lecture pour Tout le monde, mais en édition seulement pour les administrateurs. Maintenant on va attaquer le code de chargement du message.

Rendez-vous donc, sur la page que vous souhaitez notifier de la barre de statut, puis mettez vous en mode modification de la page. Insérez ensuite, n’importe ou sur la page, un Webpart « Code incorporé » que vous trouverez dans l’onglet « Insérer » du ruban Office en haut de page. Vous allez ensuite cliquer sur le lien « Modifier l’extrait de code » du Webpart et y coller le code suivant :

<!-- Core library de SharePoint -->
<script type="text/javascript" src="/sites/archimen/_layouts/15/sp.js"></script> 
<script type="text/javascript" src="/sites/mysite/Style Library/jquery-1.11.0.min.js"></script>

<script type="text/javascript">
	//ExecuteOrDelayUntilScriptLoaded(addStatusMethod, "sp.js");

	//fonction jQuery chargée au début de la page, qui va recup la configuration JSON pour afficher le bon statut
	$.getJSON( "/sites/archimen/Documents%20admins/D%C3%A9ploiement/SPstatusConfig.jso", function( data ) {
		var items = [];
		$.each( data, function( key, val ) {
			items.push(val);
		});
		addStatusMethod(items)
	});

	//fonction qui permet d'afficher un statut
	function addStatusMethod(items)
	{
		if(items[0].localeCompare("1")==0 && items[2].localeCompare("")!=0 && items[3].localeCompare("")!=0)
		{
			var color="";
			if(items[1].localeCompare("critical") == 0) color="red";
			else if(items[1].localeCompare("warning") == 0) color="yellow";
			else if(items[1].localeCompare("information") == 0) color="blue";
			else if(items[1].localeCompare("success") == 0) color="green";
			else color="red"; // couleur par défaut

			statusID = SP.UI.Status.addStatus(items[2], items[3], true);
			SP.UI.Status.setStatusPriColor(statusID, color); 
		} else {

		}
	}

</script>

IMPORTANT : Avec SharePoint 2013, pensez bien à mettre le nom des couleurs en miniscule.

Je vais expliquer brièvement ce code :

  • La méthode jQuery $.getJSON(« urlDuFichier »,function(data) { }); va me permettre de lire un fichier au format .json, et de récupérer le contenu sous forme d’un objet nommé data, elle se lance au chargement de la page
  • Puis dedans je parcours l’objet data grâce à $.each( data, function (key, val) { }); ou key est le label de la valeur (dans mon fichier précédemment créé, les labels sont « activated », « type », …) et val est sa valeur associée ( dans mon exemple de fichier « 1 » derrière activated, « information » derrière type …)
  • Dans ce parcours je push (sauvegarde) toutes les valeurs dans un tableau items
  • Quand j’ai fini, j’appelle ma fonction javascript addStatusMethod(items); en lui passant en paramètre mon tableau de valeurs
  • Dans cette fonction,  je vérifie tout d’abord que les valeurs reçues sont cohérentes : items[0] correspond à « activated », donc si il est différent de 1, je n’affiche pas de message. items[2] et items[3] représentent respectivement le titre et le message de la barre de statut, si ils sont vides, ce n’est pas la peine également d’afficher le statut.
  • Si les valeurs sont cohérentes, alors je définit la couleur du message en fonction de items[1] qui est le type de message (critical, warning, information ou success).
  • Pour finir, avec ces deux lignes de code :
statusID = SP.UI.Status.addStatus(items[2], items[3], true);
SP.UI.Status.setStatusPriColor(statusID, color);

Je créé ma barre de statut en lui passant le titre, le message et en lui disant d’accepter les couleurs prioritaires, puis je lui affecte la couleur déterminée précédemment.

Voila, si votre fichier .jso est lisible depuis n’importe quel poste client voulu, le client pourra voir le message de statut en affichant la page sur laquelle le code incorporé est présent.

Faciliter la modification du fichier

Maintenant, avouez que cela n’est pas pratique de devoir éditer le fichier à la mano dès qu’on en a besoin. Si on veut modifier facilement ce fichier, on peut partir sur la création d’un formulaire, qui utilisera des méthodes CSOM (Client Side Object Model) Javascript afin de modifier notre fichier. Personnellement, je me suis créé une page d’administration dans laquelle j’ai ajouté un code incorporé (comme précédemment) avec le contenu suivant :

<script type="text/javascript" src="/sites/archimen/Style Library/jquery-1.11.0.min.js"></script>
<script type="text/javascript">

         function updateFile(state,title,type,message) {
		var context;
		var oWebsite;
		var oList;
		var fileCreateInfo;
		var fileContent;

		context = new SP.ClientContext.get_current();
		oWebsite = context.get_web();
		oList = oWebsite.get_lists().getByTitle("Documents admins");

		fileCreateInfo = new SP.FileCreationInformation();
		fileCreateInfo.set_url("SPstatusConfig.jso");
		fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
		fileCreateInfo.set_overwrite(true);
		fileContent = '{';
		fileContent += '"activated": "'+state+'",';
		fileContent += '"type": "'+type+'",';
		fileContent += '"title": "'+title+'",';
		fileContent += '"text": "'+message+'"';
		fileContent += '}';

		for (var i = 0; i < fileContent.length; i++) {

			fileCreateInfo.get_content().append(fileContent.charCodeAt(i));
		}

		this.existingFile = oList.get_rootFolder().get_files().add(fileCreateInfo);

		context.load(this.existingFile);
		context.executeQueryAsync(
			Function.createDelegate(this, successHandler),
			Function.createDelegate(this, errorHandler)
		);

		function successHandler(sender, args) {
			SP.UI.Notify.addNotification("Fichier JSO de notification mis à jour", false);
		}

		function errorHandler(sender, args) {
			SP.UI.Notify.addNotification("Erreur : " + args.get_message(), true);
		}
	}

	function updateStatusBar(choice) {
		// on récupère l'état du statut (on ou off)
		var tmp = document.getElementsByName("status");
		var state="";
		if(tmp[0].checked) {
			state = "1";
		} else {
			state = "0";
		}
		// on récupère le titre du statut
		var title = document.getElementById("statusTitle").value;
		// on récupère le type du statut
		var selectedContent = document.getElementById("statusType");
		var type = selectedContent.options[selectedContent.selectedIndex].value;
		// on récupère le message du statut
		var message = unescape(encodeURIComponent(document.getElementById("statusSentence").value));
                if(choice==1) {
		      updateFile(state,title,type,message);
                } else {
                      SP.UI.Status.removeAllStatus(true);
                      statusID = SP.UI.Status.addStatus(title, message, true);
                      var color="";
                      if(type.localeCompare("critical") == 0) color="red";
			else if(type.localeCompare("warning") == 0) color="yellow";
			else if(type.localeCompare("information") == 0) color="blue";
			else if(type.localeCompare("success") == 0) color="green";
			else color="red"; // couleur par défaut
		      SP.UI.Status.setStatusPriColor(statusID, color); 
                }
	}

</script>

<fieldset>
	<legend>Informations:</legend>
	<table>
		<tr>
			<td>Activer/Desactiver message</td>
			<td>
				<label for="c1">On </label><input type="radio" name="status" id="c1" value="enabled" checked="checked"/>
				<label for="c2">Off</label><input type="radio" name="status" id="c2" value="disabled" /><br>
			</td>
		</tr>
		<tr>
			<td><label for="statusTitle">Titre du message</label></td><td><input id="statusTitle" type="text" /></td>
		</tr>
		<tr>
		<td><label for="statusType">Type du message</label></td>
		<td><select id="statusType">
		   <option value="critical">Critique</option>
		   <option value="warning">Avertissement</option>
		   <option value="information">Information</option>
		   <option value="success">Succès</option>
		</select></td>
		</tr>
		<tr>
		<td><label for="statusSentence">Vous pouvez saisir une phrase personnalisée </label></td><td><textarea id="statusSentence" cols="100" rows="2" maxlength="255" ></textarea></td>
		</tr>
		<tr>
		<td><label for="templateSentence">Ou choisir une phrase préconfigurer (et la modifier si besoin)</label></td>
		<td><select id="templateSentence">
			<option>Phrases personnalisées ... </option>
                        <option>L'intranet est actuellement en cours de construction, merci de ne pas l'utiliser</option>
			<option>Une erreur générale est survenue, merci de votre patience</option>
			<option>Le serveur de fichier rencontre des difficultés, merci de votre compréhension</option>
			<option>Le service de messagerie est actuellement hors-ligne, merci de votre patience</option>
			<option>Le serveur d'application n'est pas disponible pour le moment, merci de votre compréhension</option>
			<option>Une maintenance est en cours</option>
			<option>Un problème est survenu</option>
		</select></td>
		</tr>
	</table>
	<br><br>
	<input id="buttonConfirm" onclick="updateStatusBar(1);" type="button" value="Mettre à jour le statut"/> 
        <input id="buttonSurvey" onclick="updateStatusBar(0);" type="button" value="Afficher un aperçu"/><br/>
</fieldset>

<script type="text/javascript">
		$('#templateSentence').on('change', function() {
			var str = $(this).find(':selected')[0].text;
			$("#statusSentence").val(str);
		});
</script>

Qui donne cette apparence :

update_statusbar_form

Bon, voici venu le temps des explications :

Donc ici mon formulaire va me permettre de renseigner les informations suivantes :

  • Deux boutons radio pour activer/désactiver le message de statut
  • Le titre de la barre de statut
  • Son type (critique, avertissement, information, succès)
  • Et enfin le corps du message

Grâce à une méthode jQuery je rafraichis l’élément input du corps du message, pour remplir rapidement des message prédéfinis. (du type le serveur X est en panne, etc …). Ceci est fait grâce au petit script ci-dessous :

<script type="text/javascript">
	$('#templateSentence').on('change', function() {
		var str = $(this).find(':selected')[0].text;
		$("#statusSentence").val(str);
	});
</script>

Mon input ayant un l’id « statusSentence », et ma dropdown list (balises select) ayant l’id « templateSentence ».

Fonction updateStatusBar(var int)

Au clic sur le bouton « Mettre à jour le statut » je vais d’abord récupérer dans des variables Javascript toutes les valeurs de mes éléments HTML:

               // on récupère l'état du statut (on ou off)
		var tmp = document.getElementsByName("status");
		var state="";
		if(tmp[0].checked) {
			state = "1";
		} else {
			state = "0";
		}
		// on récupère le titre du statut
		var title = document.getElementById("statusTitle").value;
		// on récupère le type du statut
		var selectedContent = document.getElementById("statusType");
		var type = selectedContent.options[selectedContent.selectedIndex].value;
		// on récupère le message du statut
		var message = document.getElementById("statusSentence").value;

Une fois que j’ai tout récupéré,  je vérifie avec quel bouton j’ai appelé ma fonction (si vous faites attention, le bouton « Mettre à jour le statut » appelle la fonction avec la valeur 1 tandis que le bouton « Afficher un aperçu » l’appelle avec la valeur 0). Si je veux mettre à jour le statut, j’appelle ma fonction updateFile() afin de mettre à jour le fichier .jso avec les bonnes données; sinon j’affiche directement un message temporaire avec ces données pour que l’utilisateur puisse visualiser le message avant de le confirmer et le déployer:

if(choice==1) {
		      updateFile(state,title,type,message);
                } else {
                      SP.UI.Status.removeAllStatus(true);
                      statusID = SP.UI.Status.addStatus(title, message, true);
                      var color="";
                      if(type.localeCompare("critical") == 0) color="red";
			else if(type.localeCompare("warning") == 0) color="yellow";
			else if(type.localeCompare("information") == 0) color="blue";
			else if(type.localeCompare("success") == 0) color="green";
			else color="red"; // couleur par défaut
		      SP.UI.Status.setStatusPriColor(statusID, color); 
                }

Fonction updateFile(var state, var title, var type, var message)

Intéressons nous maintenant à la fonction qui va mettre à jour le fichier. Si on veut modifier un élément sur un site SharePoint côté client, il faut penser CSOM Javascript.

Lorsque l’on code une application côté client (CSOM) pour aller requêter le serveur SharePoint afin de lui faire faire des opérations, il faut obligatoirement appliquer la méthode context.Load(objet) pour accéder aux propriétés de l’objet en question. si vous n’avez besoin que d’une propriété; vous pouvez économiser de la ressource en précisant quelle propriété vous voulez charger :

clientContext.Load(oWebsite,w=>w.Title); // ici on récupère le titre d'un site SP

Ensuite, il faut exécuter la requête comme ceci : context.ExecuteQuery();
On peut aussi, vouloir exécuter de façon asynchrone un traitement, et avoir un message de retour. On peut le faire de cette manière :

context.ExecuteQueryAsync(Function.createDelegate(this, this.onSuccess), Function.createDelegate(this, this.onFail));

Puis il suffira des créer deux fonction onSuccess(sender, args) et onFail(sender, args) qui seront appelées dépendamment du retour du serveur.

Donc si on découpe la fonction :

var context;
var oWebsite;
var oList;
var fileCreateInfo;
var fileContent;

context = new SP.ClientContext.get_current();
oWebsite = context.get_web();
oList = oWebsite.get_lists().getByTitle("Documents admins");

Je déclare mes variables au début de ma fonction, car certaines me seront utiles pas mal de fois. Le contexte, c’est votre serveur SharePoint (un objet ClientContext instancié c’est un handler côté client pour utiliser les méthodes sur a peu près tout les éléments SharePoint). Puis on récupère votre site SharePoint actuel avec get_web(). Ensuite viens le tour de la liste, que l’on récupère par son titre « Documents admins » et que l’on stocke dans oList.

fileCreateInfo = new SP.FileCreationInformation();
fileCreateInfo.set_url("SPstatusConfig.jso");
fileCreateInfo.set_content(new SP.Base64EncodedByteArray());
fileCreateInfo.set_overwrite(true);
fileContent = '{';
fileContent += '"activated": "'+state+'",';
fileContent += '"type": "'+type+'",';
fileContent += '"title": "'+title+'",';
fileContent += '"text": "'+message+'"';
fileContent += '}';

Ensuite, je créé un objet de type FileCreationInformation, qui va contenir tout ce dont j’ai besoin pour modifier un fichier existant dans ma bibliothèque de documents. Je défini son nom, son type de contenu (Base64EncodedByteArray) et le fait qu’il puisse écraser un fichier déjà existant. Puis je rempli ma chaine de caractères avec le futur contenu du fichier .jso en intégrant dedans les arguments passés à ma fonction.

for (var i = 0; i < fileContent.length; i++) {
                fileCreateInfo.get_content().append(fileContent.charCodeAt(i));
}

this.existingFile = oList.get_rootFolder().get_files().add(fileCreateInfo);

context.load(this.existingFile);
context.executeQueryAsync(
	        Function.createDelegate(this, successHandler),
		Function.createDelegate(this, errorHandler)
);

function successHandler(sender, args) {
		SP.UI.Notify.addNotification("Fichier JSO de notification mis à jour", false);
}

function errorHandler(sender, args) {
		SP.UI.Notify.addNotification("Erreur : " + args.get_message(), true);
}

Dans la dernière partie de ma fonction, je boucle sur ma chaine précédemment créée, en fonction de son nombre de caractères, je rajoute, caractère par caractère le contenu dans la propriété « contenu » de mon objet fileCreateInfo. Puis, je stocke dans l’objet this.existingFile un nouveau fichier qui va venir modifier l’ancien, dans le dossier racine de mon objet oList. (qui est ma bibliothèque, rappelez vous !).

Ensuite, comme expliqué un peu plus haut, je dois utiliser load() afin de pouvoir exploiter les propriétés de mon objet fichier, et enfin j’exécute la requête de façon asynchrone vers le serveur grâce à executeQueryAsync(arg1, arg2) avec arg1 et arg2 étant des fonctions à exécuter si , respectivement, l’opération de déroule avec succès ou échoue.

IMPORTANT : Le premier argument, est la fonction appelée en cas de succès, dans le cas contraire, c’est le deuxième argument qui est utilisé.

Résumé

Normalement, après avoir fait ces petits mécanismes, on est capables de :

  • Remplir un formulaire en précisant un titre, un type de message, un message
  • Choisir des phrases personnalisées à utiliser rapidement lors du remplissage du formulaire
  • De choisir si on veut ou non afficher la barre de statut
  • On peut également afficher un aperçu du message
  • Et pour finir de mettre à jour le fichier .jso accessible, qui va être utilisé pour afficher sur tout les clients la petite barre qui va bien

Bien bien, ce petit tuto touche à sa fin, j’espère avoir été clair, vous pourrez ainsi informer vos utilisateur SharePoint que vous organisez un immense barbecue et qu’il y aura des merguez à volonté ! Non, je rigole, gardez les pour vous ! Allez a plus j’espère 😉

Laisser un commentaire