adminHeader.ftl
1 <#--
2 Macro: adminHeader
3 Description: Generates a header section for an administrative page, including a navigation menu and user account menu.
4 Parameters:
5 - site_name (string, required): the name of the website or application.
6 -->
7 <#macro adminHeader site_name=site_name!'Lutece' admin_url=admin_url >
8 <#local userReadMode><#attempt>${dskey('portal.site.site_property.layout.user.readmode.show.checkbox')?number}<#recover>0</#attempt></#local>
9 <#local userDarkMode><#attempt>${dskey('portal.site.site_property.layout.user.darkmode.show.checkbox')?number}<#recover>0</#attempt></#local>
10 <#local userMenuMode><#attempt>${dskey('portal.site.site_property.layout.user.menumode.show.checkbox')?number}<#recover>0</#attempt></#local>
11 <#local readMode><#attempt><#if dskey('portal.site.site_property.layout.readmode.checkbox')?number = 1> dir="rtl"</#if><#recover></#attempt></#local>
12 <#local darkMode><#attempt><#if dskey('portal.site.site_property.layout.darkmode.checkbox')?number==1> theme-dark</#if><#recover></#attempt></#local>
13 <#local layout><#attempt><#if dskey('portal.site.site_property.layout.menu.checkbox')?number==1>aside<#else>header</#if><#recover>header</#attempt></#local>
14 <#local logoUrl = (dskey('portal.site.site_property.logo_url')!)?has_content?then(dskey('portal.site.site_property.logo_url'), 'themes/admin/shared/images/logo-header-icon.svg')>
15 </head>
16 <body class="antialiased"${readMode}>
17 <@adminSkipNav />
18 <div id="lutece-layout-wrapper" class="${layout!}" data-userdarkmode="${userDarkMode}" data-usermenu="${userMenuMode}">
19 <header class="lutece-header" >
20 <nav class="lutece-nav navbar navbar-expand-lg d-print-none" data-bs-theme="dark">
21 <div class="container-fluid">
22 <a class="lutece-brand navbar-brand navbar-brand-autodark d-none-navbar-horizontal pe-0" href="${dskey('portal.site.site_property.home_url')}" title="#i18n{portal.users.admin_header.title.viewSite} ${site_name}" target="_blank" title="#i18n{portal.site.portal_footer.newWindow}">
23 <img src="${logoUrl}" height="30" alt="Logo ${site_name}" aria-hidden="true">
24 <span class="ml-2 ms-2">${site_name}</span>
25 </a>
26 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
27 <span class="navbar-toggler-icon"></span>
28 <span class="visually-hidden">#i18n{portal.util.labelShow} / #i18n{portal.util.labelHide}</span>
29 </button>
30 <div class="lutece-collapse collapse navbar-collapse" id="navbar-menu">
31 <ul class="navbar-nav">
32 <#list feature_group_list as feature_group>
33 <#if feature_group.icon?length < 1>
34 <#assign icon_class = "ti ti-mood-empty">
35 <#else>
36 <#assign icon_class = feature_group.icon>
37 </#if>
38 <#if feature_group.features?size > 1>
39 <li class="nav-item dropdown">
40 <a class="nav-link dropdown-toggle" id="dLabel${feature_group.id}Header" role="button" data-bs-toggle="dropdown" role="button" aria-expanded="false" href="${admin_url}#${feature_group.id}">
41 <i class="${icon_class} me-1"></i> <span>${feature_group.label}</span>
42 </a>
43 <div class="dropdown-menu" aria-labelledby="dLabel${feature_group.id}Header">
44 <div class="dropdown-menu-columns">
45 <div class="dropdown-menu-column">
46 <#list feature_group.features as feature>
47 <#if !feature.externalFeature>
48 <a class="dropdown-item" href="${feature.url}?plugin_name=${feature.pluginName}" title="${feature.name}">
49 <i class="${feature.iconUrl} me-1"></i>
50 <span>${feature.name} </span>
51 </a>
52 <#else>
53 <a class="dropdown-item" href="${feature.url}" title="${feature.name}">
54 <#if feature.iconUrl?has_content><i class="${feature.iconUrl} me-1"></i></#if>
55 <span>${feature.name}</span>
56 </a>
57 </#if>
58 </#list>
59 </div>
60 </div>
61 </div>
62 </li>
63 <#else>
64 <#list feature_group.features as feature>
65 <li class="nav-item">
66 <#if !feature.externalFeature>
67 <a class="nav-link" href="${feature.url}?plugin_name=${feature.pluginName}"><#if feature.iconUrl?has_content>
68 <i class="${feature.iconUrl} me-1"></i></#if>
69 <span>${feature.name}</span>
70 </a>
71 <#else>
72 <a class="nav-link" href="${feature.url}"><#if feature.iconUrl?has_content><i class="${feature.iconUrl} me-1"></i></#if>
73 <span>${feature.name}</span>
74 </a>
75 </#if>
76 </li>
77 </#list>
78 </#if>
79 </#list>
80 <li class="nav-item d-none d-lg-flex ms-auto">
81 <a class="nav-link" href="${admin_url}" title="#i18n{portal.users.admin_header.homePage}" id="go-home">
82 <i class="ti ti-home"></i><span class="visually-hidden">#i18n{portal.users.admin_header.homePage}</span>
83 </a>
84 </li>
85 <li class="nav-item d-flex d-lg-none mt-2">
86 <a class="nav-link" href="${admin_url}" title="#i18n{portal.users.admin_header.homePage}" id="go-home">
87 <i class="ti ti-home me-2"></i> <span>#i18n{portal.users.admin_header.homePage}</span>
88 </a>
89 </li>
90 <#if userMenuMode?number = 1>
91 <li class="nav-item d-none d-lg-flex">
92 <div class="nav-link" title="#i18n{portal.users.admin_header.labelMenuV} / #i18n{portal.users.admin_header.labelMenuH}" id="switch-menu" tabindex="0" role="button" data-bs-toggle="tooltip" data-bs-animation="false" data-bs-placement="bottom" data-bs-original-title="#i18n{portal.users.admin_header.labelMenuV} / #i18n{portal.users.admin_header.labelMenuH}">
93 <i class="ti ti-layout-navbar-collapse menu-rotate-icon"></i><span class="visually-hidden">#i18n{portal.users.admin_header.labelMenuV} / #i18n{portal.users.admin_header.labelMenuH}</span>
94 </div>
95 </li>
96 </#if>
97 <#if userDarkMode?number = 1>
98 <li class="nav-item" id="switch-darkmode">
99 <div class="nav-link d-none d-lg-flex" tabindex="0" role="button">
100 <i class="ti ti-moon"></i><span class="visually-hidden">#i18n{portal.users.admin_header.labelMode} <span>#i18n{portal.users.admin_header.labelDarkMode}</span></span>
101 </div>
102 <div class="nav-link d-flex d-lg-none" tabindex="0" role="button">
103 <i class="ti ti-moon me-2"></i> <span>#i18n{portal.users.admin_header.labelMode} #i18n{portal.users.admin_header.labelDarkMode}</span>
104 </div>
105 </li>
106 </#if>
107 <#if userReadMode?number = 1>
108 <@adminReadMode />
109 </#if>
110 <#if user.userLevel == 0>
111 <#if listLoggersInfo??>
112 <#assign listLogDebug = listLoggersInfo?filter( logInfo -> ( logInfo.level = 'DEBUG' || logInfo.level = 'TRACE' ) ) />
113 <#if listLogDebug?has_content>
114 <li class="nav-item d-none d-lg-flex">
115 <a href="#" class="nav-link" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show notifications" aria-expanded="false">
116 <svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M10 5a2 2 0 0 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3h-16a4 4 0 0 0 2 -3v-3a7 7 0 0 1 4 -6"></path><path d="M9 17v1a3 3 0 0 0 6 0v-1"></path></svg>
117 <#if listLoggersInfo?has_content><span class="badge bg-red"></span></#if>
118 </a>
119 <div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
120 <div class="card">
121 <div class="card-header">
122 <h3 class="card-title">Notifications</h3>
123 </div>
124 <div class="list-group list-group-flush list-group-hoverable">
125 <div class="list-group-item logger">
126 <div class="row align-items-start">
127 <div class="col-auto pt-2">
128 <span class="badge bg-red d-block"></span>
129 </div>
130 <div class="col text-truncate">
131 <h3><a href="#" class="text-body d-block">#i18n{portal.util.log.warningLevel}</a></h3>
132 <#list listLogDebug as logInfo>
133 <#if logInfo?size gt 0><div class="d-block text-truncate mt-1" title="${logInfo.path!}"><strong>${logInfo.name!} - ${logInfo.level!}</strong> ${logInfo.path!}</div></#if>
134 </#list>
135 </div>
136 </div>
137 </div>
138 </div>
139 </div>
140 </div>
141 </li>
142 </#if>
143 </#if>
144 <li class="nav-item d-none d-lg-flex">
145 <a class="nav-link" href="jsp/admin/ManageProperties.jsp" title="#i18n{portal.site.adminFeature.properties_management.name}" >
146 <i class="ti ti-home-cog"></i>
147 <span class="visually-hidden">#i18n{portal.site.adminFeature.properties_management.name}</span>
148 </a>
149 </li>
150 <li class="nav-item d-flex d-lg-none">
151 <a class="nav-link" href="jsp/admin/ManageProperties.jsp" title="#i18n{portal.site.adminFeature.properties_management.name}" >
152 <i class="ti ti-home-cog me-2"></i> <span>#i18n{portal.site.adminFeature.properties_management.name}</span>
153 </a>
154 </li>
155 <li class="nav-item d-none d-lg-flex">
156 <a class="nav-link" href="jsp/admin/AdminTechnicalMenu.jsp" title="#i18n{portal.admindashboard.view_dashboards.title}">
157 <i class="ti ti-settings"></i>
158 <span class="visually-hidden">#i18n{portal.admindashboard.view_dashboards.title}</span>
159 </a>
160 </li>
161 <li class="nav-item d-flex d-lg-none">
162 <a class="nav-link" href="jsp/admin/AdminTechnicalMenu.jsp" title="#i18n{portal.admindashboard.view_dashboards.title}">
163 <i class="ti ti-settings me-2"></i> <span>#i18n{portal.admindashboard.view_dashboards.title}</span>
164 </a>
165 </li>
166 </#if>
167 <li class="nav-item dropdown d-none d-lg-flex">
168 <a href="#" class="nav-link nav-info nav-user-info lh-1 py-0 px-2 text-reset dropdown-toggle" data-bs-toggle="dropdown" role="button" >
169 <span class="visually-hidden">#i18n{portal.util.labelMore}</span>
170 <span class="avatar avatar-sm" style="background-image:url(<#if adminAvatar>servlet/plugins/adminavatar/avatar?id_user=${user.userId}<#else>#dskey{portal.site.site_property.avatar_default}</#if>)"></span>
171 <div class="ps-2 pt-3 user-infos">
172 <p class="mb-0 fs-5 user-login">${dashboard_zone_4!}</p>
173 <p class="mt-0 small user-date">${user.dateLastLogin!}</p>
174 </div>
175 </a>
176 <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow nav-info">
177 <#if userMenuItems?has_content>
178 <#list userMenuItems as item>
179 ${item.content}
180 </#list>
181 </#if>
182 <div class="dropdown-divider nav-info"></div>
183 <#if admin_logout_url?has_content>
184 <a class="dropdown-item dropdown-logout d-none d-lg-flex" href="${admin_logout_url}" title="#i18n{portal.users.admin_header.deconnectionLink}">
185 <i class="ti ti-logout me-1"></i>
186 <span>#i18n{portal.users.admin_header.deconnectionLink}</span>
187 </a>
188 </#if>
189 </div>
190 </li>
191 <li class="nav-item justify-content-start d-lg-none">
192 <a class="nav-link dropdown-toggle" id="mobile_usermenuitems" role="button" data-bs-toggle="dropdown" role="button" aria-expanded="false" href=""><i class="ti ti-user me-2"></i>${dashboard_zone_4!}</a>
193 <#if userMenuItems?has_content>
194 <ul class="dropdown-menu">
195 <li class="nav-item d-flex"><span class="dropdown-item"><i class="ti ti-calendar me-2"></i> #i18n{portal.users.admin_header.labelLastLogin} ${user.dateLastLogin!}</span></li>
196 <#list userMenuItems as item>
197 <li class="nav-item d-flex">${item.content}</li>
198 </#list>
199 </ul>
200 </#if>
201 </li>
202 <#if admin_logout_url?has_content>
203 <li class="nav-item d-flex d-lg-none">
204 <a class="nav-link" href="${admin_logout_url}" title="#i18n{portal.users.admin_header.deconnectionLink}">
205 <i class="ti ti-logout me-2"></i>
206 <span>#i18n{portal.users.admin_header.deconnectionLink}</span>
207 </a>
208 </li>
209 </#if>
210 </ul>
211 <button id="aside-header-collapse" class="btn btn-dark btn-sm mt-5" type="button" title="#i18n{portal.util.labelToggleSize}">
212 <span class="ti ti-switch-horizontal"></span>
213 <span class="visually-hidden">#i18n{portal.util.labelToggleSize}</span>
214 </button>
215 </div>
216 </div>
217 </nav>
218 <#if user.userLevel == 0>
219 <script>
220 document.addEventListener( 'DOMContentLoaded', () => {
221 const loggers = document.querySelector('.logger') ;
222 if( loggers != null && loggers.childElementCount > 0 && document.getElementById('adminModal') != null ){
223 if( !sessionStorage.getItem('lutece-debug-modal') ){
224 sessionStorage.setItem('lutece-debug-modal', false )
225 }
226 var modalContent = '<h3>#i18n{portal.util.log.warningLevel}</h3><p><strong>#i18n{portal.util.log.modalWarningMessage}</strong></p><p class="text-center"><button class="btn btn-sm btn-danger" data-toggle="collapse" data-target="#info-log" aria-expanded="false" aria-controls="info-log" type="button">#i18n{portal.util.log.modalLabelButton}</button></p><blockquote class="collapse" id="info-log">' + loggers.querySelector('.col.text-truncate').innerHTML + '</blockquote>';
227 var adminModal = document.getElementById('adminModal');
228 var adminModalLabel = document.getElementById('adminModalLabel');
229 var adminModalBody = document.querySelector('#adminModal .modal-body');
230 if( adminModalBody != null){
231 adminModalBody.insertAdjacentHTML( 'beforeEnd', modalContent);
232 }
233 var adminModalHeader = document.querySelector('#adminModal .modal-header');
234 var adminModalHeaderBtn = document.querySelector('#adminModal .modal-header button');
235 var myAdminModal = new bootstrap.Modal( adminModal, {} );
236 adminModalLabel.insertAdjacentHTML( 'beforeEnd', '#i18n{portal.util.log.modalWarningTitle}' );
237 adminModalHeader.classList.add('text-white');
238 adminModalHeaderBtn.setAttribute( 'style', 'background: transparent url("data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 16 16\' fill=\'%23ffffff\'%3e%3cpath d=\'M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z\'/%3e%3c/svg%3e") center/.75rem auto no-repeat;');
239 adminModalHeader.classList.add('bg-danger');
240 adminModalBody.classList.add('text-danger');
241 adminModal.addEventListener('hide.bs.modal', function () {
242 sessionStorage.setItem('lutece-debug-modal',true);
243 })
244 if( sessionStorage.getItem('lutece-debug-modal') === 'false' ){
245 myAdminModal.show();
246 }
247 }
248 });
249 </script>
250 </#if>
251 </header>
252 </#macro>