KB54 Group posts by date, use floating to make style sheet even more compact.

Change-Id: I41346eb51481d4c2c4e7066373fba5b7073e3e4f
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 92e2f4e..1fa7a26 100644
--- a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java
+++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java
@@ -61,10 +61,17 @@
 
   private static final Logger log = Logger.getLogger(PostResource.class);
 
-  private static final DateTimeFormatter htmlDateFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+  private static final DateTimeFormatter htmlDateTimeFormatter =
+      DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+
+  private static final DateTimeFormatter humanDateTimeFormatter =
+      DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
+
+  private static final DateTimeFormatter htmlDateFormatter =
+      DateTimeFormatter.ISO_LOCAL_DATE;
 
   private static final DateTimeFormatter humanDateFormatter =
-      DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
+      DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
 
   private static final int pageKeyBytes = 32;
 
@@ -331,7 +338,7 @@
     if (x == null) {
       return null;
     }
-    return humanDateFormatter.format(x);
+    return humanDateTimeFormatter.format(x);
   }
 
   @TemplateExtension
@@ -340,6 +347,24 @@
     if (x == null) {
       return null;
     }
+    return htmlDateTimeFormatter.format(x);
+  }
+
+  @TemplateExtension
+  @CheckForNull
+  static String humanDate(@CheckForNull TemporalAccessor x) {
+    if (x == null) {
+      return null;
+    }
+    return humanDateFormatter.format(x);
+  }
+
+  @TemplateExtension
+  @CheckForNull
+  static String htmlDate(@CheckForNull TemporalAccessor x) {
+    if (x == null) {
+      return null;
+    }
     return htmlDateFormatter.format(x);
   }
 
diff --git a/src/main/resources/META-INF/resources/cms2/base.css b/src/main/resources/META-INF/resources/cms2/base.css
index 11a2e70..e4ef41b 100644
--- a/src/main/resources/META-INF/resources/cms2/base.css
+++ b/src/main/resources/META-INF/resources/cms2/base.css
@@ -171,8 +171,17 @@
   border-top: lightgray solid 1px;
 }
 
+.post-day {
+  margin: 0.5em 0;
+}
+
+.bookmark-title-section {
+  display: inline;
+}
+
 a.bookmark-title {
   text-decoration: none;
+  margin-right: 1em;
 }
 
 h1.bookmark-title {
@@ -182,42 +191,64 @@
   display: inline;
 }
 
+.post-day-info {
+  font-size: smaller;
+  font-style: italic;
+}
+
+.post-owner {
+  font-size: smaller;
+  color: #555;
+}
+
+.post-self-link {
+  padding-left: 5px;
+  padding-right: 5px;
+}
+
 .bookmark-info {
   font-style: italic;
-  font-size: smaller;
   margin: 0;
   padding: 0;
   flex: auto;
 }
 
+.bookmark-controls {
+  float: right;
+}
+
 article.bookmark {
-  margin: 0.5em 0;
   border: 1px solid #e0b0b0;
   padding: 0.3em;
   background: #f8f0f0;
 }
 
 article.bookmark > header {
-  display: flex
+  display: inline-flex;
+  margin-right: 5px;
+}
+
+.post-with-nonempty-body > header {
+  float: left;
 }
 
 .lazychat-message-info {
   font-style: italic;
-  font-size: smaller;
   margin: 0;
   padding: 0;
   flex: auto;
 }
 
 article.lazychat-message {
-  margin: 0.5em 0;
   border: 1px solid #a0c0c0;
   padding: 0.3em;
   background: #f0f8f0;
 }
 
 article.lazychat-message > header {
-  display: flex
+  display: flex;
+  float: left;
+  margin-right: 5px;
 }
 
 a.post-link {
@@ -250,7 +281,27 @@
 }
 
 .lazychat-message-controls {
-  flex: initial;
+  float: right;
+}
+
+.post-content > :first-child {
+  margin-top: 0;
+}
+
+.post-content > :last-child {
+  margin-bottom: 0;
+}
+
+.bookmark-description > :nth-child(2) {
+  margin-top: 0;
+}
+
+.bookmark-description > blockquote :first-child {
+  margin-top: 0;
+}
+
+.bookmark-description > blockquote :last-child {
+  margin-bottom: 0;
 }
 
 .paging {
diff --git a/src/main/resources/templates/benki/posts/postList.html b/src/main/resources/templates/benki/posts/postList.html
index 2911be4..f178927 100644
--- a/src/main/resources/templates/benki/posts/postList.html
+++ b/src/main/resources/templates/benki/posts/postList.html
@@ -54,25 +54,14 @@
 <section id="main-content">
   {#for day in postDays}
     <div class="post-day">
+      <div class="post-day-info">
+        <time datetime="{day.date.htmlDate}">{day.date.humanDate}</time>
+      </div>
+
       {#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>
-
+            <article class="bookmark {#if descriptionHtml != ""}post-with-nonempty-body{/if}">
               <section class="bookmark-editor post-editor">
                 {#if showBookmarkForm}
                 <elix-expandable-panel class="bookmark-editor-pane editor-pane">
@@ -81,40 +70,55 @@
                 {/if}
               </section>
 
-              <section class="bookmark-title-section">
-                <a href="{uri}" class="bookmark-title"><h1 class="bookmark-title">⇢&nbsp;{title}</h1></a>
-              </section>
+              <header>
+                <div class="bookmark-info">
+                  <span class="bookmark-owner post-owner">{owner.firstName}</span>
+                  <a class="post-link" href="/posts/{post.id}">
+                    <span class="post-self-link">#</span>
+                  </a>
 
-              <section class="bookmark-description">
+                  <a href="{uri}" class="bookmark-title">
+                    <h1 class="bookmark-title">⇢&nbsp;{title}</h1>.
+                  </a>
+                </div>
+              </header>
+
+              <div class="bookmark-controls">
+                {#if showBookmarkForm}
+                <button class="pure-button bookmark-edit-button">Edit</button>
+                {/if}
+              </div>
+
+              <section class="bookmark-description post-content">
                 {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>
-
               <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>
+                <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">
+              <header>
+                <div class="lazychat-message-info">
+                  <span class="lazychat-message-owner post-owner">{owner.firstName}</span>
+                  <a class="post-link" href="/posts/{post.id}">
+                    <span class="post-self-link">#</span>
+                  </a>
+                </div>
+              </header>
+
+              <div class="lazychat-message-controls">
+                {#if showLazychatForm}
+                <button class="pure-button lazychat-edit-button">Edit</button>
+                {/if}
+              </div>
+
+              <section class="lazychat-message-content post-content">
                 {contentHtml.raw}
               </section>
             </article>