diff --git a/Changelog.md b/Changelog.md
index 2985d6942d272562701e6176f0477e807a835ef2..57159ccf8a673db5aa739cf89b5690f60def7e3f 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,4 +1,4 @@
-## %"FusionDirectory 1.4" - 2023-05-02
+## %"FusionDirectory 1.4" - 2023-06-13
 
 ### Added
 
@@ -63,6 +63,8 @@
 - fd#6207 Creation of new Class - Tasks Object - standard
 - fd#6231 [Tasks-Dashboard] - Develop a new dashboard for tasks to allow granular status report on sub-tasks
 - fd#6241 [Icons] Proper icons for tasks - task dashboard - mail template
+- fd#6281 [PluginManager] - move the plugin tab from dasboard to the left menu under dashboard section
+- fd#6282 [Core] - Re-structuration of sections and related menu entries
 
 #### fusiondirectory-plugins
 - fd-plugins#2912 the autofs plugin should be updated to support autofs5
@@ -126,6 +128,10 @@
 - fd-plugins#6214 [Subscriptions] - Adds proper icons to the icons folder.
 - fd-plugins#6220 [Webauthn] - Create one file named variables_webauthn allowing the load all requirements - helping patching for supported distributions
 - fd-plugins#6226 [Public-form] - Updates plugin in order to be fully compatible with securimage library
+- fd-plugins#6233 [Supann] - FranceConnect object class to be changed.
+- fd-plugins#6234 [Supann] - Class entity - OU name is set to be unique but this is not mandatory
+- fd-plugins#6236 [Plugins] - Re-structuration of sections and related menu entries
+- fd-plugins#6238 [Plugins] - Add icons to subcritpions plugin
 
 ### Changed
 
@@ -174,6 +180,8 @@
 - fd#6266 CAS library 1.6 need a new parameter
 - fd#6267 [Core] - Update the reference from our old tools naming convention to the new ones.
 - fd#6268 change the path in the apache configuration to point to /usr/share/fusiondirectory directly
+- fd#6283 [PluginManager] objectType is of tasks and should be changed to its own type
+- fd#6286 [Core] - Tasks management class should be set outside dashboard
 
 #### fusiondirectory-plugins
 - fd-plugins#3360 update class_sieve.inc to the latest version 0.1.0
@@ -224,6 +232,7 @@
 - fd#6153 Remove samba domain caching from core
 - fd#6254 [Core] - Remove fusiondirectory-insert-schema written in Perl from the branch.
 - fd#6255 [Manpages] - Removes Perl manpages from Core
+- fd#6280 Remove dashboard completely from FusionDirectory
 
 #### fusiondirectory-plugins
 - fd-plugins#5980 removing puppert plugin from 1.4-dev
@@ -337,6 +346,7 @@
 - fd#6263 [Core] - Adapts core-fd schema to use the same OID for tasks, mailTemplate
 - fd#6264 [Core] - Removes un-required modules from Mail Template and Tasks, such as the Macro plugin.
 - fd#6265 [Core] - Fixes some transifex issues
+- fd#6276 Error CAS after saving configuration
 
 #### fusiondirectory-plugins
 - fd-plugins#4013 Ppolicy functions that not work
diff --git a/archive/admin/archive/class_archiveManagement.inc b/archive/admin/archive/class_archiveManagement.inc
index 47b0d5f3adf81773f63e9bab43214e6f7254ed10..763c1f56551b6f21186da07c5a4a72f2dec94266 100644
--- a/archive/admin/archive/class_archiveManagement.inc
+++ b/archive/admin/archive/class_archiveManagement.inc
@@ -40,7 +40,8 @@ class archiveManagement extends management
       'plTitle'       => _('Archived objects'),
       'plDescription' => _('Browse archived objects'),
       'plIcon'        => 'geticon.php?context=mimetypes&icon=application-x-archive&size=48',
-      'plSection'     => 'reporting',
+      'plSection' => ['reporting' => ['name' => _('Reporting'), 'priority' => 40]],
+      'plPriority'    => 4,
       'plManages'     => ['archivedObject'],
     ];
   }
diff --git a/argonaut/addons/argonaut/class_argonautAction.inc b/argonaut/dashboard/argonaut/class_argonautAction.inc
similarity index 100%
rename from argonaut/addons/argonaut/class_argonautAction.inc
rename to argonaut/dashboard/argonaut/class_argonautAction.inc
diff --git a/argonaut/addons/argonaut/class_argonautEventTypes.inc b/argonaut/dashboard/argonaut/class_argonautEventTypes.inc
similarity index 100%
rename from argonaut/addons/argonaut/class_argonautEventTypes.inc
rename to argonaut/dashboard/argonaut/class_argonautEventTypes.inc
diff --git a/argonaut/addons/argonaut/class_argonautImportFile.inc b/argonaut/dashboard/argonaut/class_argonautImportFile.inc
similarity index 100%
rename from argonaut/addons/argonaut/class_argonautImportFile.inc
rename to argonaut/dashboard/argonaut/class_argonautImportFile.inc
diff --git a/argonaut/addons/argonaut/class_argonautQueue.inc b/argonaut/dashboard/argonaut/class_argonautQueue.inc
similarity index 99%
rename from argonaut/addons/argonaut/class_argonautQueue.inc
rename to argonaut/dashboard/argonaut/class_argonautQueue.inc
index 3b0a8a9d90cca2598ec6d625b46cb5ab53f3e4d1..4ec35f9d76280cfc1729f0c58433d3f50719e312 100644
--- a/argonaut/addons/argonaut/class_argonautQueue.inc
+++ b/argonaut/dashboard/argonaut/class_argonautQueue.inc
@@ -48,7 +48,7 @@ class argonautQueue extends management
       'plShortName'   => _('Deployment queue'),
       'plDescription' => _('Provide a mechanism to automatically activate systems'),
       'plIcon'        => 'geticon.php?context=applications&icon=argonaut&size=48',
-      'plSection'     => 'systems',
+      'plSection'     => 'Dashboard',
       'plPriority'    => 30,
       'plCategory'    => ['argonautQueue' => ['objectClass' => 'none', 'description' => _('Deployment queue')]],
 
diff --git a/argonaut/addons/argonaut/class_argonautQueueColumn.inc b/argonaut/dashboard/argonaut/class_argonautQueueColumn.inc
similarity index 100%
rename from argonaut/addons/argonaut/class_argonautQueueColumn.inc
rename to argonaut/dashboard/argonaut/class_argonautQueueColumn.inc
diff --git a/argonaut/addons/argonaut/class_argonautQueueFilter.inc b/argonaut/dashboard/argonaut/class_argonautQueueFilter.inc
similarity index 100%
rename from argonaut/addons/argonaut/class_argonautQueueFilter.inc
rename to argonaut/dashboard/argonaut/class_argonautQueueFilter.inc
diff --git a/argonaut/addons/argonaut/import_events.tpl b/argonaut/dashboard/argonaut/import_events.tpl
similarity index 100%
rename from argonaut/addons/argonaut/import_events.tpl
rename to argonaut/dashboard/argonaut/import_events.tpl
diff --git a/audit/admin/audit/class_auditEvent.inc b/audit/reports/audit/class_auditEvent.inc
similarity index 100%
rename from audit/admin/audit/class_auditEvent.inc
rename to audit/reports/audit/class_auditEvent.inc
diff --git a/audit/admin/audit/class_auditManagement.inc b/audit/reports/audit/class_auditManagement.inc
similarity index 96%
rename from audit/admin/audit/class_auditManagement.inc
rename to audit/reports/audit/class_auditManagement.inc
index e36214e7296ff824bd96da5ddb0e1af95f6f3680..94a9489add2d3f0fe7d463cc1e5905ceb9c9e9bb 100644
--- a/audit/admin/audit/class_auditManagement.inc
+++ b/audit/reports/audit/class_auditManagement.inc
@@ -42,7 +42,8 @@ class auditManagement extends management
       'plTitle'       => _('Audit events'),
       'plDescription' => _('Browse audit events'),
       'plIcon'        => 'geticon.php?context=applications&icon=audit&size=48',
-      'plSection'     => 'reporting',
+      'plSection' => ['reporting' => ['name' => _('Reporting'), 'priority' => 40]],
+      'plPriority'    => 2,
       'plManages'     => ['auditEvent'],
     ];
   }
diff --git a/developers/addons/debugHelp/class_debugHelp.inc b/developers/reports/debugHelp/class_debugHelp.inc
similarity index 98%
rename from developers/addons/debugHelp/class_debugHelp.inc
rename to developers/reports/debugHelp/class_debugHelp.inc
index d531fcb145c0fb9784a959238dd3fd6167f519e2..5b4457be7e51ca637d342ccc6ed6c9d728ca5311 100644
--- a/developers/addons/debugHelp/class_debugHelp.inc
+++ b/developers/reports/debugHelp/class_debugHelp.inc
@@ -26,7 +26,7 @@ class debugHelp extends simplePlugin
     return [
       'plShortName'   => _('Debug help'),
       'plDescription' => _('Debug help tools'),
-      'plSection'     => 'reporting',
+      'plSection' => ['reporting' => ['name' => _('Reporting'), 'priority' => 40]],
       'plPriority'    => 1,
       'plIcon'        => 'geticon.php?context=categories&icon=applications-development&size=48',
       'plObjectType'  => ['debug' => [
diff --git a/developers/addons/debugHelp/debughelp.tpl b/developers/reports/debugHelp/debughelp.tpl
similarity index 100%
rename from developers/addons/debugHelp/debughelp.tpl
rename to developers/reports/debugHelp/debughelp.tpl
diff --git a/fusioninventory/admin/inventory/class_InventoryOperatingSystemColumn.inc b/fusioninventory/dashboard/inventory/class_InventoryOperatingSystemColumn.inc
similarity index 100%
rename from fusioninventory/admin/inventory/class_InventoryOperatingSystemColumn.inc
rename to fusioninventory/dashboard/inventory/class_InventoryOperatingSystemColumn.inc
diff --git a/fusioninventory/admin/inventory/class_inventoryManagement.inc b/fusioninventory/dashboard/inventory/class_inventoryManagement.inc
similarity index 96%
rename from fusioninventory/admin/inventory/class_inventoryManagement.inc
rename to fusioninventory/dashboard/inventory/class_inventoryManagement.inc
index 42380ccbac6f2bfa6f6565225c795ee7023bf994..f59e480e8cbca088fc1385d5a2a5ca3af97b8383 100644
--- a/fusioninventory/admin/inventory/class_inventoryManagement.inc
+++ b/fusioninventory/dashboard/inventory/class_inventoryManagement.inc
@@ -40,7 +40,7 @@ class inventoryManagement extends management
       'plTitle'       => _('Inventory objects'),
       'plDescription' => _('Browse inventory objects'),
       'plIcon'        => 'geticon.php?context=applications&icon=fusioninventory&size=48',
-      'plSection'     => 'reporting',
+      'plSection' => ['reporting' => ['name' => _('Reporting'), 'priority' => 40]],
       'plPriority'    => 5,
       'plManages'     => ['inventory'],
     ];
diff --git a/gpg/addons/gpg/class_pgpServerInfo.inc b/gpg/configuration/gpg/class_pgpServerInfo.inc
similarity index 100%
rename from gpg/addons/gpg/class_pgpServerInfo.inc
rename to gpg/configuration/gpg/class_pgpServerInfo.inc
diff --git a/ldapdump/addons/ldapdump/class_ldapDump.inc b/ldapdump/generic/ldapdump/class_ldapDump.inc
similarity index 100%
rename from ldapdump/addons/ldapdump/class_ldapDump.inc
rename to ldapdump/generic/ldapdump/class_ldapDump.inc
diff --git a/ldapdump/addons/ldapdump/ldapdump.tpl b/ldapdump/generic/ldapdump/ldapdump.tpl
similarity index 100%
rename from ldapdump/addons/ldapdump/ldapdump.tpl
rename to ldapdump/generic/ldapdump/ldapdump.tpl
diff --git a/ldapmanager/addons/ldapmanager/class_BaseSelectorOrDnAttribute.inc b/ldapmanager/export/ldapmanager/class_BaseSelectorOrDnAttribute.inc
similarity index 100%
rename from ldapmanager/addons/ldapmanager/class_BaseSelectorOrDnAttribute.inc
rename to ldapmanager/export/ldapmanager/class_BaseSelectorOrDnAttribute.inc
diff --git a/ldapmanager/addons/ldapmanager/class_csvImport.inc b/ldapmanager/export/ldapmanager/class_csvImport.inc
similarity index 100%
rename from ldapmanager/addons/ldapmanager/class_csvImport.inc
rename to ldapmanager/export/ldapmanager/class_csvImport.inc
diff --git a/ldapmanager/addons/ldapmanager/class_ldapExport.inc b/ldapmanager/export/ldapmanager/class_ldapExport.inc
similarity index 100%
rename from ldapmanager/addons/ldapmanager/class_ldapExport.inc
rename to ldapmanager/export/ldapmanager/class_ldapExport.inc
diff --git a/ldapmanager/addons/ldapmanager/class_ldapManagerTabs.inc b/ldapmanager/export/ldapmanager/class_ldapManagerTabs.inc
similarity index 94%
rename from ldapmanager/addons/ldapmanager/class_ldapManagerTabs.inc
rename to ldapmanager/export/ldapmanager/class_ldapManagerTabs.inc
index 7c5295c39698399db296117e2c4d3e3a8535dac5..15928a942d2c7bd86a08245dcb72e794d1f7d53b 100644
--- a/ldapmanager/addons/ldapmanager/class_ldapManagerTabs.inc
+++ b/ldapmanager/export/ldapmanager/class_ldapManagerTabs.inc
@@ -28,8 +28,8 @@ class ldapManagerTabs extends simpleTabs_noSpecial
       'plShortName'   => _('LDAP import/export'),
       'plDescription' => _('Allows the import or export of the ldap tree'),
       'plIcon'        => 'geticon.php?context=applications&icon=ldapmanager&size=48',
-      'plSection'     => 'conf',
       'plPriority'    => 10,
+      'plSection' => ['export' => ['name' => _('Export / Import'), 'priority' => 50]],
       'plCategory'    => ['ldapmanager' => ['objectClass' => 'none', 'description' => _('Ldap manager')]],
     ];
   }
diff --git a/ldapmanager/addons/ldapmanager/class_ldifManager.inc b/ldapmanager/export/ldapmanager/class_ldifManager.inc
similarity index 100%
rename from ldapmanager/addons/ldapmanager/class_ldifManager.inc
rename to ldapmanager/export/ldapmanager/class_ldifManager.inc
diff --git a/opsi/addons/dashboard/class_dashBoardOpsi.inc b/opsi/addons/dashboard/class_dashBoardOpsi.inc
deleted file mode 100644
index fb27fc85569a364258e99709d410c0a7b3f92ec3..0000000000000000000000000000000000000000
--- a/opsi/addons/dashboard/class_dashBoardOpsi.inc
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org)
-  Copyright (C) 2017 FusionDirectory project
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class dashboardOpsi extends simplePlugin
-{
-  static function plInfo (): array
-  {
-    return [
-      'plShortName'   => _('OPSI'),
-      'plDescription' => _('Statistics and information about OPSI'),
-      'plObjectType'  => ['dashboard'],
-
-      'plProvidedAcls'  => []
-    ];
-  }
-
-  static function getAttributesInfo (): array
-  {
-    return [
-      'stats' => [
-        'name'  => _('Statistics'),
-        'attrs' => [new FakeAttribute('stats')],
-        'template' => get_template_path('opsi_stats.tpl', TRUE, dirname(__FILE__)),
-      ],
-      'profiles' => [
-        'name'  => _('Profiles'),
-        'attrs' => [new FakeAttribute('profiles')],
-        'template' => get_template_path('opsi_profiles.tpl', TRUE, dirname(__FILE__)),
-      ],
-    ];
-  }
-
-  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
-  {
-    parent::__construct($dn, $object, $parent, $mainTab);
-
-    $this->stats    = $this->main_stats();
-    $this->profiles = $this->profile_stats();
-  }
-
-  function main_stats ()
-  {
-    global $config;
-    $ldap = $config->get_ldap_link();
-
-    /* Statistics */
-    $stats = [
-      [
-        'name'    => _('OPSI servers'),
-        'type'    => 'server',
-        'filter'  => '(objectClass=opsiServer)',
-        'img'   => 'geticon.php?context=devices&icon=server&size=16'
-      ],
-      [
-        'name'  => _('OPSI clients'),
-        'type'    => 'workstation',
-        'filter'  => '(objectClass=opsiClient)',
-        'img'     => 'geticon.php?context=devices&icon=computer&size=16'
-      ],
-      [
-        'name'  => _('OPSI groups'),
-        'type'    => 'ogroup',
-        'filter'  => '(objectClass=opsiClient)',
-        'img'     => 'geticon.php?context=types&icon=resource-group&size=16'
-      ],
-    ];
-
-    foreach ($stats as &$stat) {
-      try {
-        $stat['nb'] = count(objects::ls($stat['type'], NULL, NULL, $stat['filter'], TRUE));
-      } catch (FusionDirectoryException $e) {
-        $stat['nb'] = 0;
-        $error = new FusionDirectoryError(
-          htmlescape(sprintf(
-            _('Statistics for OPSI could not be computed because of the following error: %s'),
-            $e->getMessage()
-          ))
-        );
-        $error->display();
-      }
-    }
-    unset($stat);
-
-    return $stats;
-  }
-
-  function profile_stats ()
-  {
-    $profiles = objects::ls('opsiProfile', ['cn' => 1, 'fdOpsiServerDn' => 1, 'fdOpsiNetbootProduct' => 1, 'fdOpsiSoftwareList' => '*'], NULL, '', TRUE, 'subtree');
-
-    $id   = 'profileStats';
-    $div  = new divSelectBox('rows'.$id);
-    $smarty = get_smarty();
-    $div->setHeight(90);
-    $div->setHeaders([_('Profile'), _('Systems'), _('Groups')]);
-    foreach ($profiles as $dn => $profile) {
-      $fields = [
-        ['string' => $profile['cn']],
-        ['string' => objects::count('workstation', NULL, '(&(objectClass=opsiClient)(fdOpsiProfileDn='.$dn.'))', FALSE)],
-        ['string' => objects::count('ogroup', NULL, '(&(objectClass=opsiClient)(fdOpsiProfileDn='.$dn.'))', FALSE)],
-      ];
-      $div->addEntry($fields);
-    }
-    return $div->drawList();
-  }
-}
diff --git a/opsi/addons/dashboard/opsi_profiles.tpl b/opsi/addons/dashboard/opsi_profiles.tpl
deleted file mode 100644
index 2e5acbb892a4b1d01d86c96ccfad8e7d374366b8..0000000000000000000000000000000000000000
--- a/opsi/addons/dashboard/opsi_profiles.tpl
+++ /dev/null
@@ -1,8 +0,0 @@
-<div id="{$sectionId}" class="plugin-section">
-  <span class="legend">
-    {if $sectionIcon}<img src="{$sectionIcon|escape}" alt=""/>{/if}{$section|escape}
-  </span>
-  <div>
-    {$attributes.profiles}
-  </div>
-</div>
diff --git a/opsi/addons/dashboard/opsi_stats.tpl b/opsi/addons/dashboard/opsi_stats.tpl
deleted file mode 100644
index 80f0fd7d6f75d5e7e38c3fa373c5787e7f67d51a..0000000000000000000000000000000000000000
--- a/opsi/addons/dashboard/opsi_stats.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-<div id="{$sectionId}" class="plugin-section">
-  <span class="legend">
-    {if $sectionIcon}<img src="{$sectionIcon|escape}" alt=""/>{/if}{$section|escape}
-  </span>
-  <div>
-    <ul>
-    {foreach from=$attributes.stats item=stat}
-    <li style="list-style-image:url({$stat.img|escape})">
-      {$stat.nb|escape} {$stat.name|escape}
-    </li>
-    {/foreach}
-    </ul>
-  </div>
-</div>
diff --git a/opsi/addons/opsi/class_opsiImport.inc b/opsi/export/opsi/class_opsiImport.inc
similarity index 98%
rename from opsi/addons/opsi/class_opsiImport.inc
rename to opsi/export/opsi/class_opsiImport.inc
index 1a78530646efe8a0b20e170ebb9f5071bb6b6595..c10fbd327dbafc987ff5f9f8da91b713987fcf9c 100644
--- a/opsi/addons/opsi/class_opsiImport.inc
+++ b/opsi/export/opsi/class_opsiImport.inc
@@ -38,9 +38,8 @@ class opsiImport extends systemImport
           'mainAttr'  => FALSE,
         ]
       ],
-      'plSection'     => 'conf',
+      'plSection' => ['export' => ['name' => _('Export / Import'), 'priority' => 50]],
       'plPriority'    => 15,
-
       'plProvidedAcls'  => parent::generatePlProvidedAcls(static::getAttributesInfo())
     ];
   }
diff --git a/opsi/addons/opsi/main.inc b/opsi/export/opsi/main.inc
similarity index 100%
rename from opsi/addons/opsi/main.inc
rename to opsi/export/opsi/main.inc
diff --git a/opsi/addons/opsi/opsiimport.tpl b/opsi/export/opsi/opsiimport.tpl
similarity index 100%
rename from opsi/addons/opsi/opsiimport.tpl
rename to opsi/export/opsi/opsiimport.tpl
diff --git a/ppolicy/addons/dashboard/class_dashBoardPPolicy.inc b/ppolicy/addons/dashboard/class_dashBoardPPolicy.inc
deleted file mode 100644
index 02c63a0f55dc9549fa43c3058c147bbe23d34a86..0000000000000000000000000000000000000000
--- a/ppolicy/addons/dashboard/class_dashBoardPPolicy.inc
+++ /dev/null
@@ -1,191 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org)
-  Copyright (C) 2014-2015  Dhatim
-  Copyright (C) 2014-2016  FusionDirectory project
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class dashboardPpolicy extends simplePlugin
-{
-  static function plInfo (): array
-  {
-    return [
-      'plShortName'   => _('Ppolicy'),
-      'plDescription' => _('Statistics about ppolicy expired users'),
-      'plObjectType'  => ['dashboard'],
-      'plPriority'    => 12,
-
-      'plProvidedAcls'  => []
-    ];
-  }
-
-  static function getAttributesInfo (): array
-  {
-    return [
-      'expired_accounts' => [
-        'name'  => _('Expired accounts'),
-        'attrs' => [new FakeAttribute('expired')],
-        'template' => get_template_path('users_accounts.tpl', TRUE, dirname(__FILE__)),
-      ],
-      'locked_accounts' => [
-        'name'  => _('Locked accounts'),
-        'attrs' => [new FakeAttribute('locked')],
-        'template' => get_template_path('ppolicy_locked_accounts.tpl', TRUE, dirname(__FILE__)),
-      ],
-    ];
-  }
-
-  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
-  {
-    parent::__construct($dn, $object, $parent, $mainTab);
-
-    $this->expiredAccountsColumns = [
-      'user' => [
-        'uid'             => _('Login'),
-        'cn'              => _('Name'),
-        'telephoneNumber' => _('Phone number'),
-        'expirationDate'  => _('Expiration date'),
-      ],
-      'manager' => [
-        'manager_cn'      => _('Name'),
-        'manager_mail'    => _('Email'),
-        'manager_phone'   => _('Phone number'),
-      ]
-    ];
-
-    $this->compute_accounts_info();
-  }
-
-  function compute_accounts_info ()
-  {
-    global $config;
-    $ldap = $config->get_ldap_link();
-
-    $defaultMaxAge = NULL;
-    $ppolicydn = $config->get_cfg_value('ppolicyDefaultDn', '');
-    if (!empty($ppolicydn)) {
-      $ldap->cat($ppolicydn, ['pwdMaxAge']);
-      $policy = $ldap->fetch();
-      if (!$policy) {
-        $error = new SimplePluginError(
-          $this,
-          htmlescape(sprintf(
-            _('Default ppolicy "%s" could not be found in the LDAP!'),
-            $ppolicydn
-          ))
-        );
-        $error->display();
-      } elseif (isset($policy['pwdMaxAge'][0])) {
-        $defaultMaxAge = $policy['pwdMaxAge'][0];
-      }
-    }
-
-    /* Fetch global value from configuration */
-    $next_expired_days  = $config->get_cfg_value('dashboardExpiredAccountsDays', 15);
-    /* Convert it to seconds */
-    $next_expired_days_seconds = $next_expired_days * 24 * 60 * 60;
-    /* Ppolicy stores all dates in UTC */
-    $now = new DateTime('now', timezone::utc());
-
-    /* search all expired accounts */
-    $users = objects::ls('user', [
-        'dn'                    => 'raw',
-        'uid'                   => 'raw',
-        'cn'                    => 'raw',
-        'mail'                  => 'raw',
-        'telephoneNumber'       => 'raw',
-        'manager'               => 'raw',
-        'pwdChangedTime'        => 1,
-        'pwdPolicySubentry'     => 1,
-        'pwdAccountLockedTime'  => 1,
-      ], NULL, '(|(pwdAccountLockedTime=*)(pwdChangedTime=*))', TRUE);
-    $locked_users           = [];
-    $expired_accounts       = [];
-    $next_expired_accounts  = [];
-    // ppolicies cache
-    $maxAges = [];
-    foreach ($users as $user) {
-      if (isset($user['pwdAccountLockedTime'])) {
-        $locked_user  = dashboardUsers::get_user_infos($user);
-        $lockedTime   = LdapGeneralizedTime::fromString($user['pwdAccountLockedTime']);
-        $lockedTime->setTimezone(timezone::getDefaultTimeZone());
-        $locked_user['pwdAccountLockedTime']  = $lockedTime->format('Y-m-d H:i:s');
-        $locked_users[]                       = $locked_user;
-      }
-      if (!isset($user['pwdChangedTime'])) {
-        continue;
-      }
-      $maxAge = NULL;
-      if (isset($user['pwdPolicySubentry'])) {
-        if (isset($maxAges[$user['pwdPolicySubentry']])) {
-          $maxAge = $maxAges[$user['pwdPolicySubentry']];
-        } else {
-          $ldap->cat($user['pwdPolicySubentry'], ['pwdMaxAge']);
-          $policy = $ldap->fetch();
-          if (!$policy) {
-            $error = new SimplePluginError(
-              $this,
-              htmlescape(sprintf(
-                _('Ppolicy "%s" set for user "%s" could not be found in the LDAP!'),
-                $ppolicydn,
-                $user['dn']
-              ))
-            );
-            $error->display();
-            continue;
-          }
-          if (isset($policy['pwdMaxAge'][0])) {
-            $maxAge = $policy['pwdMaxAge'][0];
-          }
-          $maxAges[$user['pwdPolicySubentry']] = $maxAge;
-        }
-      } elseif ($defaultMaxAge !== NULL) {
-        $maxAge = $defaultMaxAge;
-      }
-      if (($maxAge === NULL) || ($maxAge <= 0)) {
-        /* No max age, it can’t be expired */
-        continue;
-      }
-      /* Build expiration date from pwdChangedTime and max age */
-      $expDate = LdapGeneralizedTime::fromString($user['pwdChangedTime']);
-      $expDate->setTimezone(timezone::utc());
-      $expDate->add(new DateInterval('PT'.$maxAge.'S'));
-      if ($expDate->getTimeStamp() < $now->getTimeStamp()) {
-        $expired_account = dashboardUsers::get_user_infos($user);
-        $expired_account['expirationDate'] = $expDate->format('d.m.Y');
-        $expired_accounts[] = $expired_account;
-      } elseif ($expDate->getTimeStamp() < ($now->getTimeStamp() + $next_expired_days_seconds)) {
-        $expired_account = dashboardUsers::get_user_infos($user);
-        $expired_account['expirationDate'] = $expDate->format('d.m.Y');
-        $next_expired_accounts[] = $expired_account;
-      }
-    }
-
-    uasort($expired_accounts, ['dashboardUsers','compareUsers']);
-    uasort($next_expired_accounts, ['dashboardUsers','compareUsers']);
-
-    $this->expired = [
-      'columns'             => $this->expiredAccountsColumns,
-      'accounts'            => $expired_accounts,
-      'accounts_next_days'  => $next_expired_accounts,
-      'next_days'           => $next_expired_days,
-    ];
-    $this->locked = [
-      'accounts'  => $locked_users,
-    ];
-  }
-}
diff --git a/subscriptions/admin/subscriptions/class_subscriptionsManagement.inc b/subscriptions/admin/subscriptions/class_subscriptionsManagement.inc
index 15b4f66585cd5b1adba64c094ab1d7dc346b6772..d2213d1637640b9b8d57cd2350d17b9c309bfa1a 100644
--- a/subscriptions/admin/subscriptions/class_subscriptionsManagement.inc
+++ b/subscriptions/admin/subscriptions/class_subscriptionsManagement.inc
@@ -41,7 +41,7 @@ class subscriptionsManagement extends management
       'plTitle'       => _('Subscription management'),
       'plDescription' => _('Manage subscriptions'),
       'plIcon'        => 'geticon.php?context=applications&icon=subscription&size=48',
-      'plSection'     => 'accounts',
+      'plSection'     => 'conf',
       'plManages'     => ['subscription'],
 
       'plProvidedAcls' => []
diff --git a/subscriptions/config/subscriptions/class_subscriptionsConfig.inc b/subscriptions/config/subscriptions/class_subscriptionsConfig.inc
index f7584fe7e844f25e5564eafac1da8627f014fe9b..9db6bebc1db5194a590dd6aba2af049a71cd55ba 100644
--- a/subscriptions/config/subscriptions/class_subscriptionsConfig.inc
+++ b/subscriptions/config/subscriptions/class_subscriptionsConfig.inc
@@ -28,7 +28,8 @@ class subscriptionsConfig extends simplePlugin
       'plDescription'   => _('FusionDirectory subscriptions plugin configuration'),
       'plObjectClass'   => ['fdSubscriptionsPluginConf'],
       'plObjectType'    => ['configuration'],
-
+      'plIcon'        => 'geticon.php?context=applications&icon=subscriptions&size=48',
+      'plSmallIcon'   => 'geticon.php?context=applications&icon=subscriptions&size=16',
       'plProvidedAcls'  => parent::generatePlProvidedAcls(static::getAttributesInfo())
     ];
   }
@@ -60,8 +61,8 @@ class subscriptionsConfig extends simplePlugin
                 ),
               ],
               ';',
-              '',
-              _('Subscription types')
+                  '',
+                  _('Subscription types')
             ),
             FALSE,
             [],
@@ -109,8 +110,8 @@ class subscriptionsConfig extends simplePlugin
                 ),
               ],
               ';',
-              '',
-              _('Rpm repositories')
+                  '',
+                  _('Rpm repositories')
             ),
             FALSE,
             [],
diff --git a/subscriptions/html/themes/breezy/icons/16/apps/subscription.png b/subscriptions/html/themes/breezy/icons/16/apps/subscription.png
index fe0bdb7f02ed9f4f1324dd1b42563e96724a2a2d..4e8405ebf930f640da8c72d019bd3696b7ad7e19 100644
Binary files a/subscriptions/html/themes/breezy/icons/16/apps/subscription.png and b/subscriptions/html/themes/breezy/icons/16/apps/subscription.png differ
diff --git a/subscriptions/html/themes/breezy/icons/48/apps/subscription.png b/subscriptions/html/themes/breezy/icons/48/apps/subscription.png
index 895cfe581dd234f5f0e6182446cde3bab4118ce5..5dd3439bfabb32a83ee867001240d0296fadd85b 100644
Binary files a/subscriptions/html/themes/breezy/icons/48/apps/subscription.png and b/subscriptions/html/themes/breezy/icons/48/apps/subscription.png differ
diff --git a/supann/admin/supannStructures/class_entite.inc b/supann/admin/supannStructures/class_entite.inc
index 16637647a67840bc243f437995fd250630f2a4ce..a9464d341d99b945db271c70e4f6567b650b59af 100644
--- a/supann/admin/supannStructures/class_entite.inc
+++ b/supann/admin/supannStructures/class_entite.inc
@@ -115,7 +115,6 @@ class entite extends simplePlugin
 
     $this->attributesAccess['supannCodeEntiteParent']->attribute->setChoices($code_entites, $label_entites);
 
-    $this->attributesAccess['ou']->setUnique('one');
     $this->attributesAccess['supannCodeEntite']->setUnique('whole', '(objectClass=supannEntite)');
     $this->attributesAccess['supannRefId']->setUnique('whole', '(objectClass=supannEntite)');
   }
diff --git a/supann/contrib/openldap/fdFranceConnect.schema b/supann/contrib/openldap/fdFranceConnect.schema
new file mode 100644
index 0000000000000000000000000000000000000000..0087974a1833875bdb0abec0145fd3c19ad9746c
--- /dev/null
+++ b/supann/contrib/openldap/fdFranceConnect.schema
@@ -0,0 +1,4 @@
+objectclass ( 1.3.6.1.4.1.38414.88.2.1 NAME 'fdFranceConnect' SUP top AUXILIARY
+	DESC 'Identité de personne FranceConnect'
+	MAY ( supannNomDeNaissance $ supannPrenomsEtatCivil $ supannOIDCDateDeNaissance $
+	supannOIDCGenre $ supannCodeINSEEPaysDeNaissance $ supannFCSub $ supannCodeINSEEVilleDeNaissance ))
diff --git a/supann/personal/supann/class_supannFC.inc b/supann/personal/supann/class_supannFC.inc
index c37d236a72b8df174c390dafc9e91cfbeace54b0..4072dfc37e719ad25610bed040706c0e771480e9 100644
--- a/supann/personal/supann/class_supannFC.inc
+++ b/supann/personal/supann/class_supannFC.inc
@@ -33,7 +33,7 @@ class supannFC extends simplePlugin
       'plShortName'   => _('France Connect'),
       'plDescription' => _('France Connect identity'),
       'plSelfModify'  => TRUE,
-      'plObjectClass' => ['supannFCPerson'],
+      'plObjectClass' => ['fdFranceConnect'],
       'plObjectType'  => ['user'],
       'plIcon'        => 'geticon.php?context=applications&icon=supann&size=48',
       'plSmallIcon'   => 'geticon.php?context=applications&icon=supann&size=16',
@@ -51,27 +51,27 @@ class supannFC extends simplePlugin
         'attrs' => [
           new StringAttribute(
             _('Birth name'), _('Last name from birth'),
-            'supannNomDeNaissance', TRUE
+            'supannNomDeNaissance', FALSE
           ),
           new StringAttribute(
             _('First names'), _('Space separated first names'),
-            'supannPrenomsEtatCivil', TRUE
+            'supannPrenomsEtatCivil', FALSE
           ),
           new DateAttribute(
             _('Date of birth'), _('Date of birth'),
-            'supannOIDCDateDeNaissance', TRUE,
+            'supannOIDCDateDeNaissance', FALSE,
             'Y-m-d', '',
             // min and max:
             NULL, 'now'
           ),
           new SelectAttribute(
             _('Gender'), _('Gender'),
-            'supannOIDCGenre', TRUE,
+            'supannOIDCGenre', FALSE,
             ['other', 'female', 'male'], '', [_('Other'), _('Female'), _('Male')]
           ),
           new StringAttribute(
             _('Country of birth'), _('INSEE code of country of birth'),
-            'supannCodeINSEEPaysDeNaissance', TRUE,
+            'supannCodeINSEEPaysDeNaissance', FALSE,
             '',
             '',
             '/^\d{5}$/',
@@ -93,7 +93,7 @@ class supannFC extends simplePlugin
           new SetAttribute(
             new StringAttribute(
               _('Subject'), _('Subject from OpenID Connect standard in the France Connect system'),
-              'supannFCSub', TRUE,
+              'supannFCSub', FALSE,
               '',
               '',
               '/^[[:ascii:]]{1,255}$/'
diff --git a/systems/addons/dashboard/class_dashBoardNetwork.inc b/systems/addons/dashboard/class_dashBoardNetwork.inc
deleted file mode 100644
index 06657282af890348b5ee63e09b5e5367109dd3e0..0000000000000000000000000000000000000000
--- a/systems/addons/dashboard/class_dashBoardNetwork.inc
+++ /dev/null
@@ -1,140 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org)
-  Copyright (C) 2010 Antoine Gallavardin
-  Copyright (C) 2011-2016 FusionDirectory project
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class dashboardNetwork extends simplePlugin
-{
-  static function plInfo (): array
-  {
-    return [
-      'plShortName'   => _('Network'),
-      'plDescription' => _('Statistics and various information'),
-      'plObjectType'  => ['dashboard'],
-      'plPriority'    => 22,
-
-      'plProvidedAcls'  => []
-    ];
-  }
-
-  static function getAttributesInfo (): array
-  {
-    return [
-      'dhcp' => [
-        'name'  => _('DHCP'),
-        'attrs' => [new FakeAttribute('dhcp_infos')],
-        'template' => get_template_path('network_dhcp.tpl', TRUE, dirname(__FILE__)),
-      ],
-      'dns' => [
-        'name'  => _('DNS'),
-        'attrs' => [new FakeAttribute('dns_infos')],
-        'template' => get_template_path('network_dhcp.tpl', TRUE, dirname(__FILE__)),
-      ],
-    ];
-  }
-
-  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
-  {
-    parent::__construct($dn, $object, $parent, $mainTab);
-
-    $this->dhcp_infos = $this->dhcp_infos();
-    if (empty($this->dhcp_infos)) {
-      unset($this->attributesInfo['dhcp']);
-    }
-
-    $this->dns_infos = $this->dns_infos();
-    if (empty($this->dns_infos)) {
-      unset($this->attributesInfo['dns']);
-    }
-  }
-
-  function dhcp_infos ()
-  {
-    global $config, $ui;
-
-    if (!class_available('dhcpService')) {
-      return [];
-    }
-
-    try {
-      $objects = objects::ls('server', ['cn' => 'raw', 'dhcpServiceDN' => 1], NULL, '(objectClass=dhcpServer)', TRUE);
-    } catch (FusionDirectoryException $e) {
-      $objects = [];
-      $error = new FusionDirectoryError(
-        htmlescape(sprintf(
-          _('Statistics for DHCP could not be computed because of the following error: %s'),
-          $e->getMessage()
-        )),
-        0,
-        $e
-      );
-      $error->display();
-    }
-
-    $servers = [];
-    foreach ($objects as $dn => $attrs) {
-      $zones = [];
-      if (strpos($ui->get_permissions($attrs['dhcpServiceDN'], 'dhcpConfiguration/dhcpSubnet', 'dhcpNetMask'), 'r') !== FALSE) {
-        $ldap_zone = $config->get_ldap_link();
-        $ldap_zone->cd($attrs['dhcpServiceDN']);
-        $ldap_zone->search('(objectClass=dhcpSubnet)', ['cn','dhcpNetMask']);
-        while ($attrs_zone = $ldap_zone->fetch()) {
-          $zones[] = [
-            'text' => $attrs_zone['cn'][0]."/".$attrs_zone['dhcpNetMask'][0]
-          ];
-        }
-      }
-
-      $servers[] = [
-        'name'  => $attrs['cn'][0],
-        'link'  => objects::link($dn, 'server', 'service_serviceDHCP', $attrs, FALSE),
-        'zones' => $zones
-      ];
-    }
-
-    return $servers;
-  }
-
-  function dns_infos ()
-  {
-    if (!class_available('dnsZone')) {
-      return [];
-    }
-    $servers  = [];
-    $zones    = objects::ls('dnsZone', ['zoneName' => 1, 'sOARecord' => 1], NULL, '', TRUE);
-    foreach ($zones as $zonedn => $zone) {
-      list ($fqdn)  = explode(' ', $zone['sOARecord']);
-      $search = dnsManagement::findServerByFQDN($fqdn, $zonedn);
-      foreach ($search as $dn => $name) {
-        if (!isset($servers[$dn])) {
-          $servers[$dn] = [
-            'name'  => $name,
-            'link'  => objects::link($dn, 'server', 'tab_dnsHost', $name, FALSE),
-            'zones' => []
-          ];
-        }
-        $servers[$dn]['zones'][] = [
-          'link' => objects::link($zonedn, 'dnsZone', '', $zone['zoneName'], FALSE)
-        ];
-      }
-    }
-
-    return array_values($servers);
-  }
-}
diff --git a/systems/addons/dashboard/class_dashBoardSystems.inc b/systems/addons/dashboard/class_dashBoardSystems.inc
deleted file mode 100644
index 90b3a68645209cb5dabd10b487c67a44a0cd5766..0000000000000000000000000000000000000000
--- a/systems/addons/dashboard/class_dashBoardSystems.inc
+++ /dev/null
@@ -1,245 +0,0 @@
-<?php
-/*
-  This code is part of FusionDirectory (http://www.fusiondirectory.org)
-  Copyright (C) 2010 Antoine Gallavardin
-  Copyright (C) 2011-2016 FusionDirectory project
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program 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 General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
-*/
-
-class dashboardSystems extends simplePlugin
-{
-  /* default values */
-  var $default_start_computer_id = 0;
-
-  static function plInfo (): array
-  {
-    return [
-      'plShortName'   => _('Systems'),
-      'plDescription' => _('Statistics and information about systems'),
-      'plObjectType'  => ['dashboard'],
-      'plPriority'    => 20,
-
-      'plProvidedAcls'  => []
-    ];
-  }
-
-  static function getAttributesInfo (): array
-  {
-    return [
-      'stats' => [
-        'name'  => _('Statistics'),
-        'attrs' => [new FakeAttribute('stats')],
-        'template' => get_template_path('systems_stats.tpl', TRUE, dirname(__FILE__)),
-      ],
-      'pc_ids' => [
-        'name'  => _('Computer name to use by unit'),
-        'attrs' => [new FakeAttribute('pc_ids')],
-        'template' => get_template_path('systems_pcids.tpl', TRUE, dirname(__FILE__)),
-      ],
-    ];
-  }
-
-  function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE)
-  {
-    parent::__construct($dn, $object, $parent, $mainTab);
-
-    $this->stats = [
-      'systems' => $this->systems_stats(),
-      'argonaut' => $this->argonaut_stats(),
-    ];
-    $this->pc_ids = $this->computer_ids_rules();
-  }
-
-  protected function systems_stats ()
-  {
-    global $config;
-    $ldap = $config->get_ldap_link();
-
-    /* Statistics */
-    $stats = [
-      ['name'  => _('Workstations'),
-            'type'  => 'workstation',
-            'img'   => 'geticon.php?context=devices&icon=computer&size=16'
-      ],
-      ['name'  => _('Servers'),
-            'type'  => 'server',
-            'img'   => 'geticon.php?context=devices&icon=server&size=16'
-      ],
-      ['name'    => _('Windows Workstations'),
-            'type'    => 'workstation',
-            'filter'  => '(objectClass=sambaSamAccount)',
-            'img'     => 'geticon.php?context=devices&icon=computer-windows&size=16'
-      ],
-      ['name'  => _('Terminals'),
-            'type'  => 'terminal',
-            'img'   => 'geticon.php?context=devices&icon=terminal&size=16'
-      ],
-      ['name'  => _('Printers'),
-            'type'  => 'printer',
-            'img'   => 'geticon.php?context=devices&icon=printer&size=16'
-      ],
-      ['name'  => _('Phones'),
-            'type'  => 'phone',
-            'img'   => 'geticon.php?context=devices&icon=telephone&size=16'
-      ],
-      ['name'  => _('Components'),
-            'type'  => 'component',
-            'img'   => 'geticon.php?context=devices&icon=network-device&size=16'
-      ],
-      ['name'  => _('Mobile phones'),
-            'type'  => 'mobilePhone',
-            'img'   => 'geticon.php?context=devices&icon=phone&size=16'],
-    ];
-
-    foreach ($stats as $key => &$stat) {
-      try {
-        $stat['nb'] = count(objects::ls($stat['type'], NULL, NULL, (isset($stat['filter']) ? $stat['filter'] : ''), TRUE));
-        if ($stat['nb'] == 0) {
-          unset($stats[$key]);
-        }
-      } catch (FusionDirectoryException $e) {
-        unset($stats[$key]);
-        $error = new FusionDirectoryError(
-          htmlescape(sprintf(
-            _('Statistics for type "%s" could not be computed because of the following error: %s'),
-            $stat['type'],
-            $e->getMessage()
-          )),
-          0,
-          $e
-        );
-        $error->display();
-      }
-    }
-    unset($stat);
-
-    return $stats;
-  }
-
-  protected function argonaut_stats ()
-  {
-    global $config, $ui;
-
-    if (!class_available('argonautServer')) {
-      return FALSE;
-    }
-
-    $argonaut_servers = objects::ls(
-      'server',
-      ['cn' => 'raw','ipHostNumber' => 'raw','argonautProtocol' => 'raw','argonautPort' => 'raw'],
-      NULL,
-      '(objectClass=argonautServer)',
-      TRUE
-    );
-    $nb_argonaut_server = count($argonaut_servers);
-    $argonaut_server    = [];
-    if ($nb_argonaut_server == 1) {
-      $attrs = reset($argonaut_servers);
-      foreach (['cn','ipHostNumber','argonautProtocol','argonautPort'] as $key) {
-        $argonaut_server[$key] = $attrs[$key][0];
-      }
-      $argonaut_server['link'] = objects::link(key($argonaut_servers), 'server', 'service_argonautServer', $attrs);
-    }
-
-    if (strpos($ui->get_permissions($config->current['BASE'], 'server/argonautClient', ''), 'r') === FALSE) {
-      $nb_argonaut_clients = 0;
-    } else {
-      $ldap = $config->get_ldap_link();
-      $ldap->cd($config->current['BASE']);
-      $ldap->search('(objectClass=argonautClient)', ['cn']);
-      $nb_argonaut_clients = $ldap->count();
-    }
-
-    return [
-      'nb_servers'  => $nb_argonaut_server,
-      'server'      => $argonaut_server,
-      'nb_clients'  => $nb_argonaut_clients,
-    ];
-  }
-
-  protected function computer_ids_rules ()
-  {
-    global $config;
-    $ldap = $config->get_ldap_link();
-    $ldap->cd($config->current['BASE']);
-    /* Begin of code for selecting next computer IDs
-    * Global variable is board_next_computer_ids_rule
-    * syntax is :
-    * 7 : nb total of digit
-    * LYP3 : prefix to use
-    * each prefix is followed by the first item flagged by an equal sign
-    * ex : "7;LYP0=3;LYP1=6;LYP2;LYP3"
-    * if to item is doned it's 0 by default
-    *
-    */
-
-    $output_next_computer_ids = "";
-    $computer_ids_rules = $config->get_cfg_value('dashboardPrefix', ['PC']);
-    if (!is_array($computer_ids_rules)) {
-      $computer_ids_rules = [$computer_ids_rules];
-    }
-
-    $nb_digits = $config->get_cfg_value('dashboardNumberOfDigit', 3);
-
-    /* running all the table */
-    foreach ($computer_ids_rules as $rule) {
-      /* aray initialization*/
-      $array_complete_list  = [];
-      $array_real_list      = [];
-      $unused_computer_ids  = [];
-      /* get computer ids configuration */
-      $config_ids = explode("=", $rule);
-      /* fist is is the prefix */
-      $prefix = $config_ids[0];
-      /* second (if specified) is the first item */
-      if (!isset($config_ids[1])) {
-        $start_id = $this->default_start_computer_id;
-      } else {
-        $start_id = $config_ids[1];
-      }
-
-      $output_next_computer_ids = $output_next_computer_ids.'<tr><th style="padding:4px;border:1px solid #BBB;">'.$prefix."</th>";
-      $nb_digits_suffix         = $nb_digits - strlen($prefix);
-
-      /* generation of list of suffixe */
-      for ($d = $start_id;$d < (10 ** $nb_digits_suffix);$d++) {
-        /* padding : 34 on 4 digit become : 0034*/
-        $array_complete_list[] = str_pad($d, $nb_digits_suffix, "0", STR_PAD_LEFT);
-      }
-
-      /* request of all computer beginning by the prefix */
-      $request = '(&(cn='.$prefix.'*)(ou:dn:=systems))';
-      $ldap->search($request, ["cn"]);
-      while ($attrs = $ldap->fetch()) {
-        /* if a computer is a windows host, we have to delete the $ at the end */
-        $computer_id        = str_replace("$", "", $attrs["cn"][0]);
-        $array_real_list[]  = substr($computer_id, -$nb_digits_suffix);
-      }
-      /* make dfference between real and complete list */
-      $unused_computer_ids = array_diff($array_complete_list, $array_real_list);
-      asort($unused_computer_ids);
-      $unused_computer_ids = array_values($unused_computer_ids);
-      /* we take the 5 first */
-
-      for ($r = 0;$r <= 5;$r++) {
-        $output_next_computer_ids .= '<td style="padding:4px;border-bottom:1px solid #BBB;">'.$prefix.$unused_computer_ids[$r]."</td>";
-      }
-      $output_next_computer_ids .= "</tr>";
-    }
-
-    return $output_next_computer_ids;
-  }
-}