Änderungen von Dokument Home
Zuletzt geändert von Steffen Rehfuß am 14.08.2026 18:48
Von Version 2.1
bearbeitet von Steffen Rehfuß
am 14.08.2026 18:47
am 14.08.2026 18:47
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Auf Version 5.1
bearbeitet von Steffen Rehfuß
am 14.08.2026 18:48
am 14.08.2026 18:48
Änderungskommentar:
Es gibt keinen Kommentar für diese Version
Zusammenfassung
-
Seiteneigenschaften (1 geändert, 0 hinzugefügt, 0 gelöscht)
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -4,14 +4,15 @@ 4 4 ## Einfach in den Seiten-Editor (Quelltext/Wiki) einfuegen. 5 5 ## ===================================================================== 6 6 ## 7 -## ---- KONFIG 1: Blog-Space + Hero-Kategorie ---- 7 +## ---- KONFIG 1: Blog-Space + Hero-Kategorie + Laufschrift-Kategorie ---- 8 8 #set ($blogSpace = 'Blog') ## technischer Space-Name des Blogs 9 9 #set ($heroCategory = 'TOP') ## Kategorie, die gross dargestellt wird 10 +#set ($breakingCategory = 'Breaking News') ## Kategorie fuer die Laufschrift oben 10 10 ## 11 11 ## ---- KONFIG 2: Die 12 App-Buttons (Text / Icon / Link / Farbe) ---- 12 12 ## icon = Font-Awesome-Name (ohne "fa-"). Farbe = beliebiger Hex-Wert. 13 13 #set ($apps = [ 14 - {'label':' Abteilung I', 'icon':'search', 'ref':'abteilung01:Main.WebHome', 'color':'#16a085'},15 + {'label':'Haupt-Wiki', 'icon':'search', 'ref':'xwiki:Main.WebHome', 'color':'#16a085'}, 15 15 {'label':'MyPage', 'icon':'key', 'ref':'MyPage.WebHome', 'color':'#2980b9'}, 16 16 {'label':'Blog', 'icon':'star', 'ref':'Blog.WebHome', 'color':'#8e44ad'}, 17 17 {'label':'Chatbot', 'icon':'pencil-square-o', 'url':"javascript:document.getElementById('toggle-chat-button').click();void(0);", 'color':'#16a085'}, ... ... @@ -37,14 +37,17 @@ 37 37 #end 38 38 #set ($postNames = $q.execute()) 39 39 ## 40 -## ---- Hero (erster TOP-Post) + bis zu 4 Kachel-Posts bestimmen ---- 41 +## ---- Hero (erster TOP-Post) + bis zu 4 Kachel-Posts + neuester Breaking-News-Post bestimmen ---- 41 41 #set ($heroDoc = $NULL) 42 42 #set ($heroObj = $NULL) 43 43 #set ($tilePosts = []) 45 +#set ($breakingDoc = $NULL) 46 +#set ($breakingObj = $NULL) 44 44 #foreach ($pn in $postNames) 45 45 #set ($pd = $xwiki.getDocument($pn)) 46 46 #set ($po = $pd.getObject('Blog.BlogPostClass')) 47 47 #set ($isTop = false) 51 + #set ($isBreaking = false) 48 48 #set ($cats = $po.getValue('category')) 49 49 #if ($cats) 50 50 #foreach ($c in $cats) ... ... @@ -53,8 +53,15 @@ 53 53 #if ($cn == $heroCategory) 54 54 #set ($isTop = true) 55 55 #end 60 + #if ($cn == $breakingCategory) 61 + #set ($isBreaking = true) 62 + #end 56 56 #end 57 57 #end 65 + #if ($isBreaking && !$breakingDoc) 66 + #set ($breakingDoc = $pd) 67 + #set ($breakingObj = $po) 68 + #end 58 58 #if ($isTop && !$heroDoc) 59 59 #set ($heroDoc = $pd) 60 60 #set ($heroObj = $po) ... ... @@ -87,6 +87,14 @@ 87 87 #set ($heroDate = $heroObj.getValue('publishDate')) 88 88 #end 89 89 ## 101 +## ---- Laufschrift-Daten aufbereiten ---- 102 +#if ($breakingDoc) 103 + #set ($breakingTitle = $breakingDoc.getPlainTitle()) 104 + #set ($breakingText = "$!breakingObj.getValue('extract')") 105 + #set ($breakingURL = $breakingDoc.getURL('view')) 106 + #set ($breakingDate = $breakingObj.getValue('publishDate')) 107 +#end 108 +## 90 90 {{html clean="false" wiki="false"}} 91 91 <style> 92 92 ## Seitenkopf (Titel + "Zuletzt geaendert" + Aktionsmenue) auf DIESER Seite ausblenden ... ... @@ -102,6 +102,34 @@ 102 102 ## Fusszeile: Tags + "Gefaellt mir" + "Erstellt von / uebersetzt von" ausblenden 103 103 #xdocTags, .doc-tags, .like-container, .xdocCreation { display: none !important; } 104 104 .intra-wrap { width: 90%; max-width: 90%; margin: 0 auto; } 124 +.intra-ticker { 125 + display: flex; align-items: stretch; height: 38px; 126 + background: #c0392b; margin-bottom: 20px; overflow: hidden; border-radius: 8px; 127 +} 128 +.intra-ticker-label { 129 + flex: 0 0 auto; display: flex; align-items: center; 130 + background: #922b21; color: #fff !important; text-decoration: none; 131 + font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; 132 + padding: 0 18px; white-space: nowrap; 133 +} 134 +.intra-ticker-viewport { flex: 1 1 auto; position: relative; overflow: hidden; } 135 +.intra-ticker-date { 136 + flex: 0 0 auto; display: flex; align-items: center; 137 + color: #ffd7d0 !important; font-size: 13px; font-weight: 700; 138 + padding: 0 6px 0 18px; white-space: nowrap; 139 +} 140 +.intra-ticker-track { 141 + position: absolute; top: 0; left: 100%; height: 100%; 142 + display: flex; align-items: center; white-space: nowrap; 143 + color: #fff !important; text-decoration: none; font-size: 14px; font-weight: 600; 144 + padding: 0 18px; 145 + animation: intra-ticker-scroll 22s linear infinite; 146 +} 147 +.intra-ticker-track:hover { animation-play-state: paused; text-decoration: underline; } 148 +@keyframes intra-ticker-scroll { 149 + from { left: 100%; } 150 + to { left: -100%; } 151 +} 105 105 .intra-cols { display: flex; gap: 20px; align-items: stretch; } 106 106 .intra-main { flex: 2 1 0; min-width: 0; } 107 107 .intra-side { flex: 1 1 0; display: flex; flex-direction: column; gap: 16px; } ... ... @@ -109,7 +109,13 @@ 109 109 position: relative; width: 100%; min-height: 360px; border-radius: 14px; 110 110 overflow: hidden; background: #223; background-size: cover; background-position: center; 111 111 box-shadow: 0 6px 18px rgba(0,0,0,.15); text-decoration: none; display: block; 159 + transition: transform .15s ease, box-shadow .15s ease; 112 112 } 161 +.intra-hero:hover { 162 + transform: translateY(-3px); 163 + box-shadow: 0 12px 28px rgba(0,0,0,.22); 164 +} 165 +.intra-hero:hover .intra-btn { filter: brightness(1.08); } 113 113 .intra-hero::after { 114 114 content: ""; position: absolute; inset: 0; 115 115 background: linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(0,0,0,.75) 100%); ... ... @@ -127,32 +127,12 @@ 127 127 } 128 128 .intra-btn:hover { filter: brightness(1.08); } 129 129 .intra-apps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; } 130 - 131 131 .intra-app { 132 - display: flex; 133 - flex-direction: column; 134 - justify-content: space-between; 135 - border-radius: 10px; 136 - padding: 12px 12px 10px; 137 - min-height: 84px; 138 - color: #fff !important; 139 - text-decoration: none; 140 - transition: transform .15s ease, 141 - box-shadow .15s ease, 142 - filter .15s ease; 184 + display: flex; flex-direction: column; justify-content: space-between; 185 + border-radius: 10px; padding: 12px 12px 10px; min-height: 84px; color: #fff !important; 186 + text-decoration: none; transition: transform .15s ease, box-shadow .15s ease; 143 143 } 144 - 145 -.intra-app:hover { 146 - transform: translateY(-2px); 147 - filter: brightness(.90); /* ca. 8 % dunkler */ 148 - box-shadow: 0 6px 14px rgba(0,0,0,.18); 149 -} 150 - 151 -.intra-app:active { 152 - filter: brightness(.86); 153 -} 154 - 155 - 188 +.intra-app:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0,0,0,.18); } 156 156 .intra-app-ic { font-size: 22px; line-height: 1; } 157 157 .intra-app-ic .fa { color: #fff; } 158 158 .intra-app-lbl { font-size: 13px; font-weight: 600; margin-top: 8px; } ... ... @@ -164,6 +164,8 @@ 164 164 } 165 165 .intra-widget { background: #fff; border: 0.5px solid #e2e6ea; border-radius: 12px; padding: 16px 18px; box-shadow: 0 3px 12px rgba(0,0,0,.06); margin-top: 35px; } 166 166 .intra-widget-h { font-size: 14px; font-weight: 700; color: #16324f; margin-bottom: 10px; } 200 +.intra-cal-link { color: #16324f; text-decoration: none; transition: color .15s ease; } 201 +.intra-cal-link:hover { color: #2c6fbb; } 167 167 .intra-tagcloud { line-height: 2; } 168 168 .intra-tag { display: inline-block; margin: 0 9px 4px 0; color: #2c6fbb; text-decoration: none; } 169 169 .intra-tag:hover { text-decoration: underline; } ... ... @@ -173,6 +173,7 @@ 173 173 .intra-cal-item:hover .intra-cal-title { text-decoration: underline; } 174 174 .intra-cal-date { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: #2c6fbb; min-width: 52px; letter-spacing: .02em; } 175 175 .intra-cal-title { font-size: 13px; color: #16324f; } 211 +.intra-cal-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; align-self: center; box-shadow: 0 0 0 1px rgba(0,0,0,.06) inset; } 176 176 .intra-cal-empty { color: #8a97a6; font-size: 13px; } 177 177 .intra-tile { 178 178 display: flex; background: #fff; border-radius: 12px; overflow: hidden; ... ... @@ -199,7 +199,7 @@ 199 199 position: relative; 200 200 transform-style: preserve-3d; 201 201 transition: transform .6s cubic-bezier(.2,.7,.2,1); 202 - transition-delay: 0s;/*RichtungserkennungimJS verhindertFehl-Flips*/238 + transition-delay: .12s; /* kein Flip beim blossen Vorbeiziehen */ 203 203 } 204 204 .intra-flip.is-back .intra-flip-inner { transform: rotateY(180deg); } 205 205 ... ... @@ -226,6 +226,18 @@ 226 226 </style> 227 227 228 228 <div class="intra-wrap"> 265 + 266 + ## ----- LAUFSCHRIFT: neuester Post mit Kategorie "Breaking News" ----- 267 + #if ($breakingDoc) 268 + <div class="intra-ticker"> 269 + <a class="intra-ticker-label" href="$breakingURL">$escapetool.xml($breakingCategory)</a> 270 + #if ($breakingDate)<span class="intra-ticker-date">$datetool.format('dd.MM.yyyy', $breakingDate)</span>#end 271 + <div class="intra-ticker-viewport"> 272 + <a class="intra-ticker-track" href="$breakingURL">$escapetool.xml($breakingTitle)#if($breakingText != '') — $escapetool.xml($breakingText)#end</a> 273 + </div> 274 + </div> 275 + #end 276 + 229 229 <div class="intra-cols"> 230 230 231 231 ## ===== LINKE SPALTE: Hero + 4 Blog-Kacheln ===== ... ... @@ -282,17 +282,20 @@ 282 282 <div class="intra-side"> 283 283 284 284 ## ----- 12 APP-BUTTONS ----- 285 - #foreach ($app in $apps) 286 - #set ($appHref = '') 287 - #if ($app.url && $app.url != '') 288 - #set ($appHref = $app.url) 289 - #elseif ($app.ref && $app.ref != '') 290 - #set ($appHref = $xwiki.getURL($app.ref, 'view')) ## <- hier greift die Aufloesung 291 - #end 292 - <a class="intra-app" style="background: $app.color;" href="#if($appHref != '')$appHref#else#end"> 293 - ... 294 - </a> 295 - #end 333 + <div class="intra-apps"> 334 + #foreach ($app in $apps) 335 + #set ($href = '') 336 + #if ("$!app.ref" != '') 337 + #set ($href = $xwiki.getURL($app.ref)) 338 + #elseif ("$!app.url" != '') 339 + #set ($href = $app.url) 340 + #end 341 + <a class="intra-app" style="background: $app.color;"#if($href != '') href="$href"#end> 342 + <span class="intra-app-ic"><span class="fa fa-$app.icon" aria-hidden="true"></span></span> 343 + <span class="intra-app-lbl">$escapetool.xml($app.label)</span> 344 + </a> 345 +#end 346 + </div> 296 296 297 297 ## ----- NAECHSTE TERMINE (Mocca Calendar) / RUECKSEITE: TAGCLOUD ----- 298 298 <div class="intra-flip-outer"> ... ... @@ -301,10 +301,19 @@ 301 301 302 302 <!-- VORDERSEITE: Naechste Termine --> 303 303 <div class="intra-flip-face intra-flip-front"> 304 - <span class="intra-flip-hint">⋮ Maus von unten</span> 305 - <div class="intra-widget-h">Nächste Termine</div> 355 + <div class="intra-widget-h"><a class="intra-cal-link" href="$xwiki.getURL('MoccaCalendar.WebHome', 'view')">Nächste Termine</a></div> 306 306 <div class="intra-cal-list"> 307 307 #set ($now = $datetool.date) 358 + ## ---- Kalenderfarben einmalig laden: Event-Elternseite (= Kalender) -> Farbe/Titel ---- 359 + #set ($calXwql = "select doc.fullName, calendar.color, calendar.title from Document doc, doc.object(MoccaCalendar.MoccaCalendarClass) calendar") 360 + #set ($calResults = $services.query.xwql($calXwql).execute()) 361 + #set ($calColorMap = {}) 362 + #set ($calTitleMap = {}) 363 + #foreach ($cr in $calResults) 364 + #set ($discard = $calColorMap.put("$cr.get(0)", "$!cr.get(1)")) 365 + #set ($discard = $calTitleMap.put("$cr.get(0)", "$!cr.get(2)")) 366 + #end 367 + #set ($defaultCalColor = '#8a97a6') 308 308 #set ($evtXwql = "from doc.object(MoccaCalendar.MoccaCalendarEventClass) as event where event.startDate >= :now and doc.hidden = false order by event.startDate asc") 309 309 #set ($evtNames = $services.query.xwql($evtXwql).bindValue('now', $now).setLimit(6).execute()) 310 310 #if ($evtNames && $evtNames.size() > 0) ... ... @@ -315,7 +315,18 @@ 315 315 #set ($eAllDay = $eo.getValue('allDay')) 316 316 #set ($eTitle = $ed.getPlainTitle()) 317 317 #if ($eTitle == '')#set ($eTitle = "$!eo.getValue('title')")#end 378 + ## Kalender der Elternseite ermitteln (Events liegen als Kind-Seite unter ihrem Kalender) 379 + #set ($eParent = "$!ed.getParent()") 380 + #set ($eColor = $calColorMap.get($eParent)) 381 + #if (!$eColor || $eColor == '') 382 + #set ($eColor = $defaultCalColor) 383 + #end 384 + #set ($eCalName = $calTitleMap.get($eParent)) 385 + #if (!$eCalName || $eCalName == '') 386 + #set ($eCalName = $xwiki.getDocument($eParent).getPlainTitle()) 387 + #end 318 318 <a class="intra-cal-item" href="$ed.getURL('view')"> 389 + <span class="intra-cal-dot" style="background: $escapetool.xml($eColor);" title="$escapetool.xml($eCalName)"></span> 319 319 <span class="intra-cal-date">#if($eStart)$datetool.format('dd.MM.', $eStart)#if("$!eAllDay" != '1') $datetool.format('HH:mm', $eStart)#end#end</span> 320 320 <span class="intra-cal-title">$escapetool.xml($eTitle)</span> 321 321 </a> ... ... @@ -376,21 +376,18 @@ 376 376 var box = document.getElementById('intra-flip-side'); 377 377 if(!box){ return; } 378 378 var hoverCapable = !!(window.matchMedia && window.matchMedia('(hover: hover)').matches); 379 - 380 - // Letzte bekannte Maus-Y-Position global mitverfolgen, um beim Betreten der Karte 381 - // die Bewegungsrichtung zu kennen (Y waechst nach unten -> "von unten" = Y wird kleiner). 450 + ## Letzte bekannte Maus-Y-Position global mitverfolgen, um beim Betreten der Karte 451 + ## die Bewegungsrichtung zu kennen (Y waechst nach unten -> "von unten" = Y wird kleiner). 382 382 var lastY = null; 383 383 document.addEventListener('mousemove', function(e){ lastY = e.clientY; }, {passive:true}); 384 - 385 385 box.addEventListener('mouseenter', function(e){ 386 386 if (!hoverCapable) { return; } 387 - var enteredFromBelow = (lastY !== null && (lastY -e.clientY)>2);456 + var enteredFromBelow = (lastY !== null && e.clientY < lastY); 388 388 if (enteredFromBelow) { 389 389 box.classList.toggle('is-back'); 390 390 } 391 391 lastY = e.clientY; 392 392 }); 393 - 394 394 box.addEventListener('click', function(e){ 395 395 if(e.target.closest('a')){ return; } 396 396 if(hoverCapable){ return; }