Intégration du service de vote

08/07/2017

Introduction

Cet article vise à intégrer le service de vote Flower.

Prérequis :

  • Utilisation d’un Artifactory Arondor (public ou interne)

Ce service de vote va permettre de demander l’avis des utilisateurs sur un composant, savoir s’il est d’accord avec l’information ou non. Ces informations de votes sont stockés dans Elasticsearch sous forme de campagne de vote. Chaque utilisateur ne peut voté qu’une seule fois, il peut cependant changer d’avis. S’il change d’avis, son ancien vote sera remplacé.

Configuration

Lors du lancement de ce service, différentes propriétés doivent être renseignés :

  • Port utilisé par le service : server.port
  • Contexte root du service : server.contextPath
  • Index Elasticsearch où les données seront stockées : es.index

Les valeurs par défaut sont :

server.port=7777
server.contextPath=/vote-service
es.index=flower-docs

Exemple : java -Dserver.port=7777 -Dserver.contextPath="/vote-service/" -Des.index="flower-docs" -jar flower-vote-service-1.0.jar

Exemple d’intégration : Validation de l’existence d’un incident

Contexte : Afin de vérifier la véracité de l’information concernant un incident, l’avis des personnes présentes l’immeuble concerné est demandé. Ceci permet d’éviter une intervention de réparation inutile.

Les incidents sont affichés sous forme de carte de résultat de recherche sur la page d’acceuil de chaque personne concerné.

A l’aide des APIs Javascript Flower, les boutons de vote ainsi qu’un compteur de vote pour chaque bouton sont ajoutés en bas de chaque carte d’incident :

var cardAPI = JSAPI.get().getCardAPI();
var actionAPI = JSAPI.get().getActionFactoryAPI();
var userAPI = JSAPI.get().getUserAPI();

var token = userAPI.getUserToken();
var scope = userAPI.getScope();
var userId = userAPI.getUserId();

var voteServiceURL = "http://localhost:7777/vote-service/" + scope + "/" ;

cardAPI.registerForComponent(function(card, component){
	var likeContainer = document.createElement('div');
	var dislikeContainer = document.createElement('div');
	
	var likeBadge = document.createElement('span'); 
	var dislikeBadge = document.createElement('span'); 
	
	if(component.getClassId().startsWith("Incident")){
     	console.log("Card found, add vote actions");
            
        addConfirmAction();
		addInfirmAction();
		
		updateBadgesCount();
		updateVoteButtonStatusWithUserVote();
	}

	function addConfirmAction(){
		likeContainer.className="container";
		var like = document.createElement('span'); 
        like.className= "like-button fa fa-thumbs-up ";
		likeBadge.className= "like-badge";
		likeBadge.innerHTML="0";

		likeContainer.appendChild(likeBadge);
		likeContainer.appendChild(like);

        var action = actionAPI.buildDOM("like ", "Like", likeContainer);

		card.getActions().add(action);

		like.onclick= function(){ 
			let category = component.getCategory();
			let componentId = component.getId();
			let likeURL = voteServiceURL + category + "/" + componentId + "/votes/like";
			doHttpRequest("POST", likeURL, token);
			updateBadgesCount();
			updateVoteButtonStatusWithUserVote();
	    }
    }

	function addInfirmAction(){
		dislikeContainer.className="container";

		var dislike = document.createElement('span'); 
      dislike.className= "dislike-button fa fa-thumbs-down ";
		dislikeBadge.className= "dislike-badge";
		dislikeBadge.innerHTML="0";
		
		dislikeContainer.appendChild(dislikeBadge);
		dislikeContainer.appendChild(dislike);

      var action = actionAPI.buildDOM("dislike ", "Dislike", dislikeContainer);
		
		card.getActions().add(action);

		dislike.onclick= function(){ 
			let category = component.getCategory();
			let componentId = component.getId();
			let dislikeURL = voteServiceURL + category + "/" + componentId + "/votes/dislike";
			doHttpRequest("POST", dislikeURL, token);
			updateBadgesCount();
			updateVoteButtonStatusWithUserVote();
	    }
    }

    function updateBadgesCount(){
		let category = component.getCategory();
		let componentId = component.getId();
		let baseURL = voteServiceURL + category + "/" + componentId;
		
		let likeCountURL =  baseURL + "/votes/likes/count";
		let likeCount = doHttpRequest("GET", likeCountURL, token);
		likeBadge.innerHTML=likeCount;
		
		let dislikeCountURL = baseURL + "/votes/dislikes/count";
		let dislikeCount = doHttpRequest("GET", dislikeCountURL, token);
		dislikeBadge.innerHTML=dislikeCount;
	}

	function updateVoteButtonStatusWithUserVote(){
		let category = component.getCategory();
		let componentId = component.getId();
		let baseURL = voteServiceURL + category + "/" + componentId;
		
		let userVoteURL = baseURL + "/votes/" + userId;
		let userVote = doHttpRequest("GET", userVoteURL, token);
		
		if(userVote != undefined && userVote.length > 0){
			let json = J60		SON.parse(userVote);
			if(json.like){
				likeContainer.classList.add("disable");
				dislikeContainer.classList.remove("disable");
			}
			else{
				likeContainer.classList.remove("disable");
				dislikeContainer.classList.add("disable");
			}

		} 
	}
});

function doHttpRequest(httpMethod, url, token)
{
    var request = new XMLHttpRequest();
    request.open(httpMethod, url, false);
	request.setRequestHeader("token", token);
    request.send(null);
    return request.responseText;
}

Le CSS suivant est nécessaire afin d’obtenir un visuel satisfaisant :

.home-card>.card-header{
	height: 50%;
}

.home-card .card-info {
	height: 50%;
}

.home-card .content{
	height: 60%;
}

.home-card .principal-actions {
	height: 20%;
	float: right;
	width: 100%;
}

.home-card .principal-actions .actions {
	display: inline-block;
	width: 100%;
}

.like-badge, .dislike-badge {
	font-size: 0.8rem;
	background: #89BA13;
	color: white;
	text-align: center;
	line-height: 1.5rem;
	width: 1.5rem;
	border-radius: 50%;
	box-shadow: 0 0 1px #444;
	float: right;
}

.like-button, .dislike-button {
	font-size: 2.5rem;
}

.container .disable {
	cursor: default !important;
}

.disable .like-button, .disable .dislike-button, .disable .like-badge, .disable .dislike-badge{
	pointer-events: none;
}

.disable .like-button, .disable .dislike-button {
	color: #333;
}

.disable .like-badge, .disable .dislike-badge{
	background: #333;
}