(in-package :fwoar.rss-reader) (defmethod spinneret:html ((object plump:node)) (plump:serialize object spinneret:*html*)) (defclass rss-reader-route () ((%feed-list :initarg :feed-list :reader feed-list))) (defun nav (route) (spinneret:with-html (loop for feed in (feed-list route) for idx from 0 collect (:a :data-ic-get-from (format nil "/f/~a" (string-downcase (feed-key feed))) :class (if (string= (feed-key feed) (feed-key (feed route))) "active" "") (feed-key feed))))) (defmethod araneus:view :around ((route rss-reader-route) model) "basic html and javascript for our app, as well as an invocation of the hook that pulls in CSS" (etypecase model (fwoar.intercooler:full-request (spinneret:with-html-string (:doctype) (:html (:head (:script :src "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js") (:script :src "https://cdnjs.cloudflare.com/ajax/libs/intercooler-js/1.2.3/intercooler.min.js" :defer "defer") (:script :defer "defer" (:raw (fwoar.rss-reader.ui:intercooler-debugger))) (:meta :name "intercoolerjs:use-data-prefix" :content "true"/) (:style (:raw (apply 'lass:compile-and-write (araneus:styles route))))) (:body (call-next-method))))) (fwoar.intercooler:partial-request (spinneret:with-html-string (call-next-method))))) (defmethod araneus:styles append ((route rss-reader-route)) "CSS Reset" '((* :margin 0 :padding 0 :font-family "\"Lato\", sans" :box-sizing border-box) ((:or pre code) :font-family "\"Source Code Pro\", monospace") (body :font-size 12pt) ((:or h1 h2 h3 h4 h5 h6) :font-size 1.6rem) ((:or ul ol) :padding-left 2rem) (.active :background "#888"))) (defmacro with-layout ((render-type layout) &body content) `(let ((content (lambda () (spinneret:with-html (:main ,@content))))) (ecase ,render-type (:full (spinneret:with-html (,layout content))) (:partial (funcall content))))) (defclass+ feed-page ((rss-reader-route (feed-list)) fwoar.intercooler:intercooler-route fwoar.default-layout:default-layout) ((%feed :initarg :feed :reader feed))) (defmethod araneus:controller ((route feed-page) params &key) (resolve-feed-reference (feed route))) (defmethod araneus:view ((route feed-page) (model fwoar.intercooler:intercooler-request)) (spinneret:with-html (spinneret:html (alimenta:render (fwoar.intercooler:request model) (feed route))))) (defmethod araneus:view ((route feed-page) (model fwoar.intercooler:full-request)) (spinneret:with-html (:h1 "Hello, World!") (:div.main (:nav :data-ic-push-url "true" :data-ic-target "#content" :data-ic-switch-class "active" (nav route)) (:main#content :data-ic-target "#content" (alimenta:render (fwoar.intercooler:request model) (feed route)))))) (defclass+ feed-item-page ((rss-reader-route (feed-list)) fwoar.intercooler:intercooler-route fwoar.default-layout:default-layout) ((%feed :initarg :feed :reader feed) (%item :initarg :item :reader item))) (defmethod araneus:controller ((route feed-item-page) params &key) (find (item route) (resolve-feed-reference (feed route)) :key (alexandria:compose 'id->slug 'alimenta:id) :test 'string-equal)) (defmethod araneus:view ((route feed-item-page) (model fwoar.intercooler:intercooler-request)) (spinneret:with-html (:raw (alimenta:content (fwoar.intercooler:request model))))) (defmethod araneus:view ((route feed-item-page) (model fwoar.intercooler:full-request)) (spinneret:with-html (:h1 "Hello, World!") (:div.main (:nav :data-ic-push-url "true" :data-ic-target "#content" #+(or)(:data-ic-replace-target "true") :data-ic-switch-class "active" (nav route)) (:main#content :data-ic-target "#content" (:raw (alimenta:content (fwoar.intercooler:request model))))))) (defmethod fwoar.default-layout:border-color ((layout rss-reader-route)) "#BDE0F3") (defmethod fwoar.default-layout:background-color ((layout rss-reader-route)) "#3f3f3f") (defmethod fwoar.default-layout:text-color ((layout rss-reader-route)) "#DCDCCC") (defmethod fwoar.default-layout:link-color ((layout rss-reader-route)) "#F5F5D6")