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