adminFooter.ftl

 1   <#--
 2   Macro: adminFooter
 3   
 4   Description: Generates the footer section, including documentation and source code links, a Lutece logo, and a version number.
 5   
 6   Parameters:
 7   - version : The version number
 8   -->
 9   <#macro adminFooter closeMain=true >
 10   <footer id='main-lutece-footer' class="d-flex justify-content-end align-items-end border-top d-none">
 11   <@p class='me-5'>${site_name} - #i18n{portal.site.portal_footer.labelMadeBy} ${version}</@p>
 12   </footer>
 13   <!-- footer menu                                                     -->
 14   <!-- Included JS Files 												            -->
 15   <!-- Le javascript 													            -->
 16   <!-- =============================================================== -->
 17   <!-- Placed at the end of the document so the pages load faster 	   -->
 18   <@coreAdminJSLinks />
 19   ${javascript_files}
 20   </div><!-- Close wrapper -->
 21   </div>
 22   <#if dskey('portal.site.site_property.bo.showXs.checkbox') == '0' >
 23   <@pageContainer class="position-fixed top-0 w-100 d-block d-md-block d-lg-none">
 24       <@pageColumn id="lutece-login-block" class="border-end p-0" height="full">
 25   	   <@div class="d-flex align-items-center justify-content-evenly vh-100">
 26   			<@div class="container-tight">
 27   				<@div class="card shadow-lg rounded-4 p-4 mx-5 mw-30">
 28   					<@div class="card-body p-5 fs-6">
 29                     <@div class="text-center mb-4">
 30                        <@link href='/' target='_blank'>
 31                           <img src="${dskey('portal.site.site_property.logo_url')}" height="40" alt="Logo" aria-hidden="true" >
 32                           <span class="visually-hidden">${site_name!'Lutece'}</span>
 33                        </@link>
 34                     </@div>
 35                     <@div class='d-flex flex-column align-items-center'>
 36                        <h2 class="h1 mb-4 text-center">#i18n{portal.admin.admin_login.welcome} ${site_name!}</h2>
 37                        <i class="ti ti-device-mobile-off" style="font-size:120px !important"></i>
 38                     </@div>
 39                  </@div>
 40   			   </@div>
 41   			</@div>
 42   		</@div>
 43   	</@pageColumn>
 44   </@pageContainer>
 45   </#if>
 46   <#if dskey('portal.site.site_property.bo.showXsWarning.checkbox')?number == 1 >
 47   <@initToast position='top-0 start-50 translate-middle-x' showAll=true >
 48      <@addToast title='' content='#i18n{portal.site.message.showXsWarningMsg}' class='text-bg-warning d-block d-sm-block d-md-block d-lg-none' />
 49   </@initToast>
 50   </#if>
 51   </#macro>
 52   <#--
 53   Macro: adminSiteFooter
 54   
 55   Description: Footer for site Admin
 56   Parameters:
 57   - 
 58   -->
 59   <#macro adminSiteFooter >
 60   <#assign siteFooter = .get_optional_template('../../../../../skin/site/portal_footer.html')>
 61   <#if siteFooter.exists><@siteFooter.include /></#if>
 62   <!-- A modal dialog containing a form -->
 63   <dialog id="addPortletDialog" class="lutece-dialog" aria-labelledby="portletModalLabel" aria-hidden="true" tabindex="-1">
 64       <div class="lutece-dialog lutece-dialog-fullscreen">
 65           <div class="lutece-dialog-content">
 66               <div class="lutece-dialog-header">
 67                   <h2 class="lutece-dialog-title h4 text-dark" id="portletModalLabel">#i18n{portal.site.portletType.labelCreate}</h2>
 68                   <button type="button" class="btn btn-link btn-close text-dark" aria-label="#i18n{portal.util.labelCancel}"><i class="ti ti-x"></i></button>
 69               </div>
 70               <div class="lutece-dialog-body">
 71                       <form action="jsp/admin/DoCreatePortlet.jsp" type="get">
 72                       <div class="container">
 73                           <div id='portlet_type_id' class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4"></div>
 74                       </div>
 75                       <div class="d-flex justify-content-center">
 76                           <button type="button" class="btn btn-secondary btn-close" value="cancel" >#i18n{portal.util.labelCancel}</button>
 77                       </div>
 78                       </form>
 79                   </div>
 80               <div>
 81           </div>
 82       </div>
 83   </div>
 84   </dialog>
 85   <script type="module">
 86   document.addEventListener( "DOMContentLoaded", function(){
 87       const parentPortletTypeNodes = window.parent.document.querySelectorAll( '#offcanvas-body-portlet-type-wrapper ul li' );
 88       const dialogPortletTypes = document.getElementById( 'portlet_type_id' );
 89       const portletDialog = document.querySelector( '#addPortletDialog' );
 90   
 91       parentPortletTypeNodes.forEach( ( item ) => {
 92           const divType = document.createElement('div')
 93           divType.classList.add('col')
 94           const aType = document.createElement('a')
 95           aType.classList.add('btn', 'btn-outline-primary', 'btn-lg','btn-block', 'btn-new-portlet', 'py-5', 'px-0' , 'my-3', 'd-flex', 'align-items-center' )
 96           aType.setAttribute( 'href', item.dataset.portletTypeHref )
 97           const spanType = document.createElement('span')
 98           spanType.classList.add( 'px-2', 'text-left' )
 99           spanType.innerText = item.dataset.portletTypeName
 100           const iconType = document.createElement('i')
 101           iconType.classList.add('ti', <#noparse>`ti-${item.dataset.portletTypeIcon}`</#noparse> ,'fs-0','d-block','me-4','mr-4','ps-2','pl-2')
 102           aType.appendChild( iconType );
 103           aType.appendChild( spanType );
 104           divType.appendChild( aType );
 105           dialogPortletTypes.appendChild( divType );
 106       })
 107   
 108       // 
 109       const columnList = document.querySelectorAll( '.lutece-admin-column' );
 110       columnList.forEach( ( col ) => {
 111           const colOutList = col.querySelectorAll( '.lutece-admin-column-outline' );
 112           colOutList.forEach( ( colOut ) => { 
 113               if( colOut.textContent.trim() === '' ){
 114                   colOut.textContent= '';
 115               }
 116           })
 117       })
 118   
 119       // "Show the dialog" button opens the <dialog> modally
 120       const btnPortletList = document.querySelectorAll( '[data-bs-toggle="modal"]' );
 121       btnPortletList.forEach( ( btnPortlet ) => {
 122           btnPortlet.addEventListener( 'click', ( event ) => {
 123               const portlet = event.currentTarget
 124               const portletColumn = portlet.dataset.portletColumn
 125               let portletOrder = portlet.dataset.portletOrder
 126               if( portletOrder === '' ){
 127                   const lastPortlet = document.querySelector(<#noparse>`#lutece-column-${portletColumn} .lutece-admin-column-outline .lutece-admin-portlet:last-child .lutece-admin-toolbar</#noparse>`)
 128                   if( lastPortlet != null ){
 129                       portletOrder = parseInt( document.querySelector(<#noparse>`#lutece-column-${portletColumn} .lutece-admin-column-outline .lutece-admin-portlet:last-child .lutece-admin-toolbar</#noparse>`).dataset.portletOrder ) + 1
 130                   } else {
 131                       portletOrder = 1
 132                   }
 133               }
 134               dialogPortletTypes.childNodes.forEach( ( item ) => {
 135                   let itemLnk = item.firstElementChild;
 136                   let itemHref = itemLnk.getAttribute('href');
 137                   <#noparse>itemLnk.setAttribute('href',`${itemHref}&portlet_column=${portletColumn}&portlet_order=${portletOrder}`)</#noparse>
 138               })  
 139               portletDialog.showModal()
 140           })
 141       })
 142   
 143       const btnCloseDialogList = document.querySelectorAll( '.btn-close' );
 144       btnCloseDialogList.forEach( ( btnCloseDialog ) => {
 145           btnCloseDialog.addEventListener( 'click', ( event ) => {
 146               portletDialog.close()
 147           })
 148       })
 149   
 150   }); 
 151   
 152   import {
 153       LuteceDraggable
 154   } from './themes/shared/modules/luteceDraggable.js';
 155   
 156   const root = document.querySelector(":root");
 157   root.style.setProperty("--column-empty-text", `"#i18n{portal.site.portletType.labelCreateColumn}"`);
 158   
 159   const containers = document.querySelectorAll('#main .lutece-admin-column-outline');
 160   const draggables = Array.from(containers).flatMap(container => [...container.children]);
 161   const AdminHomeDraggable = new LuteceDraggable( draggables, containers);
 162   
 163   async function updatePortlet( portletId, col, order ){
 164   <#noparse>const response = await fetch( `jsp/admin/site/DoModifyPortletPosition.jsp?portlet_id=${portletId}&column=${col}&order=${order}` );</#noparse>
 165   }
 166    
 167   AdminHomeDraggable.on('dragstart', (event) => {
 168      root.style.setProperty( "--column-empty-text", `"Drop moi ici !"` );
 169   });
 170    
 171   AdminHomeDraggable.on('dragover', (event) => {
 172       //event.currentTarget.style.setProperty( "opacity", ".5" );
 173   });
 174    
 175   AdminHomeDraggable.on( 'dragend', (event) => {
 176       root.style.setProperty("--column-empty-text", `"#i18n{portal.site.portletType.labelCreateColumn}"`);
 177       const dragContainer = event.target.closest( '.lutece-draggable-container' );
 178       const newCol = dragContainer.dataset.portletColumn;
 179       const portletId = event.currentTarget.firstElementChild.dataset.portletId
 180       let newOrder= 1
 181   	if ( event.currentTarget.nextSibling != null ){
 182   		newOrder = parseInt( event.currentTarget.nextSibling.firstElementChild.dataset.portletOrder )
 183   		if( newOrder > 1 ){ newOrder-- }
 184   	} else if ( event.currentTarget.previousSibling != null ){
 185   		newOrder = parseInt( event.currentTarget.previousSibling.previousSibling.firstElementChild.dataset.portletOrder )
 186   		newOrder++
 187       }
 188   
 189   	event.currentTarget.firstElementChild.firstElementChild.textContent = newOrder
 190   	event.currentTarget.firstElementChild.firstElementChild.dataset.portletOrder = newOrder
 191   	event.currentTarget.firstElementChild.firstElementChild.dataset.portletColumn = newCol
 192   
 193       if( dragContainer.textContent.trim() === '' ){ dragContainer.textContent = '' }
 194   
 195   	updatePortlet( portletId, newCol, newOrder )
 196   }); 
 197   </script> 
 198   </#macro>