diff of a054661835d8c54cfd57c2dbf1aabffd84d26ca2

a054661835d8c54cfd57c2dbf1aabffd84d26ca2
diff --git a/resources/css/murja.css b/resources/css/murja.css
index 2500153..77b2442 100644
--- a/resources/css/murja.css
+++ b/resources/css/murja.css
@@ -285,6 +285,11 @@ header {
     display: block;
 }
 
+.previously a {
+    /* a slight space between previously-links */
+    margin-right: 9px;
+}
+
 .page-changer {
     display: flex;
     justify-content: space-between;
diff --git a/src/models/post.lisp b/src/models/post.lisp
index 5f2c5bb..e0c9285 100644
--- a/src/models/post.lisp
+++ b/src/models/post.lisp
@@ -1,6 +1,6 @@
 (defpackage murja.models.post
   (:use :cl)
-  (:export :Post :get-page :get-post :post-id :post-title :article :creator :tags :created-at :post-hidden? :post-unlisted? :next-post-id :previous-post-id)
+  (:export :Post :get-page :get-post :post-id :post-title :article :creator :tags :created-at :post-hidden? :post-unlisted? :next-post-id :previous-post-id :previouslies)
   (:import-from :com.inuoe.jzon :parse))
 
 (in-package :murja.models.post)
@@ -18,13 +18,15 @@
    (hidden :initarg :hidden? :accessor post-hidden? :col-type boolean)
    (unlisted :initarg :unlisted? :accessor post-unlisted? :col-type boolean)
    (previous :ghost t :initarg :previous :accessor previous-post-id :col-type integer :initform -1)
-   (next :initform -1 :ghost t :initarg :next :accessor next-post-id :col-type integer))
+   (next :initform -1 :ghost t :initarg :next :accessor next-post-id :col-type integer)
+
+   (previouslies :initform nil :ghost t :initarg ghostlies :accessor previouslies :col-type string))
   (:metaclass postmodern:dao-class)
   (:keys id)
   (:table-name "blog.Post"))
 
 (defmethod print-object ((p Post) output)
-  (with-slots (creator id title content creator-id tags created-at hidden unlisted previous next) p
+  (with-slots (creator id title content creator-id tags created-at hidden unlisted previous next previouslies) p
     (format output "#<POST: ~{~{~a: ~s~}~^,~%~t ~}>" (list
 						(list :id id)
 						(list :title title)
@@ -40,7 +42,8 @@
 						(list :hidden hidden)
 						(list :unlisted unlisted)
 						(list :previous previous)
-						(list :next next)))))
+						(list :next next)
+						(list :previouslies previouslies)))))
 
 ;; (postmodern:query "SELECT * FROM blog.Post limit 1" (:dao post :single))
 ;; (postmodern:get-dao 'Post 349)
@@ -49,6 +52,15 @@
 (defun fix-post (p)
   ;; let's coerce this array into list, #() is truthy according to lisp 
   (setf (tags p) (coerce (parse (tags p)) 'list))
+
+  (unless (previouslies p)
+    (format t "ERROR previouslies were nil. Have you forgotten to join them to your posts?~%"))
+
+  (if (equalp "[null]" (previouslies p))
+      (setf (previouslies p) nil)
+      (when (stringp (previouslies p))
+	(setf (previouslies p) (coerce (parse (previouslies p)) 'list))))
+  
   (setf (creator p) (postmodern:get-dao 'murja.models.user:user (creator-id p)))
 
   ;; next-id and previous-id might point to unlisted posts. They should not do that, but I don't know how to wrangle *post-query* sql to support that, so they have to be fixed in lisp.
@@ -68,7 +80,16 @@
 (defparameter *post-query*
   "
 SELECT * FROM
-(SELECT p.*, LAG(id, 1, -1) OVER (ORDER BY created_at) as previous, LEAD(id, 1, -1) OVER (ORDER BY created_at) as next FROM blog.Post p where (NOT p.hidden OR (p.hidden AND $2)))
+(SELECT p.*,
+ LAG(p.id, 1, -1) OVER (ORDER BY created_at) as previous,
+ LEAD(p.id, 1, -1) OVER (ORDER BY created_at) as next,
+ JSON_AGG(TO_JSONB (pl.*) - 'referencee_id') as previouslies 
+ FROM blog.Post p
+ LEFT JOIN blog.Previously_Link_Titles pl ON (p.id = pl.referencee_id AND 
+                                              EXISTS (SELECT * FROM blog.Post pp WHERE pp.id = pl.id AND NOT pp.hidden AND NOT pp.unlisted))
+ WHERE (NOT p.hidden OR (p.hidden AND $2))
+ GROUP BY p.id
+)
 where id = $1
 ")
   
@@ -85,11 +106,14 @@ where id = $1
     (map 'list
 	 #'fix-post 
 	 (postmodern:query
-	  "SELECT p.*
+	  "SELECT p.*, JSON_AGG(TO_JSONB (pl.*) - 'referencee_id') as previouslies 
 FROM blog.Post p
+LEFT JOIN blog.Previously_Link_Titles pl ON (p.id = pl.referencee_id AND 
+                                             EXISTS (SELECT * FROM blog.Post pp WHERE pp.id = pl.id AND NOT pp.hidden AND NOT pp.unlisted))
 WHERE ((NOT p.unlisted) OR $3)
   AND ((NOT p.hidden) OR $3)
   AND (($4::timestamp IS NULL) OR p.created_at > $4::timestamp)
+GROUP BY p.id 
 ORDER BY p.created_at DESC
 LIMIT $2
 OFFSET $1"
@@ -100,3 +124,5 @@ OFFSET $1"
 	      modified-since
 	      :null)
 	  (:dao Post)))))
+
+;;(get-post 349)
diff --git a/src/views/components/post.lisp b/src/views/components/post.lisp
index 2e6f734..c2c1825 100644
--- a/src/views/components/post.lisp
+++ b/src/views/components/post.lisp
@@ -1,11 +1,13 @@
 (defpackage murja.views.components.post
   (:use :cl :murja.newui :cl-hash-util :binding-arrows :murja.models.user )
-  (:import-from :murja.models.post :post-id :post-title :creator :created-at :article :previous-post-id :next-post-id :tags)
+  (:import-from :murja.middleware.db :*settings*)
+  (:import-from :murja.models.post :previouslies :post-id :post-title :creator :created-at :article :previous-post-id :next-post-id :tags)
   (:export :post))
 
 (in-package :murja.views.components.post)
 
 (defun post (post &key show-footer?)
+  (assert *settings*)
   (let ((creator (creator post)))
     (c :article (:class "post")
        (c :h2 ()
@@ -20,6 +22,18 @@
 
        (c :section (:class "content") (article post))
 
+       
+       (when (previouslies post)
+	 (component :div (:class "previously")
+		    (map 'list
+			 (lambda (p)
+			   (cl-hash-util:with-keys ("title" "id") p
+			       (c :a (:href (format nil "/blog/post/~d" id))
+				  (format nil "~a, " (gethash "previously_label" *settings*)))))
+			 (previouslies post))))
+		     
+		    
+
        (when (tags post)
 	 (component :ul (:class "tags")
 		    (map 'list 
diff --git a/test/post.lisp b/test/post.lisp
index c9bfcfe..c35762c 100644
--- a/test/post.lisp
+++ b/test/post.lisp
@@ -66,6 +66,11 @@
 		       :previous nil
 		       :tags "[]")))
 
+(defun setup-previouslies ()
+  "5 refers to 3 and 4 (so should be fetched from db without any previouslies.
+3 refers to 1 and 2 and should contain those"
+  (postmodern:execute "INSERT INTO blog.previously_link VALUES (5, 3), (5,4), (3, 1), (3, 2)"))
+
 (defmacro within-post-test-db (&body body)
   `(progn
      (setf murja.middleware.db:*automatic-tests-on?* t)
@@ -79,7 +84,9 @@
 		(postmodern:execute "DROP TABLE IF EXISTS public.migrations_tracker")
 		(murja.migrations:migrate)
 		(postmodern:insert-dao *test-user*)
-		(mapcar #'postmodern:insert-dao *test-posts*)		
+		(mapcar #'postmodern:insert-dao *test-posts*)
+		(setup-previouslies)
+		
 		,@body)
 
 	(postmodern:execute "DROP SCHEMA IF EXISTS blog CASCADE;")
@@ -119,7 +126,18 @@
 
       ;; the next link skips correctly hiddens and unlisteds
       (is (equalp 5
-		  (next-post-id post-1))))))
+		  (next-post-id post-1))))
+
+    ;; test that previouslies honour unlisted and hidden
+    (let ((post-5 (murja.models.post:get-post 5))
+	  (post-3 (murja.models.post:get-post 3)))
+      (is-false (previouslies post-5))
+
+      (is (equalp 1
+		  (length (previouslies post-3))))
+      (is (equalp 1
+		  (gethash "id" (first (previouslies post-3)))))))) ;; 2 is hidden
+		  
 
 ;; (fiveam:explain! 
 ;;  (fiveam:run 'post-model-test))