diff of 0b101258363c57838b9c853d2b11fe5abdb0803f

0b101258363c57838b9c853d2b11fe5abdb0803f
diff --git a/src/models/tab.lisp b/src/models/tab.lisp
index b323cdc..a713bda 100644
--- a/src/models/tab.lisp
+++ b/src/models/tab.lisp
@@ -5,7 +5,7 @@
 (in-package :murja.models.tab)
 
 (defclass tab ()
-  ((route :initarg :route :initform (error "Route needed") :accessor tab-route)
+  ((route :initarg :route :initform nil :accessor tab-route)
    (component :initarg :component :initform (error "Component needed") :accessor tab-component)
    (title :initarg :title :initform (error "Title needed") :accessor title)
    (require-login :initarg :require-login :initform nil :accessor require-login)
diff --git a/src/murja-newui/newui.lisp b/src/murja-newui/newui.lisp
index 1a7ff43..71617ef 100644
--- a/src/murja-newui/newui.lisp
+++ b/src/murja-newui/newui.lisp
@@ -84,7 +84,8 @@
 (defclass event ()
   ((generated-js-id :accessor generated-js-id :initform (format nil "fn~a" (random 98765)))
    (post-js :accessor post-js :initform "" :initarg :post-js)
-   (closure :initarg :closure :initform (error "Gimme closure") :accessor closure)))
+   (closure :initarg :closure :initform (error "Gimme closure") :accessor closure)
+   (parameter-value-getter :initarg :parameter-value-getter :initform nil :accessor parameter-value-getter)))
 
 (defmethod set-state ((s state) key value)
   (with-slots (state-map root-component root-component-generator) s
@@ -163,8 +164,11 @@
 
 (defvar *js-identifiers-in-scope* (hash))
 
-(defun e (fn &key (post-js ""))
-  (let ((ev (make-instance 'event :closure fn :post-js post-js)))
+(defun e (fn &key (post-js "") (parameter-value-getter "window.event.target.value"))
+  (let ((ev (make-instance 'event
+			   :closure fn
+			   :post-js post-js
+			   :parameter-value-getter parameter-value-getter)))
     (setf (gethash (generated-js-id ev) *js-identifiers-in-scope*) ev)
     ev))
 
@@ -176,7 +180,7 @@
     (format out *component-format-string* tag attrs children)))
 
 (defmethod print-object ((e event) out)
-  (format out "send('~a', window.event.target.value); ~a /*post-js*/; return false;" (generated-js-id e) (post-js e)))
+  (format out "send('~a', ~a); ~a /*post-js*/; return false;" (generated-js-id e) (parameter-value-getter e) (post-js e)))
 ;; (with-slots (generated-js-id closure) e
 ;;   (format out "#<generated-js-id: ~a, closure: ~a>" generated-js-id (function-lambda-expression closure))))
 
diff --git a/src/views/blog-post-editor.lisp b/src/views/blog-post-editor.lisp
index 21586c5..bbd5347 100644
--- a/src/views/blog-post-editor.lisp
+++ b/src/views/blog-post-editor.lisp
@@ -1,26 +1,63 @@
 (defpackage murja.views.blog-post-editor
-  (:use :cl :murja.newui.dispatcher :murja.newui)
+  (:use
+   :cl
+   :murja.newui.dispatcher
+   :murja.newui
+   :murja.views.components.tab)
+  (:import-from :murja.middleware.auth :*user*)
   (:export :editor)
+  (:local-nicknames (:tabs :murja.models.tab))
   (:local-nicknames (:json :com.inuoe.jzon))
   (:local-nicknames (:modelpost :murja.models.post)))
 
 (in-package :murja.views.blog-post-editor)
 
 (defun editor (post)
+
   (with-state ((title (modelpost:post-title post))
 	       (content (modelpost:article post))) ()
-      (c :div ()
-       (c :input (:type "text"
-		  :name "title"
-		  :oninput (e (lambda (value) (format t "new title is ~s ~%" value)))
-		  :value title))
-       (c :textarea (:name "content"
-		     :oninput (e (lambda (value) (format t "oninput called with text value ~s~%" value ))))
-	  content)
-       (c :button (:onclick (e (lambda (v)
-				 (declare (ignore v))
-				 (format t "Toimiiko edes tää?~%"))))
-	  "Click me"))))
+    (c :div (:class "posteditor-tab")
+       (c :div (:class "editor-top")
+	  (c :input (:type "text"
+		     :name "title"
+		     :onchange (e (lambda (value) (setf title value)))
+		     :value title))
+	  (c :button (:onclick (e (lambda (v)
+				    (declare (ignore v))
+				    (format t "Toimiiko edes tää?~%"))))
+	     "Click me"))
+
+       (tabs "Editor"
+	     (list (make-instance 'tabs:tab
+				  :title "Editor"
+				  :subtab t				  
+				  :component (lambda (&rest all)
+					       (declare (ignore all))
+					       (c :div (:class "editor-container")
+						  (c :div (:name "content"
+							   :id "editor-post-content"
+							   :onchange (e (lambda (value) (setf content value))
+									;; ace-editor's event parameters are useless, to get the whole article one has to hack like this in the frontend
+									:parameter-value-getter "ace.edit('editor-post-content').getValue()"))
+						     content))))
+		   (make-instance 'tabs:tab
+				  :title "Preview"
+				  :subtab t
+				  :component (lambda (&rest lol)
+					       (declare (ignore lol))
+					       (c :div ()
+						  (let ((post (make-instance 'modelpost:post
+									     :title title
+									     :id -1
+									     :created-at nil
+									     :tags nil 
+									     :content content
+									     :creator *user*)))
+						    (murja.views.components.post:post post :show-footer? t))))))
+						
+	     nil
+	     :id "posteditor-preview-tab"
+	     ))))
 
 (deftab /blog/post/edit (:route "/blog/post/:id/edit"
 			 :require-login t
@@ -30,6 +67,7 @@
 			 :inject-to-head ((c :script (:src "https://cdnjs.cloudflare.com/ajax/libs/ace/1.43.1/ace.min.js"
 						      :integrity "sha512-4pjReWfvI2kek2LBL2nn0btGloS+00a3CvuBXdSOY0DjuMm3YJy8M5CKWKaXd4QJG5Fh4iKlLuboM1ru7FHT6Q=="
 						      :crossorigin "anonymous"
-						      :referrerpolicy "no-referrer") )))
+						      :referrerpolicy "no-referrer") )
+					  (c :script (:src "/resources/murja-ace.js"))))
   (let ((post (modelpost:get-post id :allow-hidden? t)))
     (editor post)))
diff --git a/src/views/components/post.lisp b/src/views/components/post.lisp
index 1ae697f..610615a 100644
--- a/src/views/components/post.lisp
+++ b/src/views/components/post.lisp
@@ -13,8 +13,8 @@
 	  (c :a (:href (format nil "/blog/post/~d" (post-id post)))
 	     (post-title post)))
        (c :section (:class "meta")
-	  (c :img (:class "user_avatar" :src (user-img-location creator)))
-	  (c :p () (format nil "By ~a" (user-nickname creator)))
+	  (c :img (:class "user_avatar" :src (when creator (user-img-location creator))))
+	  (c :p () (format nil "By ~a" (when creator (user-nickname creator))))
 	  (c :p () "Written at"
 	     (c :time (:datetime (created-at post))
 		(created-at post))))
diff --git a/src/views/components/tab.lisp b/src/views/components/tab.lisp
index 0544067..3df11d6 100644
--- a/src/views/components/tab.lisp
+++ b/src/views/components/tab.lisp
@@ -8,7 +8,7 @@
 
 ;; (defvar *selected-tab* nil)
 
-(defun tabs (firstly-selected-title tablist tab-params ;; &key onleave ;; how did I plan to call js callbacks here again? 
+(defun tabs (firstly-selected-title tablist tab-params &key id ;;onleave ;; how did I plan to call js callbacks here again? 
 	     )
   "Takes in a Title -> (Component | State mapping, returns a component that's supposed to look like the tab component used by the old Elm app"
 
@@ -18,12 +18,11 @@
 						(equalp (tabmodel:title tab)
 							selected-title))
 					      tablist))))
-      (c :div (:id "topbar" :class "tabs")
+      (c :div (:id (or id "topbar") :class "tabs")
 	 (component :ul (:class "tab-headers")
 		    (map 'list
 			 (lambda (tab)
-			   ;; what if we made (:li () (:a () ...) ...) that'd be changed into a (:li () ...) later if javascript exists?
-			   (c :li (:class (format nil "tab-header delinkify ~a" (when (string= (tabmodel:title tab) selected-title) "tab-selected"))
+			   (c :li (:class (format nil "tab-header ~a" (when (string= (tabmodel:title tab) selected-title) "tab-selected"))
 				   :data-href (tabmodel:tab-route tab))
 			      (c :a (:href (tabmodel:tab-route tab)
 				     :onclick (e (lambda (unused)