Menu and sortable blocks from Lemon API

e_collectivites-version
Romain_L 2 years ago
parent b4c43aba0c
commit 0a5a1b8690
  1. 45
      api_lemon_pleiade/README.md
  2. 3
      api_lemon_pleiade/api_lemon_pleiade.libraries.yml
  3. 6
      api_lemon_pleiade/api_lemon_pleiade.links.menu.yml
  4. 1
      api_lemon_pleiade/api_lemon_pleiade.routing.yml
  5. 159
      api_lemon_pleiade/js/.api_lemon_pleaide_with_icon_nextto_bloc_menu.js
  6. 95
      api_lemon_pleiade/js/api_lemon_pleiade.js
  7. 1
      api_lemon_pleiade/src/Form/PleiadeSSOapiFieldsConfig.php

@ -0,0 +1,45 @@
# API Pléiade pour SSO avec LemonLDAP
## Fonctionnement
Ce module a été créé pour récupérer les informations renvoyées par LemonLdap concernant l'utilisateur connecté.
Pour se faire, le module appelle l'API interne de drupal qui elle même appelle l'api Externe de LemonLDAP.
La réponse de L'API se fait au format JSON. Le module récupère cette réponse et la formate pour récupérer les différentes valeurs contenu dans le JSON.
La première tache du module est des créer un menu contenant les applications renvoyé par Lemon.
Dans un premier temps le fichier JS appelle en ajax l'api interne contenant la réponse de LemonLDAP.
La suite du code traite et créé le menu html avec les différentes clés et valeurs.
le résultat est stocké dans une variable et intégré à une div, ici contenant l'id "blocLemonCustom", créé précédemment dans le template twig du thème.
Pour créer les blocs sur la page d'accueil, on utilise le même procédé : On créé une variable contenant le html à intégrer puis on l'insère dans une div contenant un id spécifique.
La spécificité de ces derniers blocs sont qu'ils doivent être drag and drop.
## Librairie additionnelle
On utilise donc une librairie externe SortableJS :
https://github.com/SortableJS/Sortable
https://sortablejs.github.io/Sortable/
Activer le mod php-curl :
```
phpenmod curl
```
## Spécificités
On rend ensuite les blocs "draggable" en spécifiant la div ou les éléments sont draggable.
On voulait faire en sorte que tout soit draggable : Les blocs parents comme les liens.
On a donc créé deux zones draggable : une pour les blocs parents, et une pour les blocs (liens) enfants, que sont les blocs parents.
## Exemple de requête
exemple d'une requête curl Lemon / Myapplications :
curl 'https://authdev.ecollectivites.fr/myapplications' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' -H 'Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Cookie: llnglanguage=fr; lemonldap=076e890b80eb23483d352541795b70751f86c57cba94c2a0a20466d55ec4ae53' -H 'Upgrade-Insecure-Requests: 1' -H 'Sec-Fetch-Dest: document' -H 'Sec-Fetch-Mode: navigate' -H 'Sec-Fetch-Site: none' -H 'Sec-Fetch-User: ?1' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache'
## Admin
/admin/config/api_lemon_pleiade/settings

@ -9,8 +9,7 @@ api_lemon_pleiade_test_js:
- core/drupal.ajax
- core/views.ajax
- core/jquery.ui
# - core/jquery.ui.effects.core
# - core/jquery.ui.autocomplete
- jquery_ui_sortable/sortable
api_lemon_pleiade_test_css:
version: 1.x
css:

@ -0,0 +1,6 @@
api_lemon_pleiade.admin:
title: 'API Pléiade - LemonLDAP module settings'
description: 'Page de configuration du module API Lemon Pléiade'
parent: system.admin_config_development
route_name: api_lemon_pleiade.settings
weight: 100

@ -5,6 +5,7 @@ api_lemon_pleiade.settings:
_title: 'API LemonLDAP Pléiade Settings'
requirements:
_permission: 'administer site configuration'
api_lemon_pleiade.pleiade_data_autocomplete:
path: '/api_lemon_pleiade/pleiade-data-autocomplete'
defaults:

@ -0,0 +1,159 @@
(function ($, Drupal, drupalSettings) {
Drupal.behaviors.APIlemonDataPleiadeBehavior = {
attach: function (context, settings) {
// var field_lemon_url = drupalSettings.api_lemon_pleiade.field_lemon_url;
// var field_lemon_myapplications_url = drupalSettings.api_lemon_pleiade.field_lemon_myapplications_url;
// var field_pastell_url = drupalSettings.api_lemon_pleiade.field_pastell_url;
// var field_parapheur_url = drupalSettings.api_lemon_pleiade.field_parapheur_url;
// var field_ged_url = drupalSettings.api_lemon_pleiade.field_ged_url;
$(document).ready(function () {
// TEST JS custom module init +
// $( "#blocLemonCustom" ).sortable();
console.log("Module Pléiade API/Lemon --> hello :))");
$.ajax({
url: Drupal.url("api_lemon_pleiade/pleiade-data-autocomplete"), // on appelle le script JSON
dataType: "json", // on spécifie bien que le type de données est en JSON
type: "POST",
data: {
//variable envoyé avec la requête vers le serveur
myapplications: "", // pour le moment on recupere tout ce que renvoie myapplications de lemon
},
success: function (donnees) {
//donnees est le reçu du serveur avec les résultats
// console.log(donnees);
// on l'affiche dans une tab des settings du theme pour voir (et pour le fun :))
const obj = JSON.stringify(donnees);
document.getElementById("lemonApps").innerHTML =
"<pre>" + obj + "</pre>";
// div #menuTestLemon
var menuHtml = "<ul>";
for (var i = 0; i < donnees.myapplications.length; i++) { // on récupère la longueur du json pour boucler sur le nombre afin de créer tout nos lien du menu
menuHtml +=
'<li class="nav-small-cap"><i class="mdi mdi-dots-horizontal"></i><span class="hide-menu">' +
donnees.myapplications[i].Category + // on récupère toute les catégories du json qu'on stocke dans une liste
"</span></li>";
for ( var f = 0; f < donnees.myapplications[i].Applications.length; f++) { // Pour chaque catégories, on récupère le nombre d'applications de la catégorie puis on boucle dessus
const temp = Object.values(donnees.myapplications[i].Applications[f]);
menuHtml += // on créé ensuite le lien avec le title du lien et le la description, pour créer le bloc
'<a class="sidebar-link waves-effect waves-dark" title="' +
temp[0].AppDesc +
'" href="' +
temp[0].AppUri +
'" aria-expanded="false"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-corner-down-right"><polyline points="15 10 20 15 15 20"/><path d="M4 4v7a4 4 0 0 0 4 4h12"/></svg><span class="hide-menu">' +
Object.keys(donnees.myapplications[i].Applications[f]) +
" </span></a>";
}
menuHtml += '<li class="nav-devider"></li>';
}
menuHtml += "</ul>";
document.getElementById("menuTestLemon2").innerHTML = menuHtml; // on récupère l'entièreté du menu créé puis on le stocke dans la div contenant l'id menuTestLemon2
// Ajout du bloc a la page accueil
var blocLemon = "";
for (var i = 0; i < donnees.myapplications.length; i++) {
// nommage id div pour boucle du bloc i pour drag and drop
var id = 'row-'+i;
blocLemon +=
`<div class="col-lg-12"><div class="mb-2 shadow-lg"><div class="card my-2"><div class="card-header rounded-top" style="background-color: #1f3889"><h4 class="card-title text-light">` +
donnees.myapplications[i].Category +
`<span></span></h4></div><div class="card-body"><div class="row px-4" id="${id}">`; // ajout de le l'id dans le html avec le numéro de boucle
for ( var f = 0; f < donnees.myapplications[i].Applications.length; f++) {
const temp = Object.values(
donnees.myapplications[i].Applications[f]
);
blocLemon +=
'<div class="col-md-4 my-3"><a class="border-dark text-center row py-3 h-100 shadow-lg" title="' +
temp[0].AppDesc +
'" href="' +
temp[0].AppUri +
'"><div class="col-4 align-items-center justify-content-center d-flex"><svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-settings"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></div><div class="col-8 "><h5 class="card-title">' +
Object.keys(donnees.myapplications[i].Applications[f]) +
'</h5><p class="text-muted">' +
temp[0].AppDesc +
'</p></div></a></div>';
}
blocLemon += "</div></div></div></div></div></div>";
}
document.getElementById("blocLemonCustom").innerHTML = blocLemon; // ajout du html dans la div avec l'id blocLemonCustom
// récupère le nombre de div enfante de l'element blocLemonCustom
const htmlDoc = document.getElementById("blocLemonCustom");
const box = htmlDoc.children.length;
for ( var f = 0; f < box; f++){
// récup des éléments du bloc dont l'id contient row-n
var temps = document.getElementById("row-"+f);
Sortable.create(temps, {
animation: 150,
store: { // ajout de la sauvegarde des emplacements de chaque blocs au rafraichissement
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group);
return order ? order.split("|") : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(sortable.options.group, order.join("|"));
},
},
});
}
var el = document.getElementById("blocLemonCustom");
new Sortable.create(el, {
animation: 150,
store: { // ajout de la sauvegarde des emplacement de chaque blocs au rafraichissement
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group);
return order ? order.split("|") : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(sortable.options.group, order.join("|"));
},
},
});
},
});
});
},
};
})(jQuery, Drupal, drupalSettings);

@ -8,8 +8,8 @@
// var field_ged_url = drupalSettings.api_lemon_pleiade.field_ged_url;
$(document).ready(function () {
// TEST JS custom module init
// $( "#blocLemonCustom" ).sortable();
console.log("Module Pléiade API/Lemon --> hello :))");
@ -27,32 +27,34 @@
// on l'affiche dans une tab des settings du theme pour voir (et pour le fun :))
const obj = JSON.stringify(donnees);
document.getElementById("lemonApps").innerHTML =
document.getElementById("lemonApps").innerHTML =
"<pre>" + obj + "</pre>";
// div #menuTestLemon
var menuHtml = "<ul>";
for (var i = 0; i < donnees.myapplications.length; i++) {
// on récupère la longueur du json pour boucler sur le nombre afin de créer tout nos lien du menu
menuHtml +=
'<li class="nav-small-cap"><i class="mdi mdi-dots-horizontal"></i><span class="hide-menu">' +
donnees.myapplications[i].Category +
donnees.myapplications[i].Category + // on récupère toute les catégories du json qu'on stocke dans une liste
"</span></li>";
for (
var f = 0;
f < donnees.myapplications[i].Applications.length;
f++
) {
// Pour chaque catégories, on récupère le nombre d'applications de la catégorie puis on boucle dessus
const temp = Object.values(
donnees.myapplications[i].Applications[f]
);
menuHtml +=
menuHtml += // on créé ensuite le lien avec le title du lien et le la description, pour créer le bloc
'<a class="sidebar-link waves-effect waves-dark" title="' +
temp[0].AppDesc +
+'" href="' +
'" href="' +
temp[0].AppUri +
'" aria-expanded="false"><span class="hide-menu">' +
'" aria-expanded="false"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-corner-down-right"><polyline points="15 10 20 15 15 20"/><path d="M4 4v7a4 4 0 0 0 4 4h12"/></svg><span class="hide-menu">' +
Object.keys(donnees.myapplications[i].Applications[f]) +
" </span></a>";
}
@ -60,17 +62,20 @@
}
menuHtml += "</ul>";
document.getElementById("menuTestLemon2").innerHTML = menuHtml;
document.getElementById("menuTestLemon2").innerHTML = menuHtml; // on récupère l'entièreté du menu créé puis on le stocke dans la div contenant l'id menuTestLemon2
// Ajout du bloc a la page accueil
var blocLemon = "";
for (var i = 0; i < donnees.myapplications.length; i++) {
// nommage id div pour boucle du bloc i pour drag and drop
var id = "row-" + i;
blocLemon +=
'<div class="col-lg-12 draggable"><div class="mb-2 shadow-lg"><div class="card my-2"><div class="card-header rounded-top" style="background-color: #1f3889"><h4 class="card-title text-light">' +
`<div class="col-lg-12"><div class="mb-2 shadow-lg"><div class="card my-2"><div class="card-header rounded-top" style="background-color: #1f3889"><h4 class="card-title text-light">` +
donnees.myapplications[i].Category +
'<span></span></h4></div><div class="card-body"><div class="row">';
`<span></span></h4></div><div class="card-body"><div class="row" id="${id}">`; // ajout de le l'id dans le html avec le numéro de boucle
for (
var f = 0;
f < donnees.myapplications[i].Applications.length;
@ -81,20 +86,82 @@
);
blocLemon +=
'<div class="col-md-4"><div class="border-dark text-center h-100 shadow-sm "><a title="' +
'<div class="col-md-4 my-3"><a target="_blank" class="border-dark text-center" title="' +
temp[0].AppDesc +
'" href="' +
temp[0].AppUri +
'"><div class="col-12 pt-3"><h5 class="card-title">' +
'"><div class="col-12 py-3 h-100 shadow-lg"><h5 class="card-title">' +
Object.keys(donnees.myapplications[i].Applications[f]) +
'</h5><p class="text-muted">' +
temp[0].AppDesc +
"</p></div></a></div></div>";
"</p></div></a></div>";
}
blocLemon += "</div></div></div></div></div></div>";
}
document.getElementById("blocLemonCustom").innerHTML = blocLemon;
document.getElementById("blocLemonCustom").innerHTML = blocLemon; // ajout du html dans la div avec l'id blocLemonCustom
// récupère le nombre de div enfante de l'element blocLemonCustom
const htmlDoc = document.getElementById("blocLemonCustom");
const box = htmlDoc.children.length;
for (var f = 0; f < box; f++) {
// récup des éléments du bloc dont l'id contient row-n
var temps = document.getElementById("row-" + f);
Sortable.create(temps, {
animation: 150,
store: {
// ajout de la sauvegarde des emplacements de chaque blocs au rafraichissement
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group);
return order ? order.split("|") : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(
sortable.options.group,
order.join("|")
);
},
},
});
}
var el = document.getElementById("blocLemonCustom");
new Sortable.create(el, {
animation: 150,
store: {
// ajout de la sauvegarde des emplacement de chaque blocs au rafraichissement
/**
* Get the order of elements. Called once during initialization.
* @param {Sortable} sortable
* @returns {Array}
*/
get: function (sortable) {
var order = localStorage.getItem(sortable.options.group);
return order ? order.split("|") : [];
},
/**
* Save the order of elements. Called onEnd (when the item is dropped).
* @param {Sortable} sortable
*/
set: function (sortable) {
var order = sortable.toArray();
localStorage.setItem(sortable.options.group, order.join("|"));
},
},
});
},
});
});

@ -76,6 +76,7 @@ class PleiadeSSOapiFieldsConfig extends ConfigFormBase {
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}

Loading…
Cancel
Save