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>