This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch spring6
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/spring6 by this push:
     new d263047a0e CAUSEWAY-3407: populate nav bar
d263047a0e is described below

commit d263047a0ee1d72e591049e3b224d925ccf99923
Author: Andi Huber <[email protected]>
AuthorDate: Fri Apr 7 17:20:40 2023 +0200

    CAUSEWAY-3407: populate nav bar
---
 .../org/apache/causeway/commons/io/YamlUtils.java  |  11 +-
 .../thymeflux/test/ThymefluxViewerTests.java       |  24 +---
 .../resources/templates/nav/topNavSection.html     |  58 ++++++++++
 .../templates/prototyping/image-solid.svg          |   1 +
 .../viewer/src/main/resources/templates/root.html  | 124 +++++++++++++--------
 .../applib/services/header/HeaderUiModel.java      |   5 -
 6 files changed, 148 insertions(+), 75 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java 
b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
index f29621ec1e..ef7ebe4db2 100644
--- a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
+++ b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
@@ -184,12 +184,11 @@ public class YamlUtils {
         private Map<String, Property> postProcessMap(final Map<String, 
Property> map) {
             //debug
             //System.err.printf("%s map: %s%n", type.getName(), map);
-            map.replaceAll((k, v)->{
-                if(Can.class.isAssignableFrom(v.getType())) {
-                    return MethodPropertyFromCanToList.wrap((MethodProperty)v);
-                }
-                return v;
-            });
+            map.replaceAll((k, v)->
+                Can.class.isAssignableFrom(v.getType())
+                    && v instanceof MethodProperty // no field support yet
+                    ? MethodPropertyFromCanToList.wrap((MethodProperty)v)
+                    : v);
             return map;
         }
 
diff --git 
a/incubator/viewers/thymeflux/test/src/test/java/org/apache/causeway/viewer/thymeflux/test/ThymefluxViewerTests.java
 
b/incubator/viewers/thymeflux/test/src/test/java/org/apache/causeway/viewer/thymeflux/test/ThymefluxViewerTests.java
index 7d4e42f466..4faf069719 100644
--- 
a/incubator/viewers/thymeflux/test/src/test/java/org/apache/causeway/viewer/thymeflux/test/ThymefluxViewerTests.java
+++ 
b/incubator/viewers/thymeflux/test/src/test/java/org/apache/causeway/viewer/thymeflux/test/ThymefluxViewerTests.java
@@ -30,8 +30,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import org.apache.causeway.applib.annotation.DomainServiceLayout.MenuBar;
+import org.apache.causeway.commons.io.YamlUtils;
 import org.apache.causeway.viewer.commons.applib.services.header.HeaderUiModel;
-import 
org.apache.causeway.viewer.commons.applib.services.menu.model.NavbarSection;
 import org.apache.causeway.viewer.thymeflux.model.root.ThymefluxRootController;
 import 
org.apache.causeway.viewer.thymeflux.viewer.CausewayModuleIncViewerThymefluxViewer;
 
@@ -62,25 +62,13 @@ class ThymefluxViewerTests {
         var headerUiModel = (HeaderUiModel)model.getAttribute("headerUiModel");
         assertNotNull(headerUiModel);
 
-        var primary   = (NavbarSection)headerUiModel.navbar().primary();
-        var secondary = (NavbarSection)headerUiModel.navbar().secondary();
-        var tertiary  = (NavbarSection)headerUiModel.navbar().tertiary();
+        var navbar = headerUiModel.navbar();
 
-        assertEquals(MenuBar.PRIMARY,   primary.menuBarSelect());
-        assertEquals(MenuBar.SECONDARY, secondary.menuBarSelect());
-        assertEquals(MenuBar.TERTIARY,  tertiary.menuBarSelect());
-
-        System.err.printf("%s%n", headerUiModel.toYaml());
-
-
-        primary.topLevelEntries().forEach(top->System.err.printf("prim: %s%n", 
top.name()));
-        secondary.topLevelEntries().forEach(top->System.err.printf("sec: 
%s%n", top.name()));
-        tertiary.topLevelEntries().forEach(top->System.err.printf("tert: 
%s%n", top.name()));
-
-        primary.topLevelEntries().forEach(top->System.err.printf("prim: %s%n", 
top));
-        secondary.topLevelEntries().forEach(top->System.err.printf("sec: 
%s%n", top));
-        tertiary.topLevelEntries().forEach(top->System.err.printf("tert: 
%s%n", top));
+        assertEquals(MenuBar.PRIMARY,   navbar.primary().menuBarSelect());
+        assertEquals(MenuBar.SECONDARY, navbar.secondary().menuBarSelect());
+        assertEquals(MenuBar.TERTIARY,  navbar.tertiary().menuBarSelect());
 
+        System.err.printf("== navbar: %n%s====%n", 
YamlUtils.toStringUtf8(navbar.primary()));
     }
 
 
diff --git 
a/incubator/viewers/thymeflux/viewer/src/main/resources/templates/nav/topNavSection.html
 
b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/nav/topNavSection.html
new file mode 100644
index 0000000000..5885b82b0d
--- /dev/null
+++ 
b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/nav/topNavSection.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--/* Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+  
+         http://www.apache.org/licenses/LICENSE-2.0
+         
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License. */-->
+<html lang="en" 
+       xmlns:th="http://www.thymeleaf.org";  
+       xmlns:hx="http://www.w3.org/1999/xhtml";>
+       
+<!-- NAMED MENU DROPDOWN -->
+
+<th:block th:fragment="topNavSection(topNavSection)">
+
+<li th:each="topLevelEntry : ${topNavSection.topLevelEntries()}"
+       class="nav-item dropdown">
+       <a class="nav-link dropdown-toggle"
+               href="#" role="button" 
data-bs-toggle="dropdown"><span>[[${topLevelEntry.name()}]]</span>
+       </a>
+       <ul class="dropdown-menu">
+
+               <!-- MENU ENTRIES -->
+               <th:block th:each="menuEntry : ${topLevelEntry.subEntries()}">
+
+                       <th:block th:if="${menuEntry.asSpacer().isPresent()}"
+                               th:with="menuSpacer = 
${menuEntry.asSpacer().get()}">
+
+                               <th:block th:if="${menuSpacer.isEmpty()}">
+                                       <li><hr class="dropdown-divider"></li>
+                               </th:block>
+
+                               <th:block th:unless="${menuSpacer.isEmpty()}">
+                                       <li class="list-section-label"><span 
class="sectionLabel">[[${menuSpacer.label()}]]</span>
+                                       </li>
+                               </th:block>
+
+                       </th:block>
+                       <li><a th:if="${menuEntry.asAction().isPresent()}"
+                               th:with="menuAction = 
${menuEntry.asAction().get()}"
+                               class="dropdown-item" href="#"> 
[[${menuAction.name()}]] </a></li>
+
+               </th:block>
+
+       </ul>
+</li>
+
+</th:block>
\ No newline at end of file
diff --git 
a/incubator/viewers/thymeflux/viewer/src/main/resources/templates/prototyping/image-solid.svg
 
b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/prototyping/image-solid.svg
new file mode 100644
index 0000000000..1b5822d5c0
--- /dev/null
+++ 
b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/prototyping/image-solid.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 0 512 512"><!--! Font 
Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - 
https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, 
Inc. --><path d="M0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 
35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM323.8 
202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 
297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2 [...]
\ No newline at end of file
diff --git 
a/incubator/viewers/thymeflux/viewer/src/main/resources/templates/root.html 
b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/root.html
index 64f09c612f..974a4d2ab1 100644
--- a/incubator/viewers/thymeflux/viewer/src/main/resources/templates/root.html
+++ b/incubator/viewers/thymeflux/viewer/src/main/resources/templates/root.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
-<!-- Licensed to the Apache Software Foundation (ASF) under one
+<!--/* Licensed to the Apache Software Foundation (ASF) under one
   or more contributor license agreements.  See the NOTICE file
   distributed with this work for additional information
   regarding copyright ownership.  The ASF licenses this file
@@ -14,55 +14,80 @@
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
-  under the License. -->
+  under the License. */-->
+<html lang="en" 
+       xmlns:th="http://www.thymeleaf.org";  
+       xmlns:hx="http://www.w3.org/1999/xhtml";>
+       
 <head>
     <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+       <!--/* PROTOTYPING --> 
+       <link 
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"; 
rel="stylesheet" 
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
 crossorigin="anonymous"/>
+    <link href="../static/css/causeway-thymeflux.css" rel="stylesheet" />
+       <script 
src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"; 
integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3"
 crossorigin="anonymous" defer></script>
+       <script 
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"; 
integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V"
 crossorigin="anonymous" defer></script>
+       <!--*/-->
+       
+       <!--/*/
+    <link rel="icon" type="image/x-icon" href="/images/favicon.ico">
     <link th:rel="stylesheet" 
th:href="@{/webjars/bootstrap/5.2.3/css/bootstrap.min.css}" />
-    <link data-th-href="@{/css/causeway-thymeflux.css}" rel="stylesheet">
+    <link th:rel="stylesheet" th:href="@{/css/causeway-thymeflux.css}">
+    <script th:src="@{/webjars/popper.js/2.9.3/umd/popper.min.js}" 
defer></script>
+    <script th:src="@{/webjars/bootstrap/5.2.3/js/bootstrap.bundle.min.js}" 
defer></script>
+    <script th:src="@{/webjars/htmx.org/1.8.6/dist/htmx.min.js}" 
defer></script>
+       /*/-->
+    
 </head>
+
+
 <body>
 
-<div class="container">
+<nav class="navbar navbar-expand-md sticky-top bg-light">
+  <div class="container-fluid">
+
+       <!-- BRANDING -->
+
+    <a th:with="branding = ${headerUiModel.branding()}"
+       class="navbar-brand"  
+       href="#">
+       <img class="navbar-brand-logo" alt="Brand"
+                        src="prototyping/image-solid.svg" height="48px"/>
+       [[${branding.name.orElse("")}]]
+    </a>
+    
+    <!-- NAVBAR COLLAPSE TOGGLER -->
+    
+    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" 
data-bs-target="#navbarSupportedContent">
+      <span class="navbar-toggler-icon"></span>
+    </button>
+    
+    <!-- NAVBAR -->
+    
+    <div class="collapse navbar-collapse mr-auto" id="navbarSupportedContent">
+    
+      <!--  PRIMARY SECTION -->
+         
+         <ul th:insert="nav/topNavSection :: 
topNavSection(${headerUiModel.navbar().primary()})" 
+             class="navbar-nav me-auto mb-2 mb-lg-0">
+         </ul>
+         
+         <!--  SECONDARY AND TERTIARY SECTION -->
+         
+         <ul th:insert="nav/topNavSection :: 
topNavSection(${headerUiModel.navbar().secondary()})" 
+             class="navbar-nav">
+         </ul>
+         <ul th:insert="nav/topNavSection :: 
topNavSection(${headerUiModel.navbar().tertiary()})" 
+             class="navbar-nav">
+         </ul>
+         
+       </div>
 
-       <nav class="navbar navbar-expand-lg bg-light">
-         <div class="container-fluid">
-           <a class="navbar-brand" href="#">Navbar</a>
-           <button class="navbar-toggler" type="button" 
data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" 
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle 
navigation">
-             <span class="navbar-toggler-icon"></span>
-           </button>
-           <div class="collapse navbar-collapse" id="navbarSupportedContent">
-             <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-               <li class="nav-item">
-                 <a class="nav-link active" aria-current="page" 
href="#">Home</a>
-               </li>
-               <li class="nav-item">
-                 <a class="nav-link" href="#">Link</a>
-               </li>
-               <li class="nav-item dropdown">
-                 <a class="nav-link dropdown-toggle" href="#" role="button" 
data-bs-toggle="dropdown" aria-expanded="false">
-                   Dropdown
-                 </a>
-                 <ul class="dropdown-menu">
-                   <li><a class="dropdown-item" href="#">Action</a></li>
-                   <li><a class="dropdown-item" href="#">Another 
action</a></li>
-                   <li><hr class="dropdown-divider"></li>
-                   <li><a class="dropdown-item" href="#">Something else 
here</a></li>
-                 </ul>
-               </li>
-               <li class="nav-item">
-                 <a class="nav-link disabled">Disabled</a>
-               </li>
-             </ul>
-             <form class="d-flex" role="search">
-               <input class="form-control me-2" type="search" 
placeholder="Search" aria-label="Search">
-               <button class="btn btn-outline-success" 
type="submit">Search</button>
-             </form>
-           </div>
-         </div>
-       </nav>
+</nav>
 
+<div class="container">
 
     <div class="row">
         <div id="title">
@@ -87,20 +112,26 @@
                 <td>[[${headerUiModel.branding.logoHref}]]</td>
             </tr>
             
-            <tr class="result" th:each="topLevelEntry : 
${headerUiModel.navbar().primary().topLevelEntries()}">
+            <th:block 
th:with="topNavSection=${headerUiModel.navbar().primary()}">
+            <tr class="result" th:each="topLevelEntry : 
${topNavSection.topLevelEntries()}">
                 <td>[[${topLevelEntry.name}]]</td>
                 <td>[[${topLevelEntry.subEntries}]]</td>
             </tr>
             </th:block>
-            <tr class="result" th:each="topLevelEntry : 
${headerUiModel.navbar().secondary().topLevelEntries()}">
+            
+            <th:block 
th:with="topNavSection=${headerUiModel.navbar().secondary()}">
+            <tr class="result" th:each="topLevelEntry : 
${topNavSection.topLevelEntries()}">
                 <td>[[${topLevelEntry.name}]]</td>
                 <td>[[${topLevelEntry.subEntries}]]</td>
             </tr>
-            <tr class="result" th:each="topLevelEntry : 
${headerUiModel.navbar().tertiary().topLevelEntries()}">
+            </th:block>
+            
+            <th:block 
th:with="topNavSection=${headerUiModel.navbar().tertiary()}">
+            <tr class="result" th:each="topLevelEntry : 
${topNavSection.topLevelEntries()}">
                 <td>[[${topLevelEntry.name}]]</td>
                 <td>[[${topLevelEntry.subEntries}]]</td>
             </tr>
-            
+            </th:block>
             
             <tr class="result">
                 <td>User</td>
@@ -118,4 +149,5 @@
     </div>
 
 </div>
-</body>
\ No newline at end of file
+</body>
+</html>
\ No newline at end of file
diff --git 
a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiModel.java
 
b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiModel.java
index 4cb09499d5..faeaf59572 100644
--- 
a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiModel.java
+++ 
b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiModel.java
@@ -18,7 +18,6 @@
  */
 package org.apache.causeway.viewer.commons.applib.services.header;
 
-import org.apache.causeway.commons.io.YamlUtils;
 import 
org.apache.causeway.viewer.commons.applib.services.branding.BrandingUiModel;
 import 
org.apache.causeway.viewer.commons.applib.services.menu.model.NavbarUiModel;
 import 
org.apache.causeway.viewer.commons.applib.services.userprof.UserProfileUiModel;
@@ -30,8 +29,4 @@ public record HeaderUiModel(
         @NonNull UserProfileUiModel userProfile,
         @NonNull NavbarUiModel navbar) {
 
-    public String toYaml() {
-        return YamlUtils.toStringUtf8(this);
-    }
-
 }

Reply via email to