From 91379d1e68feebe39c2513e39487f32d1661b8a1 Mon Sep 17 00:00:00 2001
From: gloas <gloas@afi-sa.fr>
Date: Tue, 28 Apr 2020 11:43:52 +0200
Subject: [PATCH] wip on theme store

---
 VERSIONS                                      |   5 +
 .../admin/controllers/ProfilController.php    |  14 ++
 library/Class/Profil.php                      |  91 ++++++--
 library/Class/Systeme/Widget/Section.php      |   5 +
 .../Class/Systeme/Widget/Section/Footer.php   |   5 +
 .../Class/Systeme/Widget/Section/Header.php   |   5 +
 library/Class/Template/Settings.php           |   1 -
 library/Class/Template/Update.php             |  32 +++
 library/ZendAfi/Form/Decorator/Custom.php     |   2 +-
 library/ZendAfi/View/Helper/Div.php           |   3 +
 .../ZendAfi/View/Helper/FonctionsAdmin.php    |   4 +
 library/startup.php                           |   2 +-
 .../Intonation/Assets/css/intonation.css      |  31 ++-
 .../Library/FormCustomizer/Abstract.php       |  27 ++-
 .../Library/FormCustomizer/Template.php       |  20 +-
 .../Library/FormCustomizer/Widget/Default.php |   1 +
 .../templates/Intonation/Library/Settings.php |  25 ++-
 .../Library/View/Wrapper/Abstract.php         |   6 +-
 .../Library/View/Wrapper/ActivitySession.php  |   5 +-
 .../Library/View/Wrapper/Article.php          |  10 +-
 .../Library/View/Wrapper/Author.php           |   5 +-
 .../Library/View/Wrapper/Domain.php           |  11 +-
 .../Intonation/Library/View/Wrapper/Hold.php  |   2 +-
 .../Intonation/Library/View/Wrapper/Item.php  |   2 +-
 .../Library/View/Wrapper/Library.php          |   5 +-
 .../Library/RichContent/Navigation.php        |   5 +
 .../Intonation/Library/View/Wrapper/Loan.php  |   2 +-
 .../Library/View/Wrapper/Newsletter.php       |   9 +-
 .../Library/View/Wrapper/PNBLoan.php          |   2 +-
 .../Intonation/Library/View/Wrapper/Pro.php   |   2 +-
 .../Library/View/Wrapper/Record.php           |  45 ++--
 .../View/Wrapper/Record/RichContent.php       |   4 +-
 .../Library/View/Wrapper/RendezVous.php       |   2 +-
 .../Library/View/Wrapper/Review.php           |   3 +-
 .../Intonation/Library/View/Wrapper/Rss.php   |   2 +-
 .../Library/View/Wrapper/RssItem.php          |   2 +-
 .../Library/View/Wrapper/Search.php           |   2 +-
 .../Library/View/Wrapper/SearchHistory.php    |   2 +-
 .../Library/View/Wrapper/Selection.php        |   5 +-
 .../Library/View/Wrapper/Suggestion.php       |   2 +-
 .../Intonation/Library/View/Wrapper/User.php  |   2 +-
 .../Library/Widget/Carousel/Form.php          |  26 ++-
 .../Library/Widget/Carousel/Record/View.php   |   2 +-
 .../Library/Widget/Carousel/View.php          |  41 +++-
 .../Intonation/Library/Widget/Login/View.php  |  16 ++
 .../Intonation/Library/Widget/Search/View.php |   4 +-
 .../View/Admin/ProfileComposition.php         |   6 +-
 .../Intonation/View/Admin/TagEditSection.php  |  14 +-
 .../Intonation/View/Author/RenderFacets.php   |   2 +-
 .../View/CardifyOnlyDescription.php           |  11 +-
 .../templates/Intonation/View/ColumnBreak.php |  27 +++
 .../Intonation/View/RenderBadges.php          |   4 +-
 .../Intonation/View/RenderExpandable.php      |  35 ++--
 .../templates/Intonation/View/RenderGrid.php  |   3 +
 .../Intonation/View/RenderHorizontalList.php  |   3 +
 .../templates/Intonation/View/RenderList.php  |   3 +
 .../templates/Intonation/View/RenderTree.php  |  78 +++++++
 .../Intonation/View/RenderTruncateList.php    |   3 +
 .../templates/Intonation/View/RenderWall.php  |   3 +
 .../Intonation/View/Search/DomainBrowser.php  |  95 +++++++++
 .../Intonation/View/Search/Result.php         |   9 +
 .../Intonation/View/Search/TextCriteria.php   |   4 +-
 .../templates/Intonation/View/Truncate.php    |   2 +-
 .../Intonation/View/User/Informations.php     |   6 +-
 .../templates/Muscle/Assets/css/muscle.css    |   4 -
 library/templates/Muscle/Library/Settings.php |  28 +--
 .../Polygone/Assets/css/polygone.css          |   4 -
 .../templates/Polygone/Library/Settings.php   |  43 +---
 .../Assets/css/terredumilieu.css              |   4 -
 .../TerreDuMilieu/Library/Settings.php        |  30 +--
 public/admin/js/global.js                     |   2 +-
 public/opac/css/core.css                      |  54 +++++
 scripts/upgrade_db.php                        |   1 +
 .../Templates/MuscleTemplateTest.php          | 194 +++++++++++++++++-
 tests/scenarios/Templates/TemplatesTest.php   |  15 +-
 75 files changed, 940 insertions(+), 246 deletions(-)
 create mode 100644 library/Class/Template/Update.php
 create mode 100644 library/templates/Intonation/View/ColumnBreak.php
 create mode 100644 library/templates/Intonation/View/RenderTree.php
 create mode 100644 library/templates/Intonation/View/Search/DomainBrowser.php

diff --git a/VERSIONS b/VERSIONS
index d168f477bad..49267319466 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,3 +1,8 @@
+28/04/2020 - v8.0.55
+
+ - Magasin de thèmes : correction de l'ordre de chargement des fichiers CSS.
+
+
 27/04/2020 - v8.0.54
 
  - ticket #104297 : Ressources numériques : ToutApprendre : possibilité de lien (pkGroup) pointant sur des catégories spécifiques de ToutApprendre
diff --git a/application/modules/admin/controllers/ProfilController.php b/application/modules/admin/controllers/ProfilController.php
index ca0b78b5983..e6b1fca9bd7 100644
--- a/application/modules/admin/controllers/ProfilController.php
+++ b/application/modules/admin/controllers/ProfilController.php
@@ -321,6 +321,7 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
     }
 
     $enreg = $this->_updateBannerWidgets($profil, $enreg);
+    $enreg = $this->_updateFooterWidgets($profil, $enreg);
 
     if($profil->setCfgAccueil($enreg)->save()) {
       $this->_helper->notify($this->view->_('Page ' . $profil->getLibelle() . ' sauvegardée'));
@@ -345,6 +346,19 @@ class Admin_ProfilController extends ZendAfi_Controller_Action {
   }
 
 
+  protected function _updateFooterWidgets($profil, $enreg) {
+    if(!$parent_profil = $profil->getParentProfil())
+      return $this->_injectDefaultsBannerWidgets($profil, $enreg);
+
+    $temp_profil = (new Class_Profil())->setCfgAccueil($enreg);
+    $parent_profil
+      ->setFooterBoxes($temp_profil->getFooterBoxes())
+      ->save();
+
+    return $enreg;
+  }
+
+
   protected function _injectDefaultsBannerWidgets($profil, $enreg) {
     $required_widgets = $this->getSearchAndLoginWidget($profil->getBoitesDivision(Class_Profil::DIV_BANNIERE));
     foreach( $required_widgets as $id => $module) {
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index 2ff1164cd98..acc8547a930 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -613,15 +613,21 @@ class Class_Profil extends Storm_Model_Abstract {
     return Class_Url::absolute('');
   }
 
-  protected function isModulePreferencesSharedBetweenProfils($module, $type_module) {
+
+  protected function _isModulePreferencesSharedBetweenProfils($module, $type_module) {
     if (isset($module['parent_id']))
-      return false;
+      return '';
 
-    return (
-            (isset($module['division'])  && ($module['division'] == self::DIV_BANNIERE))
-            ||
-            (!isset($module['division']) && ($this->isTypeBoiteInBanniere($type_module)))
-    );
+    if (isset($module['division'])  && ($module['division'] == self::DIV_BANNIERE))
+      return self::DIV_BANNIERE;
+
+    if (isset($module['division'])  && ($module['division'] == self::DIV_FOOTER))
+      return self::DIV_FOOTER;
+
+    if (!isset($module['division']) && ($this->isTypeBoiteInBanniere($type_module)))
+      return self::DIV_BANNIERE;
+
+    return '';
   }
 
 
@@ -637,8 +643,8 @@ class Class_Profil extends Storm_Model_Abstract {
       $cfg_accueil['modules'][$id_module] :
       ['preferences' => []];
 
-    if ($this->isModulePreferencesSharedBetweenProfils($module, $type_module))
-      return $this->getModuleAccueilPreferencesByType($type_module, self::DIV_BANNIERE, $id_module);
+    if ($division_shared = $this->_isModulePreferencesSharedBetweenProfils($module, $type_module))
+      return $this->getModuleAccueilPreferencesByType($type_module, $division_shared, $id_module);
 
     $preferences = [];
     if (array_isset('preferences', $module))
@@ -678,6 +684,15 @@ class Class_Profil extends Storm_Model_Abstract {
       return $this;
     }
 
+    if (isset($module_config['division'])
+        && (self::DIV_FOOTER == $module_config['division'])
+        && $this->hasParentProfil()) {
+      $this->getParentProfil()
+           ->updateModuleConfigAccueil($id_module, $module_config)
+           ->save();
+      return $this;
+    }
+
     $cfg_accueil = $this->getCfgAccueilAsArray();
     $cfg_accueil['modules'][$id_module] = $module_config;
     $this->setCfgAccueil($cfg_accueil);
@@ -755,8 +770,8 @@ class Class_Profil extends Storm_Model_Abstract {
       : ['type_module' => $type_module,
          'preferences' => Class_Systeme_ModulesAccueil::getInstance()->getValeursParDefaut($type_module)];
 
-    if ($this->isModulePreferencesSharedBetweenProfils($module, $type_module))
-      return $this->getModuleAccueilConfigByType($type_module, self::DIV_BANNIERE);
+    if ($division_shared = $this->_isModulePreferencesSharedBetweenProfils($module, $type_module))
+      return $this->getModuleAccueilConfigByType($type_module, $division_shared);
 
     if ($local_config = $this->getLocalModuleAccueilConfig($id_module))
       return $local_config;
@@ -778,6 +793,18 @@ class Class_Profil extends Storm_Model_Abstract {
   }
 
 
+  public function getFooterBoxes() {
+    $cfg_accueil = $this->getCfgAccueilAsArray();
+    $_boxes = [];
+    foreach ($cfg_accueil['modules'] as $id => $module) {
+      if (isset($module['division']) && ($module['division'] == self::DIV_FOOTER))
+        $_boxes[$id] = $module;
+    }
+
+    return $_boxes;
+  }
+
+
   public function setBannerBoxes($widgets) {
     $cfg_accueil = $this->getCfgAccueilAsArray();
     foreach ($cfg_accueil['modules'] as $id => $module) {
@@ -793,15 +820,33 @@ class Class_Profil extends Storm_Model_Abstract {
   }
 
 
+  public function setFooterBoxes($widgets) {
+    $cfg_accueil = $this->getCfgAccueilAsArray();
+    foreach ($cfg_accueil['modules'] as $id => $module) {
+      if ($module['division'] == self::DIV_FOOTER)
+        unset($cfg_accueil['modules'][$id]);
+    }
+
+    foreach($widgets as $id => $config)
+      $cfg_accueil['modules'][$id] = $config;
+
+    $this->setCfgAccueil($cfg_accueil);
+    return $this;
+  }
+
+
   /** @return array */
   public function getLocalModuleAccueilConfig($id_module) {
     $cfg_accueil = $this->getCfgAccueilAsArray();
 
     $banner_boxes = [];
-    if ($this->hasParentProfil())
+    $footer_boxes = [];
+    if ($this->hasParentProfil()) {
       $banner_boxes = $this->getParentProfil()->getBannerBoxes();
+      $footer_boxes = $this->getParentProfil()->getFooterBoxes();
+    }
 
-    $modules_config = $cfg_accueil['modules'] + $banner_boxes;
+    $modules_config = $cfg_accueil['modules'] + $banner_boxes + $footer_boxes;
 
     $module = ['type_module' => null,
                'preferences' => [],
@@ -1570,9 +1615,15 @@ class Class_Profil extends Storm_Model_Abstract {
 
 
   public function hasBoiteInDivision($division, $type_module) {
+    $cfg_accueil = null;
+
     if ($division == self::DIV_BANNIERE and $this->hasParentProfil())
       $cfg_accueil = $this->getParentProfil()->getCfgAccueilAsArray();
-    else
+
+    if ($division == self::DIV_FOOTER and $this->hasParentProfil())
+      $cfg_accueil = $this->getParentProfil()->getCfgAccueilAsArray();
+
+    if (!$cfg_accueil)
       $cfg_accueil = $this->getCfgAccueilAsArray();
 
     $boites = $this->_filterCfgAccueilByDivision($cfg_accueil, $division);
@@ -1592,6 +1643,9 @@ class Class_Profil extends Storm_Model_Abstract {
     if ($division == self::DIV_BANNIERE and $this->hasParentProfil())
       return $this->getParentProfil()->getBoitesDivision($division);
 
+    if ($division == self::DIV_FOOTER and $this->hasParentProfil())
+      return $this->getParentProfil()->getBoitesDivision($division);
+
     if ($division == '5' && Class_AdminVar::isBoitePanierAutoEnabled())
       $this->setBoitePanierInDivisionFive();
 
@@ -1964,10 +2018,15 @@ class Class_Profil extends Storm_Model_Abstract {
     if(!$this->hasParentProfil())
       return;
 
-    if(!$parent_banner_modules = $this->getParentProfil()->getBoitesDivision(self::DIV_BANNIERE))
+    $parent_modules = $this->getParentProfil()->getBoitesDivision(self::DIV_BANNIERE)
+      + $this->getParentProfil()->getBoitesDivision(self::DIV_FOOTER);
+
+    $parent_modules = array_filter($parent_modules);
+
+    if (!$parent_modules)
       return;
 
-    if(!$ids_used_by_parent_profil = array_keys($parent_banner_modules))
+    if(!$ids_used_by_parent_profil = array_keys($parent_modules))
       return;
 
     return $this->doNotUseIds($ids_used_by_parent_profil);
diff --git a/library/Class/Systeme/Widget/Section.php b/library/Class/Systeme/Widget/Section.php
index 6e14ff9bc0b..bc47f1392c5 100644
--- a/library/Class/Systeme/Widget/Section.php
+++ b/library/Class/Systeme/Widget/Section.php
@@ -104,4 +104,9 @@ class Class_Systeme_Widget_Section extends Class_Systeme_Widget_Abstract {
   public function isMain() {
     return $this->getResourcesDefinition()->isMain();
   }
+
+
+  public function isShared() {
+    return false;
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Systeme/Widget/Section/Footer.php b/library/Class/Systeme/Widget/Section/Footer.php
index 267626c065b..65f3f63a72c 100644
--- a/library/Class/Systeme/Widget/Section/Footer.php
+++ b/library/Class/Systeme/Widget/Section/Footer.php
@@ -30,4 +30,9 @@ class Class_Systeme_Widget_Section_Footer extends Class_Systeme_Widget_Section {
   public function getResourcesDefinition() {
     return new Class_Systeme_ModulesAccueil_Section_Footer;
   }
+
+
+  public function isShared() {
+    return true;
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Systeme/Widget/Section/Header.php b/library/Class/Systeme/Widget/Section/Header.php
index 585cc99320a..7a2cfec0fe7 100644
--- a/library/Class/Systeme/Widget/Section/Header.php
+++ b/library/Class/Systeme/Widget/Section/Header.php
@@ -30,4 +30,9 @@ class Class_Systeme_Widget_Section_Header extends Class_Systeme_Widget_Section {
   public function getResourcesDefinition() {
     return new Class_Systeme_ModulesAccueil_Section_Header;
   }
+
+
+  public function isShared() {
+    return true;
+  }
 }
\ No newline at end of file
diff --git a/library/Class/Template/Settings.php b/library/Class/Template/Settings.php
index c278629ea06..132aa7b0dca 100644
--- a/library/Class/Template/Settings.php
+++ b/library/Class/Template/Settings.php
@@ -19,7 +19,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-
 class Class_Template_Settings extends Storm_Model_Abstract {
 
   protected
diff --git a/library/Class/Template/Update.php b/library/Class/Template/Update.php
new file mode 100644
index 00000000000..5068978dad6
--- /dev/null
+++ b/library/Class/Template/Update.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Template_Update {
+  public function run() {
+    $templates = (new Class_Template_Loader)->getTemplates();
+    array_walk($templates,
+               function($template)
+               {
+                 $template->updateSettings();
+               });
+  }
+}
diff --git a/library/ZendAfi/Form/Decorator/Custom.php b/library/ZendAfi/Form/Decorator/Custom.php
index a2086255a8d..8024fa02ee9 100644
--- a/library/ZendAfi/Form/Decorator/Custom.php
+++ b/library/ZendAfi/Form/Decorator/Custom.php
@@ -25,6 +25,6 @@ class ZendAfi_Form_Decorator_Custom extends Zend_Form_Decorator_HtmlTag {
   public function render($content) {
     $view = $this->_element->getView();
     $render = $this->_element->getAttrib('render');
-    return parent::render($render());
+    return parent::render($render($view));
   }
 }
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Div.php b/library/ZendAfi/View/Helper/Div.php
index 756c4b38693..3c0275e891a 100644
--- a/library/ZendAfi/View/Helper/Div.php
+++ b/library/ZendAfi/View/Helper/Div.php
@@ -22,6 +22,9 @@
 
 class ZendAfi_View_Helper_Div extends ZendAfi_View_Helper_BaseHelper {
   public function div($attributes = [], $content = '') {
+    if ( null === $content)
+      $content = '';
+
     return $this->_tag('div',
                        $content,
                        $attributes);
diff --git a/library/ZendAfi/View/Helper/FonctionsAdmin.php b/library/ZendAfi/View/Helper/FonctionsAdmin.php
index d435540400d..0ade00e4b78 100644
--- a/library/ZendAfi/View/Helper/FonctionsAdmin.php
+++ b/library/ZendAfi/View/Helper/FonctionsAdmin.php
@@ -226,6 +226,10 @@ class ZendAfi_View_Helper_FonctionsAdmin extends ZendAfi_View_Helper_BaseHelper
        && ($parent = Class_Profil::getCurrentProfil()->getParentProfil()))
        $id_profil = $parent->getId();
 
+    if(Class_Profil::DIV_FOOTER == $this->division
+       && ($parent = Class_Profil::getCurrentProfil()->getParentProfil()))
+      $id_profil = $parent->getId();
+
     return $id_profil;
   }
 }
\ No newline at end of file
diff --git a/library/startup.php b/library/startup.php
index 8bce4740e9b..5e080323996 100644
--- a/library/startup.php
+++ b/library/startup.php
@@ -81,7 +81,7 @@ class Bokeh_Engine {
 
   function setupConstants() {
     defineConstant('BOKEH_MAJOR_VERSION','8.0');
-    defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.54');
+    defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.55');
 
     defineConstant('BOKEH_REMOTE_FILES', 'https://git.afi-sa.net/afi/opacce/');
 
diff --git a/library/templates/Intonation/Assets/css/intonation.css b/library/templates/Intonation/Assets/css/intonation.css
index 3c38d979787..218712f4ecd 100644
--- a/library/templates/Intonation/Assets/css/intonation.css
+++ b/library/templates/Intonation/Assets/css/intonation.css
@@ -246,6 +246,23 @@ pre {
     background: none !important;
 }
 
+.transparent_background .breadcrumb,
+.transparent_background {
+    background: var(--front-transparent-background) !important;
+}
+
+.limit_badges_10 .badge-group .badge:nth-child(n + 11) {
+    display: none;
+}
+
+.limit_badges_5 .badge-group .badge:nth-child(n + 6) {
+    display: none;
+}
+
+.limit_badges_3 .badge-group .badge:nth-child(n + 4) {
+    display: none;
+}
+
 .no_border,
 .no_border * {
     border: 0px solid rgba(0,0,0,0) !important;
@@ -786,16 +803,10 @@ input[id^="select_record"] + * {
     min-width: 1px;
 }
 
-.only_visible_in_viewnotice {
-    display: none;
+.z_index_11 {
+    z-index: 11;
 }
 
-.recherche_viewnotice .only_visible_in_viewnotice {
-    display: block;
+.menu_buttons .button_text {
+    display: none !important;
 }
-
-.badge.only_visible_in_viewnotice .text-truncate {
-    width: auto;
-    max-width: none;
-    white-space: normal;
-}
\ No newline at end of file
diff --git a/library/templates/Intonation/Library/FormCustomizer/Abstract.php b/library/templates/Intonation/Library/FormCustomizer/Abstract.php
index 461553e84eb..a842eaee21b 100644
--- a/library/templates/Intonation/Library/FormCustomizer/Abstract.php
+++ b/library/templates/Intonation/Library/FormCustomizer/Abstract.php
@@ -55,6 +55,29 @@ class Intonation_Library_FormCustomizer_Abstract {
                                         ['label' => $this->_('Classe CSS personnalisée'),
                                          'separator' => ' ',
                                          'multiOptions' => $css]]);
+
+    $this->_form
+      ->addElement('custom',
+                   'classes_documentation',
+                   ['render' => function($view)
+                    {
+                      $html =
+                      $view->tagAnchor('http://wiki.bokeh-library-portal.org/index.php?title=Classes_CSS',
+                                       Class_Admin_Skin::current()->renderActionIconOn('help', $view),
+                                       ['class' => 'ardans_help',
+                                        'style' => 'margin-left: 5px',
+                                        'title' => $this->_('Consulter la documentation sur les classes dans le Wiki Bokeh'),
+                                        'target' => '_blank']);
+                      return $view->tag('script',
+                                        sprintf('$(function() {$("[data-name*=%s]").append("%s");});',
+                                                'boite',
+                                                str_replace('"', "'", $html)));
+                    }]);
+
+    $this->_form
+      ->addToStyleGroup(['boite',
+                         'classes_documentation']);
+
     return $this;
   }
 
@@ -327,7 +350,7 @@ class Intonation_Library_FormCustomizer_Abstract {
       ->addToDisplayGroup(array_map(function($element)
                                   {
                                     return $this->_template->withNameSpace($element);
-                                  },$elements),
+                                  }, $elements),
                         $this->_template->withNameSpace('group'));
       return $this;
     }
@@ -336,7 +359,7 @@ class Intonation_Library_FormCustomizer_Abstract {
       ->addDisplayGroup(array_map(function($element)
                                   {
                                     return $this->_template->withNameSpace($element);
-                                  },$elements),
+                                  }, $elements),
                         $this->_template->withNameSpace('group'),
                         ['legend' => $this->_('Thème'),
                          'order' => static::FIRST]);
diff --git a/library/templates/Intonation/Library/FormCustomizer/Template.php b/library/templates/Intonation/Library/FormCustomizer/Template.php
index 8f13e81e5d7..42e9af65fc3 100644
--- a/library/templates/Intonation/Library/FormCustomizer/Template.php
+++ b/library/templates/Intonation/Library/FormCustomizer/Template.php
@@ -82,7 +82,24 @@ class Intonation_Library_FormCustomizer_Template extends Intonation_Library_Form
                     'fields' => [['name' => $this->_template->withNameSpace('custom_css_class'),
                                   'label' => $this->_('classe')]],
                     'values' => [$this->_template->withNameSpace('custom_css_class') => $this->_template->getCustomCssClass()],
-                    'deleteMessage' => $this->_('cette classe')]);
+                    'deleteMessage' => $this->_('cette classe')])
+
+      ->addElement('custom',
+                   $this->_template->withNameSpace('classes_documentation'),
+                   ['render' => function($view)
+                    {
+                      $html =
+                      $view->tagAnchor('http://wiki.bokeh-library-portal.org/index.php?title=Classes_CSS',
+                                Class_Admin_Skin::current()->renderActionIconOn('help', $view),
+                                ['class' => 'ardans_help',
+                                 'style' => 'margin-left: 5px',
+                                 'title' => $this->_('Consulter la documentation sur les classes dans le Wiki Bokeh'),
+                                 'target' => '_blank']);
+                      return $view->tag('script',
+                                        sprintf('$(function() {$("[for*=%s]").append("%s");});',
+                                                $this->_template->withNameSpace('custom_css_classes'),
+                                                str_replace('"', "'", $html)));
+                    }]);
 
     $this
       ->_addToTemplateGroup(['core_css',
@@ -97,6 +114,7 @@ class Intonation_Library_FormCustomizer_Template extends Intonation_Library_Form
                              'custom_css',
                              'custom_js',
                              'nb_cols',
+                             'classes_documentation',
                              'custom_css_classes'])
       ->_addHydratingMappingGroupTo()
       ->_addResponsiveGroupTo()
diff --git a/library/templates/Intonation/Library/FormCustomizer/Widget/Default.php b/library/templates/Intonation/Library/FormCustomizer/Widget/Default.php
index 295b187d3fd..a462c7efeea 100644
--- a/library/templates/Intonation/Library/FormCustomizer/Widget/Default.php
+++ b/library/templates/Intonation/Library/FormCustomizer/Widget/Default.php
@@ -38,6 +38,7 @@ class Intonation_Library_FormCustomizer_Widget_Default extends Intonation_Librar
                    $this->_template->withNameSpace('show_footer'),
                    ['label' => $this->_('Afficher le pied'),
                     'value' => 1]);
+
     $this->_addCustomElement();
 
     $this->_addToTemplateGroup($this->_getDefaultElementsNames());
diff --git a/library/templates/Intonation/Library/Settings.php b/library/templates/Intonation/Library/Settings.php
index 44983d538e4..b440885f7d1 100644
--- a/library/templates/Intonation/Library/Settings.php
+++ b/library/templates/Intonation/Library/Settings.php
@@ -54,9 +54,16 @@ class Intonation_Library_Settings extends Intonation_System_Abstract {
                                                  'z_index_2',
                                                  'z_index_3',
                                                  'pt-3',
+                                                 'pt-5',
+                                                 'pl-2',
+                                                 'pl-md-3',
+                                                 'pr-md-3',
+                                                 'pb-3',
                                                  'px-3',
                                                  'py-3',
                                                  'm-auto',
+                                                 'ml-auto',
+                                                 'mr-auto',
                                                  'mb-3',
                                                  'mt-3',
                                                  'align-items-center',
@@ -71,7 +78,18 @@ class Intonation_Library_Settings extends Intonation_System_Abstract {
                                                  'text-right',
                                                  'text_small',
                                                  'text_no_transform',
-                                                 'admin_tools_invert_colors'
+                                                 'admin_tools_invert_colors',
+                                                 'border-primary',
+                                                 'border-left',
+                                                 'z_index_11',
+                                                 'transparent_background',
+                                                 'limit_badges_3',
+                                                 'limit_badges_5',
+                                                 'limit_badges_10',
+                                                 'justify-content-start',
+                                                 'justify-content-end',
+                                                 'justify-content-center',
+                                                 'menu_buttons'
                           ],
 
                           'hydrating_mapping' => ['div id site_web_wrapper' => 'container align-self-center no_overflow',
@@ -104,7 +122,7 @@ class Intonation_Library_Settings extends Intonation_System_Abstract {
                                                   'img class img-thumbnail' => '',
                                                   'dl' => 'row',
                                                   'dt' => 'col-12 col-sm-3',
-                                                  'dd' => 'col-12 col-sm-9 d-flex flex-wrap align-content-start',
+                                                  'dd' => 'col-12 col-sm-9',
                                                   'dt class user_info' => 'col-12 col-sm-6',
                                                   'dd class user_info' => 'col-12 col-sm-6',
                                                   'a' => 'text-secondary',
@@ -203,6 +221,7 @@ class Intonation_Library_Settings extends Intonation_System_Abstract {
                                                 'more' => 'class fas fa-ellipsis-h',
                                                 'refresh' => 'class fas fa-sync-alt',
                                                 'lock' => 'class fas fa-unlock-alt',
+                                                'eye' => 'class far fa-eye',
 
                                                 'email' => 'class fas fa-at',
                                                 'phone' => 'class fas fa-phone',
@@ -304,7 +323,7 @@ class Intonation_Library_Settings extends Intonation_System_Abstract {
 
 
   protected function _mergeData($default, $data) {
-    $merged = array_merge($data, $default);
+    $merged = array_merge($default, $data);
     if (count(array_filter(array_keys($default), 'is_string')))
       return $merged;
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Abstract.php b/library/templates/Intonation/Library/View/Wrapper/Abstract.php
index 3790e903d5b..c176f20a230 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Abstract.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Abstract.php
@@ -27,6 +27,7 @@ abstract class Intonation_Library_View_Wrapper_Abstract {
   protected
     $_view,
     $_model,
+    $_context,
     $_context_params = [],
     $_rich_content,
     $_in_js_search = false;
@@ -56,8 +57,9 @@ abstract class Intonation_Library_View_Wrapper_Abstract {
   }
 
 
-  public function setContextParams($params) {
-    $this->_context_params = $params;
+  public function setContext($instance) {
+    $this->_context = $instance;
+    $this->_context_params = $instance->getLinkToAllParams();
     return $this;
   }
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/ActivitySession.php b/library/templates/Intonation/Library/View/Wrapper/ActivitySession.php
index 67ab16b0666..4da4dfb3536 100644
--- a/library/templates/Intonation/Library/View/Wrapper/ActivitySession.php
+++ b/library/templates/Intonation/Library/View/Wrapper/ActivitySession.php
@@ -96,7 +96,8 @@ class Intonation_Library_View_Wrapper_ActivitySession extends Intonation_Library
   public function getDescription() {
     return
       $this->getBadges()
-      . $this->_view->truncate($this->_model->getContenu());
+      . $this->_view->truncate($this->_model->getContenu(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
@@ -169,7 +170,7 @@ class Intonation_Library_View_Wrapper_ActivitySession extends Intonation_Library
                                         $main_title)));
     }
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Article.php b/library/templates/Intonation/Library/View/Wrapper/Article.php
index d727a02a505..378f764e8df 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Article.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Article.php
@@ -23,7 +23,10 @@
 class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wrapper_Abstract {
 
   public function getMainTitle() {
-    return $this->_model->getTitre();
+    return
+      $this->_model->getCacherTitre()
+      ? ''
+      : $this->_model->getTitre();
   }
 
 
@@ -76,7 +79,8 @@ class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wr
 
   public function getDescription() {
     return $this->getBadges()
-      . $this->_view->truncate($this->_model->getSummary());
+      . $this->_view->truncate($this->_model->getSummary(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
@@ -196,7 +200,7 @@ class Intonation_Library_View_Wrapper_Article extends Intonation_Library_View_Wr
                             $value));
     }
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Author.php b/library/templates/Intonation/Library/View/Wrapper/Author.php
index 66c354c8a0a..a1fb0cbe09d 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Author.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Author.php
@@ -165,7 +165,8 @@ class Intonation_Library_View_Wrapper_Author extends Intonation_Library_View_Wra
   public function getDescription() {
     return
       $this->getBadges()
-      . $this->_view->truncate($this->getFullDescription());
+      . $this->_view->truncate($this->getFullDescription(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
@@ -198,7 +199,7 @@ class Intonation_Library_View_Wrapper_Author extends Intonation_Library_View_Wra
                                         $facet_label)));
     }
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Domain.php b/library/templates/Intonation/Library/View/Wrapper/Domain.php
index 110ae636d58..cf418814b87 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Domain.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Domain.php
@@ -43,9 +43,14 @@ class Intonation_Library_View_Wrapper_Domain extends Intonation_Library_View_Wra
 
 
   public function getMainLink() {
-    return new Intonation_Library_Link(['Url' => $this->_view->url(['controller' => 'recherche',
-                                                                    'action' => 'simple',
-                                                                    'id_catalogue' => $this->_model->getId()]),
+    $url = ['controller' => 'recherche',
+            'action' => 'simple',
+            'id_catalogue' => $this->_model->getId()];
+
+    if ($this->_context)
+      $url ['id_module'] = $this->_context->getId();
+
+    return new Intonation_Library_Link(['Url' => $this->_view->url($url),
 
                                         'Image' => Class_Template::current()->getIco($this->_view,
                                                                                      'read-document',
diff --git a/library/templates/Intonation/Library/View/Wrapper/Hold.php b/library/templates/Intonation/Library/View/Wrapper/Hold.php
index 9d9256ad861..9edefc0758d 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Hold.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Hold.php
@@ -207,7 +207,7 @@ class Intonation_Library_View_Wrapper_Hold extends Intonation_Library_View_Wrapp
                 ->setTitle($this->_('Rang de la réservation: %s', $this->_model->getRang())))
     ];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Item.php b/library/templates/Intonation/Library/View/Wrapper/Item.php
index 2c0e802e7fa..7b607fb5aa5 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Item.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Item.php
@@ -141,7 +141,7 @@ class Intonation_Library_View_Wrapper_Item extends Intonation_Library_View_Wrapp
                                     $this->_model->getCodeBarres())))
     ];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Library.php b/library/templates/Intonation/Library/View/Wrapper/Library.php
index 391383275f9..80e62075b22 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Library.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Library.php
@@ -85,7 +85,8 @@ class Intonation_Library_View_Wrapper_Library extends Intonation_Library_View_Wr
     return
       $this->getBadges()
       . $this->_view->renderLibraryOpening($this->_model)
-      . $this->_view->truncate($this->_model->getInscription());
+      . $this->_view->truncate($this->_model->getInscription(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
@@ -174,7 +175,7 @@ class Intonation_Library_View_Wrapper_Library extends Intonation_Library_View_Wr
                             $value));
     }
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Library/RichContent/Navigation.php b/library/templates/Intonation/Library/View/Wrapper/Library/RichContent/Navigation.php
index eb189377780..12072e95cf2 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Library/RichContent/Navigation.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Library/RichContent/Navigation.php
@@ -48,6 +48,11 @@ class Intonation_Library_View_Wrapper_Library_RichContent_Navigation {
       return $this->_list;
 
     $this->_list = Class_Bib::findAllBy(['order' => 'libelle']);
+    $this->_list = array_filter($this->_list, function($library)
+                                {
+                                  return null !== Class_Users::findFirstBy(['id_site' => $library->getId(),
+                                                                            'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]);
+                                });
 
     while ((current($this->_list)->getId()) != $this->_model->getId())
       next($this->_list);
diff --git a/library/templates/Intonation/Library/View/Wrapper/Loan.php b/library/templates/Intonation/Library/View/Wrapper/Loan.php
index b685b0959e2..f983645a98d 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Loan.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Loan.php
@@ -169,7 +169,7 @@ class Intonation_Library_View_Wrapper_Loan extends Intonation_Library_View_Wrapp
                 ->setTitle($this->_('Exemplaire déjà prolongé')))
     ];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Newsletter.php b/library/templates/Intonation/Library/View/Wrapper/Newsletter.php
index 552f836310b..63c4ccd9b4f 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Newsletter.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Newsletter.php
@@ -46,8 +46,7 @@ class Intonation_Library_View_Wrapper_Newsletter extends Intonation_Library_View
          'Title' => $this->_view->_("Me désinscrire à la lettre d'information %s", $this->_model->getTitre()),
          'Image' => Class_Template::current()->getIco($this->_view,
                                                       'selection',
-                                                      'library'),
-         'Popup' => true]
+                                                      'library')]
       : ['Url' => $this->_view->url(['controller' => 'abonne',
                                      'action' => 'subscribe-newsletter',
                                      'id' => $this->_model->getId()]),
@@ -55,8 +54,7 @@ class Intonation_Library_View_Wrapper_Newsletter extends Intonation_Library_View
          'Title' => $this->_view->_("M'inscrire à la lettre d'information %s", $this->_model->getTitre()),
          'Image' => Class_Template::current()->getIco($this->_view,
                                                       'no-selection',
-                                                      'library'),
-         'Popup' => true];
+                                                      'library')];
 
     return new Intonation_Library_Link($params);
   }
@@ -90,7 +88,8 @@ class Intonation_Library_View_Wrapper_Newsletter extends Intonation_Library_View
 
   public function getDescription() {
     $template = $this->_model->newTemplate();
-    return $this->_view->truncate($template->getBodyHTML());
+    return $this->_view->truncate($template->getBodyHTML(),
+                                  ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/PNBLoan.php b/library/templates/Intonation/Library/View/Wrapper/PNBLoan.php
index bf304e56c1d..3a3622e3bb0 100644
--- a/library/templates/Intonation/Library/View/Wrapper/PNBLoan.php
+++ b/library/templates/Intonation/Library/View/Wrapper/PNBLoan.php
@@ -78,7 +78,7 @@ class Intonation_Library_View_Wrapper_PNBLoan extends Intonation_Library_View_Wr
                 ->setTitle($this->_('Bibliothèque de l\'emprunt: %s', $this->_model->getBibliotheque()))),
     ];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Pro.php b/library/templates/Intonation/Library/View/Wrapper/Pro.php
index a2fbf4c3232..c7c4a45ab34 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Pro.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Pro.php
@@ -137,7 +137,7 @@ class Intonation_Library_View_Wrapper_Pro extends Intonation_Library_View_Wrappe
       $badges = $this->_addBookmarkedDomainsToBadges($bookmarked_domains,
                                                      $badges);
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record.php b/library/templates/Intonation/Library/View/Wrapper/Record.php
index f4eec091559..6b615b4f0d2 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record.php
@@ -55,7 +55,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
                                                                                      'read-document',
                                                                                      'library'),
                                         'Text' => $this->_('Voir'),
-                                        'Title' => $this->_('Voir le document "%s" de "%s" de type "%s"',
+                                        'Title' => $this->_('Voir le document %s de %s de type %s',
                                                             $this->getMainTitle(),
                                                             $this->getSecondaryTitle(),
                                                             $this->getDocTypeLabel())]);
@@ -87,7 +87,8 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
 
     $description = $xsl->isEnabled() && $this->getAllowXSL()
       ? $this->_view->Notice_Xsl($xsl)
-      : $this->_view->truncate($this->_model->getResume());
+      : $this->_view->truncate($this->_model->getResume(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
 
     return $this->getBadges() . $description;
   }
@@ -100,7 +101,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
 
 
   public function getDescriptionTitle() {
-    return $this->_('Résumé du document "%s"', $this->getMainTitle());
+    return $this->_('Résumé du document %s', $this->getMainTitle());
   }
 
 
@@ -130,13 +131,6 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
 
   public function getBadges() {
     $badges = [((new Intonation_Library_Badge)
-                ->setTag('div')
-                ->setClass(' pb-1 mb-1 px-0 card-title only_visible_in_viewnotice')
-                ->setText($this->_getFullTitle())
-                ->setTitle($this->_('Compléments de titre pour le document %s',
-                                    $this->_model->getTitrePrincipal(' ')))),
-
-               ((new Intonation_Library_Badge)
                 ->setTag('a')
                 ->setClass('warning fs_1em record_doctype')
                 ->setUrl($this->_view->url(['controller' => 'recherche',
@@ -181,7 +175,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
                                           'library'))
                               : ''))
                   ->setText($this->_model->isNouveaute() ? $this->_('Nouveauté') : '')
-                  ->setTitle($this->_('Le document %s est nouveau dans votre bibliotèque',
+                  ->setTitle($this->_('Le document %s est nouveau dans votre bibliothèque',
                                       $this->_model->getTitrePrincipal(' '))));
 
     $badges = $this->_injectReviewsBadgesInto($badges);
@@ -200,7 +194,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
 
     $badges = $this->_addSerieBadges($badges);
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
@@ -467,7 +461,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
                                            'Image' => Class_Template::current()->getIco($this->_view,
                                                                                         'print',
                                                                                         'utils'),
-                                           'Title' => $this->_('Imprimer "%s"', $this->_model->getTitrePrincipal(' ')),
+                                           'Title' => $this->_('Imprimer %s', $this->_model->getTitrePrincipal(' ')),
                                            'Attribs' => ['target' => '_blank']])
             : '');
   }
@@ -499,19 +493,6 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra
   }
 
 
-  protected function _getFullTitle() {
-    $main = $this->getMainTitle();
-    $titles = $this->_model->getChampNotice(Class_Codification::CODE_TITRE);
-
-    $titles = array_filter($titles, function($title) use ($main)
-                           {
-                             return false === strpos($main, $title);
-                           });
-
-    return implode(BR, $titles);
-  }
-
-
   public function getEmbedMedia() {
     return '';
   }
@@ -632,13 +613,13 @@ class Intonation_Library_View_Wrapper_RecordProReviewsBadge
 
 
   protected function _countTitle() {
-    return $this->_('Nombre d\'avis des professionnels sur le document "%s".',
+    return $this->_('Nombre d\'avis des professionnels sur le document %s.',
                     $this->_recordTitle());
   }
 
 
   protected function _scoreTitle() {
-    return $this->_('Note moyenne des avis des professionnels sur le document "%s".',
+    return $this->_('Note moyenne des avis des professionnels sur le document %s.',
                     $this->_recordTitle());
   }
 }
@@ -664,13 +645,13 @@ class Intonation_Library_View_Wrapper_RecordUsersReviewsBadge
 
 
   protected function _countTitle() {
-    return $this->_('Nombre d\'avis des abonnés sur le document "%s".',
+    return $this->_('Nombre d\'avis des abonnés sur le document %s.',
                     $this->_recordTitle());
   }
 
 
   protected function _scoreTitle() {
-    return $this->_('Note moyenne des avis des abonnés sur le document "%s".',
+    return $this->_('Note moyenne des avis des abonnés sur le document %s.',
                     $this->_recordTitle());
   }
 }
@@ -696,13 +677,13 @@ class Intonation_Library_View_Wrapper_RecordCommunityReviewsbadge
 
 
   protected function _countTitle() {
-    return $this->_('Nombre d\'avis de la communauté sur le document "%s".',
+    return $this->_('Nombre d\'avis de la communauté sur le document %s.',
                     $this->_recordTitle());
   }
 
 
   protected function _scoreTitle() {
-    return $this->_('Note moyenne des avis de la communauté sur le document "%s".',
+    return $this->_('Note moyenne des avis de la communauté sur le document %s.',
                     $this->_recordTitle());
   }
 }
diff --git a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent.php b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent.php
index 000cf5ff0b3..61d33714c5f 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Record/RichContent.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Record/RichContent.php
@@ -37,7 +37,9 @@ class Intonation_Library_View_Wrapper_Record_RichContent extends Intonation_Libr
 
   public function getActions() {
     return $this->_view->div(['class' => 'col-12 px-0 mt-3 record_summary'],
-                             $this->_view->truncate($this->_model->getResume(), 50));
+                             $this->_view->truncate($this->_model->getResume(),
+                                                    ['class' => 'model_description_' . get_class($this->_model)],
+                                                    50));
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/RendezVous.php b/library/templates/Intonation/Library/View/Wrapper/RendezVous.php
index 25bc1659f4e..43fefe8a849 100644
--- a/library/templates/Intonation/Library/View/Wrapper/RendezVous.php
+++ b/library/templates/Intonation/Library/View/Wrapper/RendezVous.php
@@ -101,7 +101,7 @@ class Intonation_Library_View_Wrapper_RendezVous extends Intonation_Library_View
 
     $badges [] = $location;
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Review.php b/library/templates/Intonation/Library/View/Wrapper/Review.php
index b7737d6b646..5f42330fea0 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Review.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Review.php
@@ -123,7 +123,8 @@ class Intonation_Library_View_Wrapper_Review extends Intonation_Library_View_Wra
 
 
   public function getDescription() {
-    return $this->_view->truncate($this->_model->getAvis());
+    return $this->_view->truncate($this->_model->getAvis(),
+                               ['class' => 'model_description_' . get_class($this->_model)]);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Rss.php b/library/templates/Intonation/Library/View/Wrapper/Rss.php
index 7407cff1cd2..074c44961b4 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Rss.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Rss.php
@@ -92,7 +92,7 @@ class Intonation_Library_View_Wrapper_Rss extends Intonation_Library_View_Wrappe
       ->setText($tag)
       ->setTitle($this->_('Tag attribué au flux %s', $this->_model->getTitre()));
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/RssItem.php b/library/templates/Intonation/Library/View/Wrapper/RssItem.php
index ac669864ef4..c72d7277ac7 100644
--- a/library/templates/Intonation/Library/View/Wrapper/RssItem.php
+++ b/library/templates/Intonation/Library/View/Wrapper/RssItem.php
@@ -86,7 +86,7 @@ class Intonation_Library_View_Wrapper_RssItem extends Intonation_Library_View_Wr
                ->setText($this->_model->getPubDate())
                ->setTitle($this->_('Date de diffusion de %s', $this->getMainTitle()))];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Search.php b/library/templates/Intonation/Library/View/Wrapper/Search.php
index f07b4e60a2c..a4c5f0e809b 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Search.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Search.php
@@ -112,7 +112,7 @@ class Intonation_Library_View_Wrapper_Search extends Intonation_Library_View_Wra
                                                       ['class' => 'badge badge-light fs_1em'])))
                 ->setTitle($this->_('Le nombre de documents pour la recherche %s', $this->_model->getLabel())))];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/SearchHistory.php b/library/templates/Intonation/Library/View/Wrapper/SearchHistory.php
index 2b1b8d670f6..c44c9640d88 100644
--- a/library/templates/Intonation/Library/View/Wrapper/SearchHistory.php
+++ b/library/templates/Intonation/Library/View/Wrapper/SearchHistory.php
@@ -42,6 +42,6 @@ class Intonation_Library_View_Wrapper_SearchHistory extends Intonation_Library_V
                 ->setText(date('d/m/Y H:i:s', $criterias->getTime()))
                 ->setTitle($this->_('La date de la recherche %s', $this->_model->getLabel())))];
 
-    return parent::getBadges() . $this->_view->renderBadges($badges);
+    return parent::getBadges() . $this->_view->renderBadges($badges, $this);
   }
 }
\ No newline at end of file
diff --git a/library/templates/Intonation/Library/View/Wrapper/Selection.php b/library/templates/Intonation/Library/View/Wrapper/Selection.php
index 1bef8c357b7..680e8025585 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Selection.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Selection.php
@@ -56,7 +56,8 @@ class Intonation_Library_View_Wrapper_Selection extends Intonation_Library_View_
     return $this->getBadges()
       . BR
       . $this->_('Liste des documents : %s',
-                 $this->_view->truncate(implode(', ', $records_title)));
+                 $this->_view->truncate(implode(', ', $records_title),
+                                        ['class' => 'model_description_' . get_class($this->_model)]));
   }
 
 
@@ -132,7 +133,7 @@ class Intonation_Library_View_Wrapper_Selection extends Intonation_Library_View_
                 ->setTitle($this->_('La date de dernière mise à jour de la sélection %s',
                                     $this->_model->getLibelle())))];
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/Suggestion.php b/library/templates/Intonation/Library/View/Wrapper/Suggestion.php
index 29a2163c7f0..a7d2188ce24 100644
--- a/library/templates/Intonation/Library/View/Wrapper/Suggestion.php
+++ b/library/templates/Intonation/Library/View/Wrapper/Suggestion.php
@@ -163,7 +163,7 @@ class Intonation_Library_View_Wrapper_Suggestion extends Intonation_Library_View
                   ->setText($this->_model->getIsbn())
                   ->setTitle($this->_('ISBN %s', $this->_model->getIsbn())));
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/View/Wrapper/User.php b/library/templates/Intonation/Library/View/Wrapper/User.php
index fb06320c9a7..a8d03ac45ac 100644
--- a/library/templates/Intonation/Library/View/Wrapper/User.php
+++ b/library/templates/Intonation/Library/View/Wrapper/User.php
@@ -257,7 +257,7 @@ class Intonation_Library_View_Wrapper_User extends Intonation_Library_View_Wrapp
                     ->setTitle($this->_('Vous avez %d rendez-vous',
                                         $number_of_rendez_vous)));
 
-    return $this->_view->renderBadges($badges);
+    return $this->_view->renderBadges($badges, $this);
   }
 
 
diff --git a/library/templates/Intonation/Library/Widget/Carousel/Form.php b/library/templates/Intonation/Library/Widget/Carousel/Form.php
index eee8c692002..97451fb33aa 100644
--- a/library/templates/Intonation/Library/Widget/Carousel/Form.php
+++ b/library/templates/Intonation/Library/Widget/Carousel/Form.php
@@ -26,7 +26,8 @@ class Intonation_Library_Widget_Carousel_Form extends ZendAfi_Form_Configuration
     parent::init();
 
     Class_ScriptLoader::getInstance()
-      ->addJQueryReady('checkBoxToggleVisibilityForElement("#link_to_all", $("#all_order, #all_layout, #all_rendering").closest("tr"), true);');
+      ->addJQueryReady('toggleVisibilityForElement("#link_to_all_url", $("#all_layout, #all_rendering").closest("tr"), function(element) {return ! element.val();});')
+      ->addJQueryReady('checkBoxToggleVisibilityForElement("#link_to_all", $("#all_layout, #all_rendering, #link_to_all_text, #link_to_all_title, #link_to_all_url, #link_to_all_to_main_title").closest("tr"), true);');
 
     $this
 
@@ -52,6 +53,25 @@ class Intonation_Library_Widget_Carousel_Form extends ZendAfi_Form_Configuration
                    'link_to_all',
                    ['label' => $this->_('Proposer le lien vers tous les documents')])
 
+      ->addElement('text',
+                   'link_to_all_text',
+                   ['label' => $this->_('Texte du lien vers tous les documents'),
+                    'placeholder' => $this->_('En lire plus')])
+
+      ->addElement('text',
+                   'link_to_all_title',
+                   ['label' => $this->_('Titre du lien vers tous les documents'),
+                    'placeholder' => $this->_('En lire plus sur %s')])
+
+      ->addElement('text',
+                   'link_to_all_url',
+                   ['label' => $this->_('URL du lien vers tous les documents'),
+                    'placeholder' => $this->_('Automatique')])
+
+      ->addElement('checkbox',
+                   'link_to_all_to_main_title',
+                   ['label' => $this->_('Le titre de la boite utilise le lien précédent')])
+
       ->addElement('checkbox',
                    'embeded_code',
                    ['label' => $this->_('Proposer le code "embeded"')])
@@ -94,6 +114,10 @@ class Intonation_Library_Widget_Carousel_Form extends ZendAfi_Form_Configuration
       ->addToShareGroup(['rss',
                          'embeded_code',
                          'link_to_all',
+                         'link_to_all_text',
+                         'link_to_all_title',
+                         'link_to_all_url',
+                         'link_to_all_to_main_title',
                          'all_rendering',
                          'all_layout']);
 
diff --git a/library/templates/Intonation/Library/Widget/Carousel/Record/View.php b/library/templates/Intonation/Library/Widget/Carousel/Record/View.php
index 5f640aea06f..8e2827c568d 100644
--- a/library/templates/Intonation/Library/Widget/Carousel/Record/View.php
+++ b/library/templates/Intonation/Library/Widget/Carousel/Record/View.php
@@ -80,7 +80,7 @@ class Intonation_Library_Widget_Carousel_Record_View extends Intonation_Library_
   }
 
 
-  protected function _getLinkToAllParams() {
+  public function getLinkToAllParams() {
     $url_params = ['module' => 'opac',
                    'controller' => 'recherche',
                    'action' => 'simple',
diff --git a/library/templates/Intonation/Library/Widget/Carousel/View.php b/library/templates/Intonation/Library/Widget/Carousel/View.php
index 8516cd0bd13..bb82c26dc6e 100644
--- a/library/templates/Intonation/Library/Widget/Carousel/View.php
+++ b/library/templates/Intonation/Library/Widget/Carousel/View.php
@@ -30,7 +30,7 @@ abstract class Intonation_Library_Widget_Carousel_View extends Zendafi_View_Help
 
 
   public function getHtml() {
-    $this->titre = $this->_settings->getTitre();
+    $this->titre = $this->_getMainTitle();
     $this->contenu = $this->_getHTML();
 
     return $this->getHtmlArray();
@@ -113,14 +113,39 @@ abstract class Intonation_Library_Widget_Carousel_View extends Zendafi_View_Help
 
 
   protected function _getTagLinkToAll() {
-    return $this->view->tagAction(new Intonation_Library_Link(['Text' => $this->_('En lire plus'),
+    return $this->view->tagAction(new Intonation_Library_Link(['Text' => $this->_getLinkToAllText(),
                                                                'Url' => $this->_getLinkToAllUrl(),
                                                                'OnlyClasses' => 'btn btn-secondary render_all_link',
                                                                'Image' => Class_Template::current()
                                                                ->getIco($this->view,
                                                                         'search_more',
                                                                         'library'),
-                                                               'Title' => $this->_getLinkToAllTitle()]));
+                                                               'Title' => $this->_getLinkToAllTitleDb()]));
+  }
+
+
+  protected function _getLinkToAllText() {
+    $text = $this->_settings->getLinkToAllText();
+    return $text
+      ? $text
+      : $this->_('En lire plus');
+  }
+
+
+  protected function _getLinkToAllTitleDb() {
+    $title = $this->_settings->getLinkToAllTitle();
+    return $title
+      ? sprintf($title, $this->titre)
+      : $this->_getLinkToAllTitle();
+  }
+
+
+  protected function _getMainTitle() {
+    if ( ! $use_url = $this->_settings->getLinkToAllToMainTitle())
+      return $this->_settings->getTitre();
+
+    return $this->view->tagAnchor($this->_getLinkToAllUrl(),
+                                  $this->_settings->getTitre());
   }
 
 
@@ -145,7 +170,7 @@ abstract class Intonation_Library_Widget_Carousel_View extends Zendafi_View_Help
                        return (new $wrapper)
                          ->setView($this->view)
                          ->setModel($element)
-                         ->setContextParams($this->_getLinkToAllParams());
+                         ->setContext($this);
                      }, $elements);
   }
 
@@ -208,6 +233,9 @@ abstract class Intonation_Library_Widget_Carousel_View extends Zendafi_View_Help
 
 
   protected function _getLinkToAllUrl() {
+    if ($url = $this->_settings->getLinkToAllUrl())
+      return $url;
+
     if ($this->_settings->getAllLayout() == Intonation_Library_Widget_Carousel_Record_Definition::SEARCH)
       return $this->view->url(array_filter(['module' => 'opac',
                                             'controller' => 'recherche',
@@ -243,6 +271,11 @@ abstract class Intonation_Library_Widget_Carousel_View extends Zendafi_View_Help
   }
 
 
+  public function getLinkToAllParams() {
+    return [];
+  }
+
+
   public function getHandleLinkToAll() {
     return true;
   }
diff --git a/library/templates/Intonation/Library/Widget/Login/View.php b/library/templates/Intonation/Library/Widget/Login/View.php
index 67ff720dfec..f72739b6967 100644
--- a/library/templates/Intonation/Library/Widget/Login/View.php
+++ b/library/templates/Intonation/Library/Widget/Login/View.php
@@ -160,6 +160,22 @@ abstract class IntonationLoginRenderAbstract {
                               implode($html),
                               $this->_getLinksListAttribs());
 
+    $show_password_button =
+      $this->_view->tag('div',
+                        Class_Template::current()
+                        ->getIco($this->_view,
+                                 'eye',
+                                 'utils'),
+                        ['onclick' => "$(this).parent().find('input').attr('type', function(index, attr) {return attr == 'password' ? 'text' : 'password';});",
+                         'class' => 'password_toggle']);
+
+    $show_password_js = sprintf('$("#password").parent().append("%s"); $("#password").parent().attr("style", "position: relative;");',
+                                str_replace('"', '\"', $show_password_button));
+
+
+    Class_ScriptLoader::getInstance()
+      ->addJQueryReady($show_password_js);
+
     return $this->_renderForm($form) . $html;
   }
 
diff --git a/library/templates/Intonation/Library/Widget/Search/View.php b/library/templates/Intonation/Library/Widget/Search/View.php
index bb44765c70d..d2978a9e73b 100644
--- a/library/templates/Intonation/Library/Widget/Search/View.php
+++ b/library/templates/Intonation/Library/Widget/Search/View.php
@@ -160,7 +160,7 @@ abstract class IntonationSearchRenderAbstract {
 
       ->addElement('custom',
                    'custom_reset_search',
-                   ['render' => function()
+                   ['render' => function($view)
                     {
                       if (!$this->_has_facet)
                         return '';
@@ -366,7 +366,7 @@ class IntonationSearchRenderInline extends IntonationSearchRenderAbstract {
     if ($html = $criteria . implode($optional_form_elements) . $advanced_search)
       $form->addElement('custom',
                         'custom_advanced_search',
-                        ['render' => function() use ($html)
+                        ['render' => function($view) use ($html)
                      {
                        return $this->_renderToggle($html);
                      }]);
diff --git a/library/templates/Intonation/View/Admin/ProfileComposition.php b/library/templates/Intonation/View/Admin/ProfileComposition.php
index 4f36fbc892b..895e606ee33 100644
--- a/library/templates/Intonation/View/Admin/ProfileComposition.php
+++ b/library/templates/Intonation/View/Admin/ProfileComposition.php
@@ -47,7 +47,11 @@ class Intonation_View_Admin_ProfileComposition extends ZendAfi_View_Helper_Profi
 
 
   protected function _getFooterColumn() {
-    return $this->_getDivisionColumn(Class_Profil::DIV_FOOTER, $this->_('Division pied de page'));
+    return $this->_getDivisionColumn(Class_Profil::DIV_FOOTER, $this->_('Division pied de page')
+                                     . $this->view->tagImg(Class_Admin_Skin::current()->getIconUrl('actions',
+                                                                                                   'help'),
+                                                           ['title' => $this->_('Attention. Cette division est partagée entre toutes les pages du profil.'),
+                                                            'style' => 'margin:0 0 -3px 5px;cursor: help;']));
   }
 
 
diff --git a/library/templates/Intonation/View/Admin/TagEditSection.php b/library/templates/Intonation/View/Admin/TagEditSection.php
index b7a7c6496a6..d46310572a4 100644
--- a/library/templates/Intonation/View/Admin/TagEditSection.php
+++ b/library/templates/Intonation/View/Admin/TagEditSection.php
@@ -30,7 +30,7 @@ class Intonation_View_Admin_TagEditSection extends ZendAfi_View_Helper_BaseHelpe
                              'controller' => 'widget',
                              'action' => 'edit-section',
                              'id' => $section->getId(),
-                             'id_profil' => $section->getProfile()->getId()],
+                             'id_profil' => $this->_getProfileId($section)],
                             null, true);
     $label = $this->_('Modifier la section "%s"', $section->getTitle());
 
@@ -43,4 +43,16 @@ class Intonation_View_Admin_TagEditSection extends ZendAfi_View_Helper_BaseHelpe
 
     return $html;
   }
+
+
+  protected function _getProfileId($section) {
+    $profile_id = $section->getProfile()->getId();
+    if ( ! $section->isShared())
+      return $profile_id;
+
+    if ( ! $section->getProfile()->hasParentProfil())
+      return $profile_id;
+
+    return $section->getProfile()->getParentProfil()->getId();
+  }
 }
\ No newline at end of file
diff --git a/library/templates/Intonation/View/Author/RenderFacets.php b/library/templates/Intonation/View/Author/RenderFacets.php
index 864a9671dd9..c142807f96c 100644
--- a/library/templates/Intonation/View/Author/RenderFacets.php
+++ b/library/templates/Intonation/View/Author/RenderFacets.php
@@ -39,6 +39,6 @@ class Intonation_View_Author_RenderFacets extends ZendAfi_View_Helper_BaseHelper
                                         $facet_label)));
     }
 
-    return $this->view->renderBadges($badges);
+    return $this->view->renderBadges($badges, $this);
   }
 }
diff --git a/library/templates/Intonation/View/CardifyOnlyDescription.php b/library/templates/Intonation/View/CardifyOnlyDescription.php
index ff4040d63b3..658e93fe8f3 100644
--- a/library/templates/Intonation/View/CardifyOnlyDescription.php
+++ b/library/templates/Intonation/View/CardifyOnlyDescription.php
@@ -23,6 +23,7 @@
 class Intonation_View_CardifyOnlyDescription extends Intonation_View_CardHelper {
 
   public function cardifyOnlyDescription($element, $img = '') {
+    $element_class = get_class($element);
     $content = [$element->getContentForJSSearch()];
     $content = $this->_addTitle($element, $content);
 
@@ -30,20 +31,20 @@ class Intonation_View_CardifyOnlyDescription extends Intonation_View_CardHelper
       $content [] = $this->_tag('div',
                                 $this->view->tagAction($second_link
                                                        ->setInlineText(1)),
-                                ['class' => 'card-subtitle']);
+                                ['class' => 'card-subtitle card_subtitle_' . $element_class]);
 
     if ($summary = $element->getDescription())
       $content [] = $this->_tag('div',
                                 $element->getDescription(),
                                 ['title' => strip_tags($element->getDescriptionTitle()),
-                                 'class' => 'card-text']);
+                                 'class' => 'card-text card_description_' . $element_class]);
 
     $html = [];
 
     if (!empty($content))
       $html [] = $this->_tag('div',
                              implode($content),
-                             ['class' => 'card-body']);
+                             ['class' => 'card-body card_body_' . $element_class]);
 
     $links = [];
     if ($link = $element->getMainLink())
@@ -59,10 +60,10 @@ class Intonation_View_CardifyOnlyDescription extends Intonation_View_CardHelper
     if (!empty($links))
       $html [] = $this->_tag('div',
                              implode($links),
-                             ['class' => 'card-footer d-flex flex-row justify-content-between  ' . $hide_text_button_class]);
+                             ['class' => 'card-footer d-flex flex-row justify-content-between ' . $hide_text_button_class . ' card_footer_' . $element_class]);
 
     return $this->_tag('div',
                        $img . implode($html),
-                       ['class' => 'card']);
+                       ['class' => 'card card_' . $element_class]);
   }
 }
\ No newline at end of file
diff --git a/library/templates/Intonation/View/ColumnBreak.php b/library/templates/Intonation/View/ColumnBreak.php
new file mode 100644
index 00000000000..1148029ace8
--- /dev/null
+++ b/library/templates/Intonation/View/ColumnBreak.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Intonation_View_ColumnBreak extends ZendAfi_View_Helper_BaseHelper {
+  public function columnBreak() {
+    return $this->_div(['class' => 'w-100'], '');
+  }
+}
diff --git a/library/templates/Intonation/View/RenderBadges.php b/library/templates/Intonation/View/RenderBadges.php
index 51dd2def27b..9b8d0b66753 100644
--- a/library/templates/Intonation/View/RenderBadges.php
+++ b/library/templates/Intonation/View/RenderBadges.php
@@ -22,7 +22,7 @@
 
 class Intonation_View_RenderBadges extends ZendAfi_View_Helper_BaseHelper {
 
-  public function renderBadges($badges) {
+  public function renderBadges($badges, $instance) {
     $badges = array_map(function($badge)
                         {
                           if (!$text = $badge->getText())
@@ -48,6 +48,6 @@ class Intonation_View_RenderBadges extends ZendAfi_View_Helper_BaseHelper {
 
     return $this->_tag('div',
                        implode(array_filter($badges)),
-                       ['class' => 'badge-group']);
+                       ['class' => 'badge-group badge_group_' . get_class($instance)]);
   }
 }
\ No newline at end of file
diff --git a/library/templates/Intonation/View/RenderExpandable.php b/library/templates/Intonation/View/RenderExpandable.php
index 8e9813ed49b..05109c7aea8 100644
--- a/library/templates/Intonation/View/RenderExpandable.php
+++ b/library/templates/Intonation/View/RenderExpandable.php
@@ -24,30 +24,35 @@ class Intonation_View_RenderExpandable extends ZendAfi_View_Helper_BaseHelper {
   public function renderExpandable($content, $button = '', $collapsing_class = 'navbar-expand-md') {
     $id = 'navbar_' . uniqid();
 
+    $button = $this->_getButton($button, $id);
+
+    $content = $this->view->div(['class' => 'collapse navbar-collapse',
+                                 'id' => $id],
+                                $content);
+
+    return $this->view->div(['class' => 'navbar d-print p-0 m-0 ' . $collapsing_class],
+                            $button . $content);
+  }
+
+
+  protected function _getButton($button, $id) {
     if ($button instanceof Intonation_Library_Link)
-      $button = $this->view->tagAction($button->setAttribs(array_merge((($attribs = $button->getAttribs())
+      return $this->view->tagAction($button->setAttribs(array_merge((($attribs = $button->getAttribs())
                                                                         ? $attribs
                                                                         : []),
                                                                        ['type' => 'button',
                                                                         'data-toggle' => 'collapse',
                                                                         'data-target' => '#' . $id])));
+
     $button = $button
       ? $button
       : $this->_tag('span', '', ['class' => 'navbar-toggler-icon']);
 
-    $button = $this->_tag('button',
-                          $button,
-                          ['class' => 'navbar-toggler navbar-light mb-2',
-                           'type' => 'button',
-                           'data-toggle' => 'collapse',
-                           'data-target' => '#' . $id]);
-
-    $content = $this->view->div(['class' => 'collapse navbar-collapse',
-                                 'id' => $id],
-                                $content);
-
-    return $this->view->div(['class' => 'navbar d-print p-0 m-0 ' . $collapsing_class],
-                            $button . $content);
-
+    return $this->_tag('button',
+                       $button,
+                       ['class' => 'navbar-toggler navbar-light mb-2',
+                        'type' => 'button',
+                        'data-toggle' => 'collapse',
+                        'data-target' => '#' . $id]);
   }
 }
diff --git a/library/templates/Intonation/View/RenderGrid.php b/library/templates/Intonation/View/RenderGrid.php
index 5985f399aeb..f89f66e9f3c 100644
--- a/library/templates/Intonation/View/RenderGrid.php
+++ b/library/templates/Intonation/View/RenderGrid.php
@@ -24,6 +24,9 @@ class Intonation_View_RenderGrid extends ZendAfi_View_Helper_BaseHelper {
 
 
   public function renderGrid($collection, $callback) {
+    if ($collection->isEmpty())
+      return '';
+
     $html = array_filter($collection
                          ->injectInto([], function($html, $element) use ($callback)
                                       {
diff --git a/library/templates/Intonation/View/RenderHorizontalList.php b/library/templates/Intonation/View/RenderHorizontalList.php
index 9d1bf495c51..9b61772ed5c 100644
--- a/library/templates/Intonation/View/RenderHorizontalList.php
+++ b/library/templates/Intonation/View/RenderHorizontalList.php
@@ -23,6 +23,9 @@
 class Intonation_View_RenderHorizontalList extends ZendAfi_View_Helper_BaseHelper {
 
   public function renderHorizontalList($collection, $callback) {
+    if ($collection->isEmpty())
+      return '';
+
     $html = $collection
       ->injectInto('', function($html, $element) use ($callback)
     {
diff --git a/library/templates/Intonation/View/RenderList.php b/library/templates/Intonation/View/RenderList.php
index 2a38e95b78a..79ec4479bd5 100644
--- a/library/templates/Intonation/View/RenderList.php
+++ b/library/templates/Intonation/View/RenderList.php
@@ -23,6 +23,9 @@
 class Intonation_View_RenderList extends ZendAfi_View_Helper_BaseHelper {
 
   public function renderList($collection, $callback) {
+    if ($collection->isEmpty())
+      return '';
+
     $html = $collection
       ->injectInto('', function($html, $element) use ($callback)
     {
diff --git a/library/templates/Intonation/View/RenderTree.php b/library/templates/Intonation/View/RenderTree.php
new file mode 100644
index 00000000000..f37c72952cc
--- /dev/null
+++ b/library/templates/Intonation/View/RenderTree.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Intonation_View_RenderTree extends ZendAfi_View_Helper_BaseHelper {
+
+  protected
+    $_parent_classes = 'col-10 col-sm-3 offset-0 mb-3 tree_view_parent border-primary border',
+    $_current_classes = 'col-10 col-sm-3 mb-3 offset-1 tree_view_current border-success border',
+    $_child_classes = 'col-9 offset-2 tree_view_child border-info border p-3';
+
+
+  public function renderTree($parents, $current, $children, $callback) {
+    $html = [$this->_renderParents($parents, $callback),
+             $this->_renderCurrent($current, $callback),
+             $this->_renderChildren($children, $callback)];
+
+    $html = array_filter($html);
+
+    return $this->view->grid(implode($this->view->columnBreak(),
+                                     $html),
+                             ['class' => 'tree_view border-primary']);
+
+  }
+
+
+  protected function _renderParents($parents, $callback) {
+    if ($parents->isEmpty())
+      return '';
+
+    $html = [];
+
+    foreach ($parents as $parent)
+      $html [] = $this->_div(['class' => $this->_parent_classes],
+                             $callback($parent));
+
+    return implode($this->view->columnBreak(),
+                   $html);
+  }
+
+
+  protected function _renderCurrent($domain, $callback) {
+    return $this->_div(['class' => $this->_current_classes],
+                       $callback($domain));
+  }
+
+
+  protected function _renderChildren($children, $callback) {
+    if ($children->isEmpty())
+      return '';
+
+    $html = [];
+
+    foreach ($children as $child)
+      $html [] = $callback($child);
+
+    return $this->_div(['class' => $this->_child_classes],
+                       $this->view->renderGrid($children, $callback));
+  }
+}
diff --git a/library/templates/Intonation/View/RenderTruncateList.php b/library/templates/Intonation/View/RenderTruncateList.php
index 197762018d5..ca259e99f37 100644
--- a/library/templates/Intonation/View/RenderTruncateList.php
+++ b/library/templates/Intonation/View/RenderTruncateList.php
@@ -28,6 +28,9 @@ class Intonation_View_RenderTruncateList extends ZendAfi_View_Helper_BaseHelper
 
 
   public function renderTruncateList($collection, $callback) {
+    if ($collection->isEmpty())
+      return '';
+
     $size = $collection->count();
 
     if (50 < $size)
diff --git a/library/templates/Intonation/View/RenderWall.php b/library/templates/Intonation/View/RenderWall.php
index bad8b1d23ee..b91431df63b 100644
--- a/library/templates/Intonation/View/RenderWall.php
+++ b/library/templates/Intonation/View/RenderWall.php
@@ -26,6 +26,9 @@ class Intonation_View_RenderWall extends ZendAfi_View_Helper_BaseHelper {
 
 
   public function renderWall($collection, $callback) {
+    if ($collection->isEmpty())
+      return '';
+
     $this->_masonry_id = uniqid();
 
     $this->renderHeadScriptsOn(Class_ScriptLoader::getInstance());
diff --git a/library/templates/Intonation/View/Search/DomainBrowser.php b/library/templates/Intonation/View/Search/DomainBrowser.php
new file mode 100644
index 00000000000..e42debb4fd2
--- /dev/null
+++ b/library/templates/Intonation/View/Search/DomainBrowser.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright (c) 2012-2020, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Intonation_View_Search_DomainBrowser extends ZendAfi_View_Helper_BaseHelper {
+  public function Search_DomainBrowser($criteria) {
+    if ( ! $id_module = $criteria->getIdModule())
+      return '';
+
+    if ( ! $config = Class_Profil::getCurrentProfil()->getLocalModuleAccueilConfig($id_module))
+      return '';
+
+    if(!isset($config['type_module']))
+      return '';
+
+    if($config['type_module'] != 'DOMAIN_BROWSER')
+      return '';
+
+    $preferences = $config['preferences'];
+    $root_id = $preferences['root_domain_id'];
+
+    $current = ($current = $criteria->getCatalogue())
+      ? $current
+      : Class_Catalogue::getRoot();
+
+    return $this->view->renderTree($this->_getParents($current, $root_id),
+                                   $this->_getCurrent($current),
+                                   $this->_getChildren($current),
+                                   function($wrapper)
+                                   {
+                                     return $this->view->cardify($wrapper);
+                                   });
+  }
+
+
+  protected function _getParents($current, $root_id) {
+    $parents = $current->getParentsUntil($root_id);
+    array_pop($parents);
+
+    $parents = array_map(function($domain)
+                         {
+                           return $this->_wrapDomain($domain);
+                         },
+                         $parents);
+    return new Storm_Collection($parents);
+  }
+
+
+  protected function _getCurrent($current) {
+    return $this->_wrapDomain($current);
+  }
+
+
+  protected function _getChildren($current) {
+    $children = $current->getChildren();
+
+    $children = array_map(function($domain)
+                          {
+                            return $this->_wrapDomain($domain);
+                          },
+                          $children);
+
+    return new Storm_Collection($children);
+  }
+
+
+  protected function _wrapDomain($domain) {
+    return (new Intonation_Library_View_Wrapper_Domain)
+      ->setModel($domain)
+      ->setView($this->view);
+  }
+
+
+  protected function _childSeparator() {
+    return Class_Template::current()->getIco($this->view, 'tree-child', 'utils');
+  }
+}
diff --git a/library/templates/Intonation/View/Search/Result.php b/library/templates/Intonation/View/Search/Result.php
index 75f8f6c5dc5..2d3e2987ae1 100644
--- a/library/templates/Intonation/View/Search/Result.php
+++ b/library/templates/Intonation/View/Search/Result.php
@@ -65,6 +65,13 @@ class Intonation_View_Search_Result extends ZendAfi_View_Helper_BaseHelper {
                                               : $title_from_url)),
                                   strtolower($text_criteria));
 
+    $domain_browser = ((($domain_browser = $this->view->Search_DomainBrowser($criteria))
+                        ? $this->_div(['class' => 'col-12 pt-2 mb-2 search_domain_browser'],
+                                      $this->view->renderExpandable($domain_browser,
+                                                                    $this->_tag('span', '', ['class' => 'navbar-toggler-icon'])
+                                                                    . $this->_tag('span', $this->_('Arborescence'), ['class' => 'ml-3 text-dark'])))
+                        : ''));
+
     $tools = $records
       ? $this->_div(['class' => 'col-12 border-top border-bottom pt-2 mb-2 search_tools'],
                     $this->_renderTools($search, $criteria))
@@ -89,6 +96,8 @@ class Intonation_View_Search_Result extends ZendAfi_View_Helper_BaseHelper {
 
              $tools,
 
+             $domain_browser,
+
              ($records
               ? $this->_div(['class' => 'col-12 col-md-3'],
                             $facets)
diff --git a/library/templates/Intonation/View/Search/TextCriteria.php b/library/templates/Intonation/View/Search/TextCriteria.php
index 426b2472a24..cb3f577af19 100644
--- a/library/templates/Intonation/View/Search/TextCriteria.php
+++ b/library/templates/Intonation/View/Search/TextCriteria.php
@@ -35,9 +35,7 @@ class Intonation_View_Search_TextCriteria extends Intonation_View_Search_HtmlCri
   public function visitCatalogue($catalogue) {
     $this->_domain = $catalogue;
 
-    return $this->_criteria->hasExpressionRecherche()
-      ? $this->htmlAppend($this->view->_('dans %s', $catalogue->getLibelle()))
-      : $this;
+    return $this->htmlAppend($this->view->_('dans %s', $catalogue->getLibelle()));
   }
 
 
diff --git a/library/templates/Intonation/View/Truncate.php b/library/templates/Intonation/View/Truncate.php
index 2824d2e2a4f..4dd548413f6 100644
--- a/library/templates/Intonation/View/Truncate.php
+++ b/library/templates/Intonation/View/Truncate.php
@@ -21,7 +21,7 @@
 
 
 class Intonation_View_Truncate extends ZendAfi_View_Helper_BaseHelper {
-  public function truncate($text, $size = '20', $tag = 'p', $attribs = []) {
+  public function truncate($text, $attribs = [], $size = '20', $tag = 'p') {
     if (! $text)
       return '';
 
diff --git a/library/templates/Intonation/View/User/Informations.php b/library/templates/Intonation/View/User/Informations.php
index 62cb26b9f71..85a1f539072 100644
--- a/library/templates/Intonation/View/User/Informations.php
+++ b/library/templates/Intonation/View/User/Informations.php
@@ -58,7 +58,7 @@ class Intonation_View_User_Informations extends ZendAfi_View_Helper_BaseHelper {
                                    'Image' => Class_Template::current()->getIco($this->view, 'edit', 'utils'),
                                    'Text' => $this->_('Modifier mes informations'),
                                    'Title' => $this->_('Modifier les informations me concernant'),
-                                   'Class' => 'btn btn-sm btn-success',
+                                   'Class' => 'btn btn-sm btn-success mr-3',
                                    'InlineText' => 1]);
 
     $edit_password =
@@ -67,7 +67,7 @@ class Intonation_View_User_Informations extends ZendAfi_View_Helper_BaseHelper {
                                    'Image' => Class_Template::current()->getIco($this->view, 'lock', 'utils'),
                                    'Text' => $this->_('Changer mon mot de passe'),
                                    'Title' => $this->_('Changer le mot de passe de mon compte.'),
-                                   'Class' => 'btn btn-sm btn-secondary ml-3',
+                                   'Class' => 'btn btn-sm btn-secondary',
                                    'InlineText' => 1]);
 
     return
@@ -88,7 +88,7 @@ class Intonation_View_User_Informations extends ZendAfi_View_Helper_BaseHelper {
                                                     'action' => 'en-lire-plus',
                                                     'id' => $library->getId()]),
                                   $library->getLibelle(),
-                                  ['title' => $this->_('En lire plus au sur %s',
+                                  ['title' => $this->_('En lire plus sur %s',
                                                        $library->getLibelle())]);
   }
 }
diff --git a/library/templates/Muscle/Assets/css/muscle.css b/library/templates/Muscle/Assets/css/muscle.css
index 83697caefb2..c01a854be84 100644
--- a/library/templates/Muscle/Assets/css/muscle.css
+++ b/library/templates/Muscle/Assets/css/muscle.css
@@ -72,10 +72,6 @@ header {
     display: flex;
 }
 
-.menu_buttons .button_text {
-    display: none !important;
-}
-
 .menu_buttons .nav-link,
 .menu_buttons .nav-link:hover {
     color: var(--muscle-black) !important;
diff --git a/library/templates/Muscle/Library/Settings.php b/library/templates/Muscle/Library/Settings.php
index 116aa8e1899..d615f70b433 100644
--- a/library/templates/Muscle/Library/Settings.php
+++ b/library/templates/Muscle/Library/Settings.php
@@ -30,32 +30,8 @@ class Muscle_Library_Settings extends Intonation_Library_Settings {
 
     $custom_css_classes = $settings[$this->_template->withNameSpace('custom_css_class')];
 
-    $custom_css_classes = ['position_fixed_bottom',
-                           'position_fixed_bottom_left',
-                           'position_fixed_bottom_right',
-                           'position_fixed_top',
-                           'position_fixed_top_left',
-                           'position_fixed_top_right',
-                           'position_fixed_mid_left',
-                           'position_fixed_mid_right',
-                           'pt-3',
-                           'pt-5',
-                           'pb-3',
-                           'pl-2',
-                           'pl-md-3',
-                           'pr-md-3',
-                           'no_border',
-                           'no_border_radius',
-                           'no_shadow',
-                           'm-auto',
-                           'ml-auto',
-                           'mr-auto',
-                           'align-items-center',
-                           'auto_col',
-                           'justify-content-start',
-                           'justify-content-end',
-                           'justify-content-center',
-                           'menu_buttons'];
+    $custom_css_classes = array_merge($custom_css_classes,
+                                      []);
 
     $settings[$this->_template->withNameSpace('custom_css_class')] = $custom_css_classes;
 
diff --git a/library/templates/Polygone/Assets/css/polygone.css b/library/templates/Polygone/Assets/css/polygone.css
index e2b52070373..dd841405d39 100644
--- a/library/templates/Polygone/Assets/css/polygone.css
+++ b/library/templates/Polygone/Assets/css/polygone.css
@@ -69,10 +69,6 @@ header {
     display: flex;
 }
 
-.menu_buttons .button_text {
-    display: none !important;
-}
-
 .ui-state-active,
 .btn:active,
 a:active,
diff --git a/library/templates/Polygone/Library/Settings.php b/library/templates/Polygone/Library/Settings.php
index 675f19ac81f..159a76c4ddc 100644
--- a/library/templates/Polygone/Library/Settings.php
+++ b/library/templates/Polygone/Library/Settings.php
@@ -27,41 +27,14 @@ class Polygone_Library_Settings extends Intonation_Library_Settings {
 
     $custom_css_classes = $settings[$this->_template->withNameSpace('custom_css_class')];
 
-    $custom_css_classes = ['position_fixed_bottom',
-                           'position_fixed_bottom_left',
-                           'position_fixed_bottom_right',
-                           'position_fixed_top',
-                           'position_fixed_top_left',
-                           'position_fixed_top_right',
-                           'position_fixed_mid_left',
-                           'position_fixed_mid_right',
-                           'pt-3',
-                           'pt-5',
-                           'pb-3',
-                           'pl-2',
-                           'pl-md-3',
-                           'pr-md-3',
-                           'no_background',
-                           'no_border',
-                           'no_border_radius',
-                           'no_shadow',
-                           'm-auto',
-                           'ml-auto',
-                           'mr-auto',
-                           'align-items-center',
-                           'auto_col',
-                           'justify-content-start',
-                           'justify-content-end',
-                           'justify-content-center',
-                           'menu_buttons',
-                           'polygone_big_menu_buttons',
-                           'polygone_widget',
-                           'polygone_simple_widget',
-                           'no_card_footer',
-                           'no_badges',
-                           'scroll_search',
-                           'flying_widget',
-                           'z-index-11'];
+    $custom_css_classes = array_merge($custom_css_classes,
+                                      ['polygone_big_menu_buttons',
+                                       'polygone_widget',
+                                       'polygone_simple_widget',
+                                       'no_card_footer',
+                                       'no_badges',
+                                       'scroll_search',
+                                       'flying_widget']);
 
     $settings[$this->_template->withNameSpace('custom_css_class')] = $custom_css_classes;
 
diff --git a/library/templates/TerreDuMilieu/Assets/css/terredumilieu.css b/library/templates/TerreDuMilieu/Assets/css/terredumilieu.css
index 3afcdab16e3..d001c68304a 100644
--- a/library/templates/TerreDuMilieu/Assets/css/terredumilieu.css
+++ b/library/templates/TerreDuMilieu/Assets/css/terredumilieu.css
@@ -410,10 +410,6 @@ footer .tdm_social_network_widget .nav-item:first-child {
     text-align: center;
 }
 
-.z_index_11 {
-    z-index: 11;
-}
-
 .tdm_flying_widget.position_fixed_top_right {
     top: 80px !important;
 }
diff --git a/library/templates/TerreDuMilieu/Library/Settings.php b/library/templates/TerreDuMilieu/Library/Settings.php
index 2f239c2d386..c2296aacdde 100644
--- a/library/templates/TerreDuMilieu/Library/Settings.php
+++ b/library/templates/TerreDuMilieu/Library/Settings.php
@@ -27,30 +27,12 @@ class TerreDuMilieu_Library_Settings extends Intonation_Library_Settings {
 
     $custom_css_classes = $settings[$this->_template->withNameSpace('custom_css_class')];
 
-    $custom_css_classes = ['position_fixed_bottom',
-                           'position_fixed_bottom_left',
-                           'position_fixed_bottom_right',
-                           'position_fixed_top',
-                           'position_fixed_top_left',
-                           'position_fixed_top_right',
-                           'position_fixed_mid_left',
-                           'position_fixed_mid_right',
-                           'pt-3',
-                           'pb-3',
-                           'no_border',
-                           'no_border_radius',
-                           'no_shadow',
-                           'm-auto',
-                           'align-items-center',
-                           'auto_col',
-                           'tdm_widget',
-                           'tdm_flying_widget',
-                           'tdm_search_widget',
-                           'tdm_social_network_widget',
-                           'tdm_main_nav_widget',
-                           'border-primary',
-                           'border-left',
-                           'z_index_11'];
+    $custom_css_classes = array_merge($custom_css_classes,
+                                      ['tdm_widget',
+                                       'tdm_flying_widget',
+                                       'tdm_search_widget',
+                                       'tdm_social_network_widget',
+                                       'tdm_main_nav_widget']);
 
     $settings[$this->_template->withNameSpace('custom_css_class')] = $custom_css_classes;
 
diff --git a/public/admin/js/global.js b/public/admin/js/global.js
index d8a5aa96f1d..79455f89ae3 100644
--- a/public/admin/js/global.js
+++ b/public/admin/js/global.js
@@ -220,7 +220,7 @@ function toggleVisibilityForElement(eventSourceSelector, objectToShowSelector, t
       : objectToShow.fadeOut();
   }
 
-  sourceObject.change(function(event) {
+  sourceObject.on('change input', function(event) {
     return toggleVisibility($(event.target));
   });
 
diff --git a/public/opac/css/core.css b/public/opac/css/core.css
index 83a3be32a2a..1275ee0a0c1 100644
--- a/public/opac/css/core.css
+++ b/public/opac/css/core.css
@@ -139,4 +139,58 @@ ol.breadcrumb li {
 
 [data-spambots] {
     margin-left: -5000px;
+}
+
+.tree_view .card-footer {
+    display: none !important;
+}
+
+.tree_view .card-body {
+    padding: 0.5rem;
+}
+
+.tree_view .card-columns {
+    column-gap: 0.5rem;
+}
+
+.tree_view .card-title {
+    margin: 0;
+}
+
+.tree_view_current:not(:last-child)::before,
+.tree_view_parent::before {
+    display: block;
+    content: '';
+    position: absolute;
+    border-width: 0;
+    border-color: inherit;
+    border-style: solid;
+    border-left-width: 2px;
+    height: 1rem;
+    left: 50%;
+    width: 100%;
+    bottom: calc(-1rem - 1px);
+    z-index: 0;
+}
+
+.tree_view_current:not(:last-child)::before {
+    bottom: calc(-1rem - 3px);
+}
+
+.tree_view .card {
+    z-index-1;
+}
+
+.tree_view_current {
+    border-width: 3px !important;
+}
+
+.password_toggle {
+    position: absolute;
+    right: 10px;
+    top: 5px;
+}
+
+.password_toggle i {
+    color: var(--front-background-modale) !important;
 }
\ No newline at end of file
diff --git a/scripts/upgrade_db.php b/scripts/upgrade_db.php
index 2ce3a6f3e26..f292f93e564 100644
--- a/scripts/upgrade_db.php
+++ b/scripts/upgrade_db.php
@@ -10,4 +10,5 @@ if (262 < (int)Class_CosmoVar::getValueOf('patch_level'))
 $force = $argc>1 && $argv[1]=='--force';
 
 (new Class_Migration_ScriptPatchs())->run($force);
+(new Class_Template_Update)->run();
 ?>
\ No newline at end of file
diff --git a/tests/scenarios/Templates/MuscleTemplateTest.php b/tests/scenarios/Templates/MuscleTemplateTest.php
index 6381b39e247..84272e0ed90 100644
--- a/tests/scenarios/Templates/MuscleTemplateTest.php
+++ b/tests/scenarios/Templates/MuscleTemplateTest.php
@@ -40,9 +40,9 @@ abstract class MuscleTemplateTestCase extends Admin_AbstractControllerTestCase {
       ->save();
 
     $id = (new Muscle_Template)->tryOn($profile);
-    (new Class_Profil_Promoter)->promote($profile);
+    (new Class_Profil_Promoter)->promote(Class_Profil::find($id));
 
-    Class_Profil::find($id)->setHeaderCss('live_editor.css')->save();
+    Class_Profil::find(1)->setHeaderCss('live_editor.css')->save();
   }
 
 
@@ -210,7 +210,7 @@ class MuscleTemplateOpacAdvancedSearchTest extends MuscleTemplateTestCase {
 
   /** @test */
   public function advancedSearchSettingsShouldContainsCustomForm() {
-    $this->dispatch('/admin/widget/edit-action/id/recherche_avancee/id_profil/24');
+    $this->dispatch('/admin/widget/edit-action/id/recherche_avancee/id_profil/1');
     $this->assertXPath('//input[@id="forms"]');
   }
 }
@@ -333,4 +333,192 @@ class MuscleTemplateIndexFormulaireContactTest extends MuscleTemplateTestCase {
     $this->dispatch('/index/formulairecontact');
     $this->assertXPath('//form[contains(@action, "formulairecontact")]');
   }
+}
+
+
+
+
+class MuscleTemplateUpdateSettingsTest extends MuscleTemplateTestCase {
+  public function setUp() {
+    parent::setUp();
+    $muscle_settings = Class_Template_Settings::findFirstBy(['template' => 'MUSCLE']);
+
+    $muscle_settings_instance = $muscle_settings->getSettingsInstance();
+    $muscle_settings_instance->setMuscleIconsMapLibrary(['new_icon_key' => 'class far fa-new-ico']);
+
+    $muscle_settings->setSettings(serialize($muscle_settings_instance->toArray()))->save();
+    (new Class_Template_Update)->run();
+    $muscle_settings->clearCache();
+  }
+
+
+  /** @test */
+  public function bgDarkShouldBePresentInCustomCssClassAfterUpdate() {
+    $settings = (new Muscle_Template)->getSettingsInstance();
+    $icons_map_library = $settings->getMuscleIconsMapLibrary();
+    $this->assertContains('class far fa-new-ico', $icons_map_library);
+    $this->assertContains('class fas fa-user', $icons_map_library);
+  }
+}
+
+
+
+
+class MuscleTemplateAdminNewPageTest extends MuscleTemplateTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/admin/profil/newpage/id_profil/1');
+  }
+
+  /** @test */
+  public function shouldRedirectToProfile26() {
+     $this->assertRedirectTo('/admin/profil/accueil/id_profil/26');
+  }
+
+
+  /** @test */
+  public function profile26FooterShouldContainsScroll() {
+    $this->assertTrue(Class_Profil::find(26)->hasBoiteInDivision(Class_Profil::DIV_FOOTER, 'SCROLL'));
+  }
+}
+
+
+
+class MuscleTemplateNewPageEditDispatchTest extends MuscleTemplateTestCase {
+
+
+  public function setUp() {
+    parent::setUp();
+    $newpage = Class_Profil::getLoader()
+      ->newInstance()
+      ->setParentProfil(Class_Profil::getPortail())
+      ->setLibelle('** nouvelle page **');
+    $newpage->save();
+    $this->dispatch('/admin/profil/accueil/id_profil/' . $newpage->getId());
+  }
+
+
+  /** @test */
+  public function linkToEditScrollShouldContainsProfile1() {
+    $this->assertXPath('//div//a[contains(@href, "admin/widget/edit-widget/id/13/id_profil/1")]');
+  }
+
+
+  /** @test */
+  public function linkToEditFooterShouldContainsProfile1() {
+    $this->assertXPath('//div//a[contains(@href, "admin/widget/edit-section/id/6/id_profil/1")]');
+  }
+
+
+  /** @test */
+  public function linkToEditMainDivisionShouldContainsProfile26() {
+    $this->assertXPath('//div//a[contains(@href, "admin/widget/edit-section/id/2/id_profil/26")]');
+  }
+}
+
+
+
+class MuscleTemplateSearchResultWithDomainBrowserTest extends MuscleTemplateTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    $this->fixture('Class_CodifAuteur',
+                   ['id' => 43,
+                    'libelle' => 'Pomme d\'API']);
+
+    $records = [$this->fixture('Class_Notice',
+                               ['id' => 89,
+                                'titre_principal' => 'Tintin e i picaros']),
+                $this->fixture('Class_Notice',
+                               ['id' => 99,
+                                'titre_principal' => 'Tintin au Tibet'])];
+
+    $result = $this->mock();
+
+    $result
+      ->whenCalled('setDuration')
+      ->answers($result)
+
+      ->whenCalled('setSettings')
+      ->answers($result)
+
+      ->whenCalled('getSettings')
+      ->answers(['facettes' => ''])
+
+      ->whenCalled('fetchFacetsAndTags')
+      ->answers(['facettes' => '',
+                 'suggests' => [['id' => 'M87',
+                                 'label' => 'Pomme (sujet)'],
+
+                                ['id' => 'A43',
+                                 'label' => 'Pomme d\'API (auteur)']]])
+
+      ->whenCalled('getRecordsCount')
+      ->answers(2)
+
+      ->whenCalled('isError')
+      ->answers(false)
+
+      ->whenCalled('getCriteresRecherche')
+      ->answers((new Intonation_Library_Search_Criteria)->setParams(['expressionRecherche' => '',
+                                                                     'id_module' => 78,
+                                                                     'id_catalogue' => 3,
+                                                                     'id_profil' => 1,
+                                                                     'liste_format' => 4]))
+
+      ->whenCalled('fetchRecords')
+      ->answers($records)
+
+      ->whenCalled('fetchAllRecordsIds')
+      ->answers([89, 99]);
+
+    $engine = $this->mock()
+
+                   ->whenCalled('lancerRecherche')
+                   ->answers($result);
+
+    Class_MoteurRecherche::setInstance($engine);
+
+    $this->fixture('Class_Catalogue',
+                   ['id' => 1,
+                    'libelle' => 'Nouveauté']);
+
+    $this->fixture('Class_Catalogue',
+                   ['id' => 2,
+                    'libelle' => 'BD',
+                    'parent_id' => 1]);
+
+    $this->fixture('Class_Catalogue',
+                   ['id' => 3,
+                    'libelle' => 'Romans',
+                    'parent_id' => 1]);
+
+    $preferences = array_merge(Class_Systeme_ModulesAccueil::getInstance()
+                               ->getModuleByCode('DOMAIN_BROWSER')
+                               ->getDefaultValues(),
+                               ['root_domain_id' => 1]);
+
+
+    $profile = Class_Profil::getPortail()->updateModuleConfigAccueil(78,
+                                                       ['type_module' => 'DOMAIN_BROWSER',
+                                                        'division' => 2,
+                                                        'preferences' => $preferences]);
+
+    $profile->save();
+
+    $this->dispatch('/recherche/simple/id_module/78/id_catalogue/3');
+  }
+
+
+  /** @test */
+  public function domainBrowserShouldContainsNovelty() {
+    $this->assertXPathContentContains('//div[contains(@class, "tree_view_parent")]', 'Nouveauté');
+  }
+
+
+  /** @test */
+  public function domainBrowserShouldContainsRomans() {
+    $this->assertXPathContentContains('//div[contains(@class, "tree_view_current")]', 'Romans');
+  }
 }
\ No newline at end of file
diff --git a/tests/scenarios/Templates/TemplatesTest.php b/tests/scenarios/Templates/TemplatesTest.php
index 4a6cbd89198..cc18eb987ed 100644
--- a/tests/scenarios/Templates/TemplatesTest.php
+++ b/tests/scenarios/Templates/TemplatesTest.php
@@ -199,18 +199,19 @@ class TemplatesControllerUpdateIntonationTest extends TemplatesEnabledTestCase {
                                  'IntonationCustomCssClass' => ['bg-dark',
                                                                 'align-items-center']])->save();
 
-    $this->dispatch('/admin/template/update/template/INTONATION', true);
   }
 
 
   /** @test */
   public function shouldRedirectToReferer() {
+    $this->dispatch('/admin/template/update/template/INTONATION', true);
     $this->assertRedirect();
   }
 
 
   /** @test */
   public function bgDarkShouldBePresentInCustomCssClass() {
+    $this->dispatch('/admin/template/update/template/INTONATION', true);
     $settings = Class_Template::current()->getSettings();
     $custom_css_class = $settings->getIntonationCustomCssClass();
     $this->assertContains('bg-dark',
@@ -220,6 +221,7 @@ class TemplatesControllerUpdateIntonationTest extends TemplatesEnabledTestCase {
 
   /** @test */
   public function alignItemsCenterBePresentInCustomCssClass() {
+    $this->dispatch('/admin/template/update/template/INTONATION', true);
     $settings = Class_Template::current()->getSettings();
     $settings->updateSettings();
     $custom_css_class = $settings->getIntonationCustomCssClass();
@@ -230,6 +232,7 @@ class TemplatesControllerUpdateIntonationTest extends TemplatesEnabledTestCase {
 
   /** @test */
   public function alignItemsCenterShouldBePresentInCustomCssClassOnce() {
+    $this->dispatch('/admin/template/update/template/INTONATION', true);
     $settings = Class_Template::current()->getSettings();
     $settings->updateSettings();
     $custom_css_class = $settings->getIntonationCustomCssClass();
@@ -1072,6 +1075,12 @@ class TemplatesEditTest extends TemplatesEnabledTestCase {
   public function hydratingMappingShouldContainsSiteWebWrapper() {
     $this->assertXPathContentContains('//script[contains(text(), "IntonationHydratingMapping")]', 'site_web_wrapper');
   }
+
+
+  /** @test */
+  public function linkToCssClassesDocumentationShouldBePresent() {
+    $this->assertXPathContentContains('//script', 'http://wiki.bokeh-library-portal.org/index.php?title=Classes_CSS');
+  }
 }
 
 
@@ -5106,7 +5115,7 @@ class TemplatesDispatchRssWidgetTest extends TemplatesIntonationTestCase {
   /** @test */
   public function rssNoticeajaxResourcesShouldRenderRenderItems() {
     $this->dispatch('/opac/noticeajax/resources/id/' . $this->_record_id);
-    $this->assertXPath('//div');
+    $this->assertContains('onload_utils', $this->_response->getBody());
   }
 
 
@@ -5127,6 +5136,6 @@ class TemplatesDispatchRssWidgetTest extends TemplatesIntonationTestCase {
   /** @test */
   public function loadRssItemShouldRenderHtml() {
     $this->dispatch('/opac/rss/render-items/id/3/id_profil/72');
-    $this->assertXpath('//div');
+    $this->assertContains('onload_utils', $this->_response->getBody());
   }
 }
\ No newline at end of file
-- 
GitLab