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-cancel 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-cancel" value="cancel" >
 77                           <svg  xmlns="http://www.w3.org/2000/svg"  width="24"  height="24"  viewBox="0 0 24 24"  fill="none"  stroke="currentColor"  stroke-width="2"  stroke-linecap="round"  stroke-linejoin="round"  class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg> #i18n{portal.util.labelClose}</button>
 78                       </div>
 79                       </form>
 80                   </div>
 81               <div>
 82           </div>
 83       </div>
 84   </div>
 85   </dialog>
 86   <script type="module">
 87   document.addEventListener( "DOMContentLoaded", function(){
 88       const parentPortletTypeNodes = window.parent.document.querySelectorAll( '#offcanvas-body-portlet-type-wrapper ul li' );
 89       const dialogPortletTypes = document.getElementById( 'portlet_type_id' );
 90       const portletDialog = document.querySelector( '#addPortletDialog' );
 91   
 92       parentPortletTypeNodes.forEach( ( item ) => {
 93           const divType = document.createElement('div')
 94           divType.classList.add('col')
 95           const aType = document.createElement('a')
 96           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' )
 97           aType.setAttribute( 'href', item.dataset.portletTypeHref )
 98           const spanType = document.createElement('span')
 99           spanType.classList.add( 'px-2', 'text-left', 'truncate' )
 100           spanType.innerText = item.dataset.portletTypeName
 101           const iconType = document.createElement('i')
 102           iconType.classList.add('ti', <#noparse>`ti-${item.dataset.portletTypeIcon}`</#noparse> ,'fs-0','d-block','me-4','mr-4','ps-2','pl-2')
 103           aType.appendChild( iconType );
 104           aType.appendChild( spanType );
 105           divType.appendChild( aType );
 106           dialogPortletTypes.appendChild( divType );
 107       })
 108   
 109       // 
 110       const columnList = document.querySelectorAll( '.lutece-admin-column' );
 111       columnList.forEach( ( col ) => {
 112           const colOutList = col.querySelectorAll( '.lutece-admin-column-outline' );
 113           colOutList.forEach( ( colOut ) => { 
 114               if( colOut.textContent.trim() === '' ){
 115                   colOut.textContent= '';
 116               }
 117           })
 118       })
 119   
 120       // "Show the dialog" button opens the <dialog> modally
 121       const btnPortletList = document.querySelectorAll( '[data-bs-toggle="modal"]' );
 122       btnPortletList.forEach( ( btnPortlet ) => {
 123           btnPortlet.addEventListener( 'click', ( event ) => {
 124               const portlet = event.currentTarget
 125               const portletColumn = portlet.dataset.portletColumn
 126               let portletOrder = portlet.dataset.portletOrder
 127               if( portletOrder === '' ){
 128                   const lastPortlet = document.querySelector(<#noparse>`#lutece-column-${portletColumn} .lutece-admin-column-outline .lutece-admin-portlet:last-child .lutece-admin-toolbar</#noparse>`)
 129                   if( lastPortlet != null ){
 130                       portletOrder = parseInt( document.querySelector(<#noparse>`#lutece-column-${portletColumn} .lutece-admin-column-outline .lutece-admin-portlet:last-child .lutece-admin-toolbar</#noparse>`).dataset.portletOrder ) + 1
 131                   } else {
 132                       portletOrder = 1
 133                   }
 134               }
 135               dialogPortletTypes.childNodes.forEach( ( item ) => {
 136                   let itemLnk = item.firstElementChild;
 137                   let itemHref = itemLnk.getAttribute('href');
 138                   <#noparse>itemLnk.setAttribute('href',`${itemHref}&portlet_column=${portletColumn}&portlet_order=${portletOrder}`)</#noparse>
 139               })  
 140               portletDialog.showModal()
 141           })
 142       })
 143   
 144       const btnCloseDialogList = document.querySelectorAll( '.btn-close' );
 145       btnCloseDialogList.forEach( ( btnCloseDialog ) => {
 146           btnCloseDialog.addEventListener( 'click', ( event ) => {
 147               portletDialog.close()
 148           })
 149       })
 150   
 151   }); 
 152   
 153   import {
 154       LuteceDraggable
 155   } from './themes/shared/modules/luteceDraggable.js';
 156   
 157   const root = document.querySelector(":root");
 158   root.style.setProperty("--column-empty-text", `"#i18n{portal.site.portletType.labelCreateColumn}"`);
 159   
 160   const containers = document.querySelectorAll('#main .lutece-admin-column-outline');
 161   const draggables = Array.from(containers).flatMap(container => [...container.children]);
 162   const AdminHomeDraggable = new LuteceDraggable( draggables, containers);
 163   
 164   async function updatePortlet( portletId, col, order ){
 165   <#noparse>const response = await fetch( `jsp/admin/site/DoModifyPortletPosition.jsp?portlet_id=${portletId}&column=${col}&order=${order}` );</#noparse>
 166   }
 167    
 168   AdminHomeDraggable.on('dragstart', (event) => {
 169      root.style.setProperty( "--column-empty-text", `"Drop moi ici !"` );
 170   });
 171    
 172   AdminHomeDraggable.on('dragover', (event) => {
 173       //event.currentTarget.style.setProperty( "opacity", ".5" );
 174   });
 175    
 176   AdminHomeDraggable.on( 'dragend', (event) => {
 177       root.style.setProperty("--column-empty-text", `"#i18n{portal.site.portletType.labelCreateColumn}"`);
 178       const dragContainer = event.target.closest( '.lutece-draggable-container' );
 179       const newCol = dragContainer.dataset.portletColumn;
 180       const portletId = event.currentTarget.firstElementChild.dataset.portletId
 181       let newOrder= 1
 182   	if ( event.currentTarget.nextSibling != null ){
 183   		newOrder = parseInt( event.currentTarget.nextSibling.firstElementChild.dataset.portletOrder )
 184   		if( newOrder > 1 ){ newOrder-- }
 185   	} else if ( event.currentTarget.previousSibling != null ){
 186   		newOrder = parseInt( event.currentTarget.previousSibling.previousSibling.firstElementChild.dataset.portletOrder )
 187   		newOrder++
 188       }
 189   
 190   	event.currentTarget.firstElementChild.firstElementChild.textContent = newOrder
 191   	event.currentTarget.firstElementChild.firstElementChild.dataset.portletOrder = newOrder
 192   	event.currentTarget.firstElementChild.firstElementChild.dataset.portletColumn = newCol
 193   
 194       if( dragContainer.textContent.trim() === '' ){ dragContainer.textContent = '' }
 195   
 196   	updatePortlet( portletId, newCol, newOrder )
 197   }); 
 198   </script> 
 199   </#macro>