KB54 Put posts in date buckets for templating.

Change-Id: Ic17b2dede722f5962a55b9c4d3b4663a71480e9c
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
index 3a02e4e..bbfafa2 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java
@@ -6,11 +6,15 @@
 import eu.mulk.mulkcms2.benki.users.User;
 import eu.mulk.mulkcms2.benki.users.User_;
 import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
+import java.time.LocalDate;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TimeZone;
+import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import javax.json.bind.annotation.JsonbTransient;
@@ -173,7 +177,9 @@
     public @CheckForNull final Integer nextCursor;
     public final List<T> posts;
 
-    private PostPage(
+    private static final TimeZone timeZone = TimeZone.getDefault();
+
+    public PostPage(
         @CheckForNull Integer c0,
         @CheckForNull Integer c1,
         @CheckForNull Integer c2,
@@ -183,6 +189,26 @@
       this.nextCursor = c2;
       this.posts = resultList;
     }
+
+    public class Day {
+      public final @CheckForNull LocalDate date;
+      public final List<T> posts;
+
+      private Day(LocalDate date, List<T> posts) {
+        this.date = date;
+        this.posts = posts;
+      }
+    }
+
+    public List<Day> days() {
+      return posts.stream()
+          .collect(Collectors.groupingBy(post -> post.date.toLocalDate()))
+          .entrySet()
+          .stream()
+          .map(x -> new Day(x.getKey(), x.getValue()))
+          .sorted(Comparator.comparing((Day day) -> day.date).reversed())
+          .collect(Collectors.toUnmodifiableList());
+    }
   }
 
   public static List<Post> findViewable(
diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java
index 5f3c8b4..92e2f4e 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java
@@ -13,6 +13,7 @@
 import com.rometools.rome.io.WireFeedOutput;
 import eu.mulk.mulkcms2.benki.accesscontrol.PageKey;
 import eu.mulk.mulkcms2.benki.accesscontrol.Role;
+import eu.mulk.mulkcms2.benki.posts.Post.PostPage;
 import eu.mulk.mulkcms2.benki.users.User;
 import io.quarkus.qute.Template;
 import io.quarkus.qute.TemplateExtension;
@@ -116,7 +117,7 @@
     }
 
     return postList
-        .data("posts", q.posts)
+        .data("postDays", q.days())
         .data("feedUri", feedUri)
         .data("pageTitle", pageTitle)
         .data("showBookmarkForm", showBookmarkForm())
@@ -150,7 +151,7 @@
     }
 
     return postList
-        .data("posts", q.posts)
+        .data("postDays", q.days())
         .data("feedUri", feedUri)
         .data("pageTitle", pageTitle)
         .data("showBookmarkForm", showBookmarkForm())
@@ -191,7 +192,7 @@
     var post = getPostIfVisible(id);
 
     return postList
-        .data("posts", List.of(post))
+        .data("postDays", new PostPage<>(null, null, null, List.of(post)).days())
         .data("pageTitle", pageTitle)
         .data("showBookmarkForm", false)
         .data("showLazychatForm", false)
diff --git a/src/main/resources/templates/benki/posts/postList.html b/src/main/resources/templates/benki/posts/postList.html
index bc479f4..2911be4 100644
--- a/src/main/resources/templates/benki/posts/postList.html
+++ b/src/main/resources/templates/benki/posts/postList.html
@@ -1,4 +1,4 @@
-{@java.util.List<eu.mulk.mulkcms2.benki.posts.Post> posts}
+{@java.util.List<eu.mulk.mulkcms2.benki.posts.Day> postDays}
 {@java.lang.String pageTitle}
 {@java.lang.Boolean showBookmarkForm}
 {@java.lang.Boolean hasPreviousPage}
@@ -52,72 +52,76 @@
 </div>
 
 <section id="main-content">
-  {#for post in posts}
-    {#with post}
-      {#if post.isBookmark}
-        <article class="bookmark">
-          <header>
-            <div class="bookmark-info">
-              <a class="post-link" href="/posts/{post.id}">
-                <time datetime="{date.htmlDateTime}">{date.humanDateTime}</time>
-                <span class="bookmark-owner">{owner.firstName} {owner.lastName}</span>
-              </a>
-            </div>
+  {#for day in postDays}
+    <div class="post-day">
+      {#for post in day.posts}
+        {#with post}
+          {#if post.isBookmark}
+            <article class="bookmark">
+              <header>
+                <div class="bookmark-info">
+                  <a class="post-link" href="/posts/{post.id}">
+                    <time datetime="{date.htmlDateTime}">{date.humanDateTime}</time>
+                    <span class="bookmark-owner">{owner.firstName} {owner.lastName}</span>
+                  </a>
+                </div>
 
-            <div class="bookmark-controls">
-              {#if showBookmarkForm}
-              <button class="pure-button bookmark-edit-button">Edit</button>
-              {/if}
-            </div>
-          </header>
+                <div class="bookmark-controls">
+                  {#if showBookmarkForm}
+                  <button class="pure-button bookmark-edit-button">Edit</button>
+                  {/if}
+                </div>
+              </header>
 
-          <section class="bookmark-editor post-editor">
-            {#if showBookmarkForm}
-            <elix-expandable-panel class="bookmark-editor-pane editor-pane">
-              <mlk-bookmark-submission-form edited-id="{post.id}"></mlk-bookmark-submission-form>
-            </elix-expandable-panel>
-            {/if}
-          </section>
+              <section class="bookmark-editor post-editor">
+                {#if showBookmarkForm}
+                <elix-expandable-panel class="bookmark-editor-pane editor-pane">
+                  <mlk-bookmark-submission-form edited-id="{post.id}"></mlk-bookmark-submission-form>
+                </elix-expandable-panel>
+                {/if}
+              </section>
 
-          <section class="bookmark-title-section">
-            <a href="{uri}" class="bookmark-title"><h1 class="bookmark-title">⇢&nbsp;{title}</h1></a>
-          </section>
+              <section class="bookmark-title-section">
+                <a href="{uri}" class="bookmark-title"><h1 class="bookmark-title">⇢&nbsp;{title}</h1></a>
+              </section>
 
-          <section class="bookmark-description">
-            {descriptionHtml.raw}
-          </section>
-        </article>
-      {#else}
-        <article class="lazychat-message">
-          <header>
-            <div class="lazychat-message-info">
-              <a class="post-link" href="/posts/{post.id}">
-                <time datetime="{date.htmlDateTime}">{date.humanDateTime}</time>
-                <span class="lazychat-message-owner">{owner.firstName} {owner.lastName}</span>
-              </a>
-            </div>
+              <section class="bookmark-description">
+                {descriptionHtml.raw}
+              </section>
+            </article>
+          {#else}
+            <article class="lazychat-message">
+              <header>
+                <div class="lazychat-message-info">
+                  <a class="post-link" href="/posts/{post.id}">
+                    <time datetime="{date.htmlDateTime}">{date.humanDateTime}</time>
+                    <span class="lazychat-message-owner">{owner.firstName} {owner.lastName}</span>
+                  </a>
+                </div>
 
-            <div class="lazychat-message-controls">
-              {#if showLazychatForm}
-                <button class="pure-button lazychat-edit-button">Edit</button>
-              {/if}
-            </div>
-          </header>
+                <div class="lazychat-message-controls">
+                  {#if showLazychatForm}
+                    <button class="pure-button lazychat-edit-button">Edit</button>
+                  {/if}
+                </div>
+              </header>
 
-          <section class="lazychat-editor post-editor">
-            {#if showLazychatForm}
-              <elix-expandable-panel class="lazychat-editor-pane editor-pane">
-                <mlk-lazychat-submission-form edited-id="{post.id}"></mlk-lazychat-submission-form>
-              </elix-expandable-panel>
-            {/if}
-          </section>
+              <section class="lazychat-editor post-editor">
+                {#if showLazychatForm}
+                  <elix-expandable-panel class="lazychat-editor-pane editor-pane">
+                    <mlk-lazychat-submission-form edited-id="{post.id}"></mlk-lazychat-submission-form>
+                  </elix-expandable-panel>
+                {/if}
+              </section>
 
-          <section class="lazychat-message-content">
-            {contentHtml.raw}
-          </section>
-        </article>
-      {/if}
-    {/with}
+              <section class="lazychat-message-content">
+                {contentHtml.raw}
+              </section>
+            </article>
+          {/if}
+        {/with}
+      {/for}
+    </div>
   {/for}
 </section>