Skip to content

Documentation, trucs et astuces pour l'utilisation de l'environnement de développement de Primo explore

Notifications You must be signed in to change notification settings

jsicot/Memento-Primo-dev

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 

Repository files navigation

Memento-Primo-dev

Pré-requis

Techonologies utilisées

  • NodeJS : framework de développement Javascript
  • Gulp :un task runner qui permet d'automatiser certaines tâches de développement (création d'un serveur web local, rafraîchissement automatique du navigateur à chaque modification de fichier, préprocesseurs Sass ou LESS, optimisation des CSS, JavaScript et images)
  • Npm : un gestionnaire de « packages » (ie librairies, modules, plugins) Node.js

Philosophie et objectifs

  • Tout client (quelque soit sa configuration) doit pouvoir créer facilement une vue pour son institution
  • Possibilité d'intervenir sur de nombreux éléments sans forcément toucher au JS
  • La personnalisation est possible directement en local, permet de se libérer du backend de Primo. Aucun accès ssh, sftp au serveur distant n'est nécessaire
  • Joue le rôle de serveur proxy en utilisant l'API REST de Primo
  • S'appuie sur le customization package, c-à-d un ensemble de fichiers (HTML, CSS et JS + Images) qui permettent de surcharger/outrepasser les templates natifs de l'interface Primo Explore
  • ExLibris a prévu de nombreuses directives permettant de hooker l'interface

Installation. todo.

Optionnel : installer Git.

  1. Télécharger (ou cloner via git) l'environnement de développement via Github

    • git clone https://github.com/ExLibrisGroup/primo-explore-devenv.git
    • choisir de préférence la dernière version stable (dernier tag)
# Get new tags from the remote
$ git fetch --tags
 
# Get the latest tag name
$ latestTag=$(git describe --tags `git rev-list --tags --max-count=1`)
 
# Checkout the latest tag
$ git checkout $latestTag
  1. Installer nodejs v6.9.2

  2. Installer Npm : npm install npm@3.3.12 -g

  3. Installer Gulp : npm install -g gulp

  4. Aller dans le dossier racine de l'environnement de dev : cd /path/to/your/project/folder/primo-explore-devenv

  5. Installer les dépendances nodesjs (ie packages npm) : npm install

  6. Télécharger ou cloner le primo-explore-package) depuis Github et le placer dans le dossier /path/to/your/project/folder/primo-explore-devenv/primo-explore/custom

  7. Renommer ce dossier en fonction de l'identifiant de votre vue Primo

  8. Éditer le fichier de configuration Gulp (dans /path/to/your/project/folder/primo-explore-devenv/gulp/config.js (ici) pour changer le proxy server : var PROXY_SERVER = http://your-server:your-port.

    • Utiliser l'url de l'instance production ou de la sandbox de votre frontend Primo. La vue déclarée ci-dessus doit exister.
    • Si votre instance est en https, indiquez cette dernière avec le port, comme ceci : var PROXY_SERVER = https://your-server:443
  9. Se placer dans le dossier de l'environnement dev pour lancer le serveur local via la commande : gulp run --view <VIEW_CODE>

> gulp run --view <VIEW_CODE>
[11:30:35] Starting 'connect:primo_explore'...
[11:30:35] Finished 'connect:primo_explore' after 111 ms
[11:30:35] Starting 'reinstall-primo-node-modules'...
[11:30:35] Finished 'reinstall-primo-node-modules' after 78 μs
[11:30:35] Starting 'watch-js'...
[11:30:35] Finished 'watch-js' after 21 ms
[11:30:35] Starting 'watch-custom-scss'...
[11:30:35] Finished 'watch-custom-scss' after 50 μs
[11:30:35] Starting 'watch-css'...
[11:30:35] Finished 'watch-css' after 5.32 ms
[11:30:35] Starting 'setup_watchers'...
[11:30:35] Finished 'setup_watchers' after 2.13 ms
[11:30:35] Starting 'custom-html-templates'...
[11:30:35] Finished 'custom-html-templates' after 17 ms
[11:30:35] Starting 'custom-js'...
[11:30:35] Finished 'custom-js' after 14 ms
[11:30:35] Starting 'custom-scss'...
[11:30:35] Finished 'custom-scss' after 5.86 μs
[11:30:35] Starting 'custom-css'...
[BS] Access URLs:
 -------------------------------------
       Local: http://localhost:8003
 -------------------------------------
          UI: http://localhost:3001
 -------------------------------------
- **VIEW_CODE** = Identifiant de la vue et nom du customization package.
- **Astuce** : pour connaître l'ensemble des commandes disponibles avec Gulp : `gulp -T`
  1. Ouvrir votre navigateur à l'adresse : localhost:8003/primo-explore/?vid=<VIEW_CODE>, un frontend primo est visible. Tout est OK.

Exemples de personnalisation

Structure du customization package

├── css
│   ├── custom1.css
│   ├── README.md
├── html
│   ├── home_en_US.html
│   └── README.md
├── img
│   └── README.md
├── js
│   ├── custom.js
│   └── README.md
├── README.md
└── showDirectives.txt

Personnalisation des CSS

Changer les couleurs

  1. Copier le fichier colors.json disponible à l'emplacement /path/to/your/project/folder/primo-explore-devenv/colors.json dans /path/to/your/project/folder/primo-explore-devenv/primo-explore/custom/<VIEW_CODE>
  2. Éditer ce fichier. Exemple :
{
  "primary": "#53738C",
  "secondary" : "#A9CDD6",
  "backgroundColor" : "white",
  "links": "#5C92BD",
  "warning": "tomato",
  "positive": "#0f7d00",
  "negative": "gray",
  "notice": "#e08303"
}
  1. Lancer la commande : gulp app-css --view <VIEW_CODE>
    • génère un thème pour votre instance avec les couleurs définies
    • un fichier app-colors.css est créé dans votre customization package à l'emplacement : /path/to/your/project/folder/primo-explore-devenv/primo-explore/custom/<VIEW_CODE>/css/app-colors.css

Autres exemples

Astuce utiliser la console web pour identifier les sélecteurs css que vous souhaitez outrepasser/personnaliser. Précaution lorsqu'on joue avec les css : ne pas casser le côté responsive de l'interface.

Exemple : inverser le main menu et la search bar
  • Éditer le custom1.css
.header.topbar-wrapper {
    flex-direction: column-reverse;
}

Primo Explore utilise beaucoup le flex display, ce qui permet de faire beaucoup de choses pour modifier l'affichage avec de simples déclarations css

Astuces

Ne pas modifier directement le custom1.css.

L'ensemble des fichiers css présents dans le dossier primo-explore/custom/<VIEW_CODE>/css seront agrégés dans custom1.css.

Il est également possible d'utiliser un preprocesseur CSS de type Sass afin de mieux organiser ses développements sur les css.

Utiliser SCSS/SASS avec Gulp

Créez et placez vos fichiers .scss dans un dossier scss à la racine de votre custom package view primo-explore/custom/<VIEW_CODE>/scss. Ensuite pour compiler automatiquement vos fichiers .scss, vous pouvez utiliser l'option --useScss avec Gulp :

> gulp run --view <VIEW_CODE> --useScss --browserify

Alternative utilisation de node-sass :

Depuis la racine de primo-explore-devenv

./node_modules/.bin/node-sass --watch --source-map true --source-map-contents --output primo-explore/custom/<VIEW_CODE>/css primo-explore/custom/<VIEW_CODE>/css/sass/main.scss

Extraire les fichiers SCSS/SASS sources avec Gulp

Possibilité d'extraire les fichier .scss natifs de primo avec la ligne de commande suivante :

gulp extract-scss-files

Pour en savoir plus

Personnalisation via Javascript

Création du Package.json

Npm init -y

Le package.json va permettre de renseigner à npm les métadonnées de notre projet ainsi que des dépendances utilisées.

Identifier les directives disponibles

Déboguage des directives/components : utilisation de la console web de Chrome.

La console web permet d'avoir accès à une partie du code source = documentation principale

angular.reloadWithDebugInfo(); // important !! pour lancer primo en mode debug. A exécuter à chaque utilisation.
angular.element($0).scope().$ctrl //apres avoir inspecté une directive

L'ensemble des directives en prm-xxx-after permettent de créer un nouveau component.

Utiliser le bookmarklet fourni dans le customisation package : showDirectives.txt pour afficher l'ensemble des directives disponibles sur une page données.

javascript:(function(){var%20script=document.createElement(%22SCRIPT%22);script.src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js';script.type='text/javascript';document.getElementsByTagName(%22head%22)[0].appendChild(script);var%20checkReady=function(callback){if(window.jQuery){callback(jQuery)}else{window.setTimeout(function(){checkReady(callback)},100)}};checkReady(function($){$('primo-explore').find('[parent-ctrl=%22$ctrl%22]').each(function(){$(this).append('<a%20href=%22#%22%20title=%22'+$(this)[0].outerHTML.replace(/</g,'').replace(/>/g,'').replace(/\//g,'').replace(/%22/g,'').replace(/parent-ctrl./g,'').replace(/-([a-z])/g,function(m,w){return%20w.toUpperCase()}).replace(/\$ctrl(.*)/g,'')+'%22%20style=%22display:block;height:auto;color:black;%22>Hover%20for%20id</a>')})})})();

Autre bookmarklet qui permet d'avoir accès répidement au pnx id, à la noctice source et au pnx : https://github.com/gabriele-h/PrimoNUIShow

Exemple : récupérer l'élément puis le controleur de prm-search-bar
e = angular.element(document.querySelector('prm-search-bar'));
c = e.controller('prm-search-bar');
Fonctions utiles (source)
Lister tous les components
function getComponents() {
let tags = document.getElementsByTagName('*');
let components = [];
for (let tag of tags) {
  let tagName = tag.localName;  
  if (/^prm-/.test(tagName)){
    let component = {name: tagName, obj:angular.element(tag)};
    components.push(component);
  }
}
    return components;
}
Retourner l'objet scope d'un component donné
function getComponentScope(componentName) {
let app = getComponents().filter((f)=>f.name===componentName)
.map((m)=>angular.element(m.obj[0]).scope())

return app;
}
Retourner l'objet controller d'un component donné
function getComponentCtrl(componentName) {
    return getComponentScope(componentName).map((m)=> (m.$ctrl || m.$$childHead.$ctrl))
}
exemple : récupérer un ensemble de résultats depuis la console web
var prmSearchEl = angular.element(document.querySelector('prm-search'));
var prmSearchScope = prmSearchEl.scope();
var resultSet = prmSearchScope.$$childTail.$ctrl.searchResults;
console.log(resultSet); // Tous les résultats
console.log(resultSet[0]["@id"]); // URI du premier résultat
console.log(resultSet[0].pnx.display.title); // Titre du premier résultat

Installer un module Npm

De nombreux modules ont déjà été réalisés/partagés par la communauté : https://www.npmjs.com/search?q=primo-explore

Pour faciliter le déploiement de modules, il est conseillé d'utiliser Browserify.

Browserify : simplifie l'écriture du code et l'integration des packages npm.

Même conseil que pour les css, ne pas éditer directement le custom.js Créer un fichier main.js (en copiant le contenu du custom.js) dans le dossier primo-explore/custom/<VIEW_CODE>/js.

Lancer le serveur local avec Browserify : gulp run --view <VIEW_CODE> --browserify

Cela permet d'utiliser l'environnement de développement avec la méthode ES6. Le main.js et tout code javascript sont automatiquement transpilés dans le custom.js avec rechargement navigateur pour voir les modifications en live.

Exemple : installation du module Unpaywall
cd primo-explore/custom/<VIEW_CODE>
npm install primo-explore-oadoi-link --save-dev
Éditer le fichier main.js
//Ajouter la ligne suivante en haut du fichier
import 'primo-explore-oadoi-link';
//Ajouter oaidoi dans les modules angulars appelée au niveau de l'application
    var app = angular.module('viewCustom', [
    										'angularLoad',
											'oadoi'
    										]);
 //Ajouter les variables nécessaires au fonctionnement du module
    app
	  .constant('oadoiOptions', {
	  	"imagePath": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAk1BMVEX///81vfYqufWy7eNUwus3vvZ92uWp6+IuvPcoufYxvfjZ8PlUx/XQ9urV7vn6//3I6fVgxeNGwvYxtu1Yv92E3eVay/Hq+/SI3+Nzy+Ch6OJ01uiw4O1Mxfjy/fjE8+e95fGT1eRnxuCk3Oljz+1Fu+x7ytpSu9+J0OBLuedYvt+s4OuS2eaU4+LZ+O3J9Oht1OtlyPIDAAADeklEQVR4nO2aa3fiIBCGBY0OWV3XEOttTdN2Y2/W9v//uo0b04uGzEDgcE6X92PCME9gYIDQ6wUFBQUFBX0SexcMCJrNVvu7/JcTAAZEsahY7Z9tQTBTAefJbO8RoGK4ff7hEaAU58WDV4BjM6w6hUNngCODiH56BSgRiju/AGVH3Bp2hCWAMhyLG78AZSMYBYI9gBKBGTSCTYCyEXZ+AcpI0O4GywBspktgG4CJJz0E6wBMzDwDMKGVIB0AMK2h4AIA5G+/AGVuoicGcp28EpBK8xk5Dqjek/m6fz162WwZCYGT10kkgGjTX5zKTydjzgnI0h4Av5qc2WQvBARqXkI/hc+nl1YJTkCNQ/T7101WizFKIFZ2ABr9kwhYbgGAv32UzA6TxafeeEVHAydNR61VQFIHfy97SyIWjecfAYk2ASdlpfYqRnWx/vY4BQFwGNaP8E7gXQFgXDf58mPsi7oN+u4B3jtAfKl2e3qMzwaU6bDNfnMqc/gab+LUCxM0DAtCRmizr4fg8PzF4d/jbIsRUMZBm/1rVWQRnde7rF68YX1AmYxazKH60Mtog3H1YokBxAW+QG0DOI2B+aWf6sUaHwf46owAsFEBjFAAGKBh2GZexcAiuYw1KgCTaE5ss95eZ1l2+NPghgzA0YOLdvvjqWCTyADw1A1AJTJAXHgGqIv6A0AT0rcHgACATYVqS66UOHXsWhAmAiwdqQw3C8SwUj9C1gSmALxhO9RMgDQCYMlABUD035uO25vAFACdwN7VkKxtAERkgCECYBgD9gAMh+H3ATDNBQHg2wAAWpFrgIFnAI6e1jkGwI+t3QIQdqduAeAWtXcKEONbQ7cAQDi1dwqAjwHHAIQecAtAOat1CYCuBVwDdDoptQCAnw20AJCX5b0rJYAg/bhSWS9pO5NJwwlW/Q20H2dK86uXPq6RemcGj7S/6Cp7pt6bfpZ6W4SfjyEAXZUS/5268k+OYkf+8fNBtwCxzP0CUNKgQwBINe6xuAB41LnX5sA/5Br+HQDE5KsDbgBiqXe30bZ/TffWAUD7aqdl/6Q1iDsAcZ/7BACjS6XW3Mfi3sS/NQCQO7PLzZb881Tj/pp1ACH177JaBIjlrsvt9q7egWvlPtsAINMb84v1HQEAuDSYeLoDlI65LNJOHW8OEEk5SFcPecd2DwoKCgr63/UXnxY8Wl1A45AAAAAASUVORK5CYII=",
	  	"email": "yourmail@home.fr"
	  });

Créer un component simplement : exemple d'un menu

Éditer le main.js, ajouter :

	app.component('prmTopBarBefore', {
	     templateUrl: 'custom/<VIEW_CODE>/html/customnav.html'
	});

Dans le dossier html du customization package, créer un nouveau fichier customnav.html avec le contenu suivant :

<prm-customnav>
<div layout="row" layout-padding layout-align="space-between center">
<div>
    <md-button>Accueil</md-button>
    <md-button>Bibliothèques</md-button>
    <md-button>Services</md-button>
    <md-button class="hide-xs">Collections</md-button>
     <md-button class="hide-xs">Ressources</md-button>
     <md-button class="hide-xs">Actualités</md-button>
    <md-menu>
        <md-button md-menu-origin ng-click="$mdOpenMenu()">Aide et Formation</md-button>
        <md-menu-content width="2">
            <md-menu-item>
                <md-button>Ateliers de la BU</md-button>
            </md-menu-item>
            <md-menu-item>
                <md-button>Guides en ligne</md-button>
            </md-menu-item>
              <md-menu-item>
                <md-button>RDV avec un bibliothécaire</md-button>
            </md-menu-item>
        </md-menu-content>
    </md-menu>
</div>
<div class="nav-buttons">
    <md-button class="md-raised md-accent">Mon compte lecteur</md-button>
</div></prm-customnav>

Enfin, au niveau des css ajouter :

prm-topbar {
    height: 100%;
}
prm-topbar .top-nav-bar {
    height: 60px;
}
prm-customnav .layout-padding {
    background: #333;
    color: #FFF;
}
prm-logo .logo-image, prm-logo img {
    max-height: 40px;
}

Création d'un module avec appel d'un webservice externe

Créer un fichier intitulé sfxHoldings.module.js dans primo-explore/custom/<VIEW_CODE>/js avec le code ci-dessous :

angular.module('sfxHoldings', []).component('prmViewOnlineAfter', {
  bindings: { parentCtrl: '<' },
  controller: function controller($scope, $http, $element, sfxholdingsService) {
    this.$onInit = function () {
      var obj = $scope.$ctrl.parentCtrl.item.linkElement.links[0];
      if (obj.hasOwnProperty("getItTabText") && obj.hasOwnProperty("displayText") && obj.hasOwnProperty("isLinktoOnline") && obj.hasOwnProperty("link")) {
        if (obj['displayText'] == "openurlfulltext") {
	      console.log(obj);
	      console.log(obj['link']);
          var openurl = obj['link'];
          var openurlSvc = openurl.replace("http://acceder.bu.univ-rennes2.fr/sfx_33puedb","https://catalogue.bu.univ-rennes2.fr/r2microws/getSfx.php");
          var response = sfxholdingsService.getSfxData(openurlSvc).then(function (response) {
            var holdings = response.data;
            if (holdings === null) {
	            
            } else {
	          angular.element(document.querySelector('prm-view-online div a.arrow-link.md-primoExplore-theme'))[0].style.display = "none"; 
// 	          console.log(holdings);
              $scope.sfxholdings = holdings;
            }
          });
        } 
      } 
    };
  },
  template: `<prm-spinner class="inline-loader display-inline dark-on-light half-transparent" ng-if="sfxloading"></prm-spinner>

<div ng-if="sfxholdings" id="sfxholdings">
	<h3 class="section-title">En Ligne :</h3>
    <md-list class="separate-list-items margin-bottom-medium padding-bottom-zero">
        <md-list-item class="md-2-line _md-no-proxy _md" ng-repeat="(index, holding) in sfxholdings">
        <a class="neutralized-button layout-full-width layout-display-flex md-button md-ink-ripple layout-row" tabindex="0" layout="flex" href="{{holding.href}}" target="_blank" md-ink-ripple="red" role="button">
                <div layout="row" flex="100" layout-align="space-between center" class="layout-align-space-between-center layout-row flex-100">
                    <div class="md-list-item-text layout-wrap layout-row flex" layout="row" layout-wrap="" flex="">
                        <div flex="" flex-xs="100" class="flex-xs-100 flex">
                        <h3>{{holding.title}}</h3>
                            <p><span class="availability-status available">Accès</span>
                            	<span ng-if="holding.coverage">, </span>
								<span>{{holding.coverage}}</span></p>
						</div>
                        <div layout-align="end center" layout="row" layout-wrap="" flex-xs="100" flex-sm="30" flex="" class="list-item-actions layout-wrap layout-align-end-center layout-row flex-xs-100 flex-sm-30 flex"></div>
                    </div>
                    <prm-icon ng-if="!$ctrl.isOvp()" class="padding-right-small" icon-type="svg" svg-icon-set="action" icon-definition="ic_open_in_new_24px">
                        <md-icon md-svg-icon='action:ic_open_in_new_24px'></md-icon>
                        <prm-icon-after parent-ctrl="$ctrl"></prm-icon-after>
                    </prm-icon>
                </div>
                <div class="md-ripple-container" style=""></div>
            </div>
        </md-list-item>
    </md-list>
</div>
`
}).factory('sfxholdingsService', ['$http', function ($http) {
  return {
    getSfxData: function getSfxData(url) {
      return $http({
        method: 'JSONP',
        url: url
      });
    }
  };
}]).run(function ($http) {
  // Necessary for requests to succeed...not sure why
  $http.defaults.headers.common = { 'X-From-ExL-API-Gateway': undefined };
});

Éditer ensuite le main.js pour ajouter :

import { sfxHoldings } from './sfxHoldings.module';

Important : il faut nécessaire de mettre le web service dans une liste blanche (utilisation de $sceDelegateProvider.resourceUrlWhitelist() ou $sce.trustAsResourceUrl()) pour autoriser les requêtes http externes.

	app.config(['$sceDelegateProvider', function ($sceDelegateProvider) {
	  var urlWhitelist = $sceDelegateProvider.resourceUrlWhitelist();
	  urlWhitelist.push('https://catalogue.bu.univ-rennes2**');
	  $sceDelegateProvider.resourceUrlWhitelist(urlWhitelist);
	}]);

Utile : Dépôt Github proposant un environnement de dev pour écrire des plugins : https://github.com/alliance-pcsg/primo-plugin-devenv

Personnalisation du HTML

Suit une convention de nommage. Exemples pour modifier la page d'accueil :

home_en_US.html > page d'accueil pour l'anglais home_fr_FR.html > page d'accueil pour le français

Astuce : les templates de primo sont accessibles depuis la console web > sources > primo-explore > lib > templates.js

Il est possible d'outrepasser n'importe quel template de cette liste en utilisant la méthode suivante :

angular.module('primo-explore.config').run(['$templateCache', function($templateCache) {
    $templateCache.put('components/search/searchBar/search-bar.html','<votre-code></votre-code-htm>');
}]);

Personnalisation des images (logo, images pour les types de document, favicon)

Simplement déposer les images dans le dossier img. Exemple pour les images des types de document : icon_.png (se référer aux code tables dans le backend Primo).

Astuce :

  • les icônes utilisées dans l'UI Primo sont définies dans le fichier webpack:///www/components/appConfig/iconConfig.ts (accès via console web)
  • la source svg des icônes est disponible au chemin : /primo-explore/img/svg/svg-primo-ui.svg
  • pour appeler une icone : <prm-icon icon-type="{type}" svg-icon-set="{iconSet}" icon-definition="{icon}"></prm-icon-after>

Générer l'archive de son customization package pour l'uploader dans le backend Primo

  • gulp create-package

Si vous avez utilisé des directives import pour appeler les différents packages JS, il peut être nécessaire de demander à gulp de rendre le code compatible avec le navigateur par l'utilisation du paramètre --browserify. En l'absence de cette option, le navigateur retournera des erreurs indiquant qu'il ne connaît pas la fonction require :

  • gulp create-package --browserify

Choisir le numéro correspondant au nom de votre vue et cliquer sur entrée. Le fichier zip est localisé dans /path/to/your/project/folder/primo-explore-devenv/packages

Proposer un éditeur de vue avec une IHM, le tout adossé à un "app store" pour étendre les fonctionnalités de Primo à l'aide de modules installable en un clic. Un service qui sera probablement hébergé directement par ExLibris.

Primo Studio

webinar

tuto pour publier un addon dans NPM puis PrimoStudio

A Repository File of Primo-explore projects generated by the ELUNA/IGeLU Primo Communities

Sources utilisées

Exemples d'institutions utilisant la NUI + dépôts Github

About

Documentation, trucs et astuces pour l'utilisation de l'environnement de développement de Primo explore

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published