M good-place/acts.janet => good-place/acts.janet +6 -5
@@ 29,10 29,11 @@
(forever
(def lc (notify-modify t))
(cocoon/emerge
- (make-act {:watch
- (fn [&] [(clear-module lc) RenderAll])
- :effect
- (fn [&] (print "Modified " lc))})))))
+ (make-act
+ {:watch
+ (fn [&] [(clear-module lc) RenderAll])
+ :effect
+ (fn [&] (print "Modified " lc))})))))
(define-watch Monitor [&]
[content/Monitor
@@ 57,7 58,7 @@
(define-watch Development [&]
[Present
SetDev
- (web/start
+ (web/open
{:render-content-file content/render-file
:render-blog-file blog/markup-and-render-file
:render-all RenderAll
M good-place/acts/blog.janet => good-place/acts/blog.janet +2 -2
@@ 30,7 30,7 @@
(make-watch
(fn [_ e _]
(def {:site-title st :dev dev :markups ms
- :files {:blog bfiles}} e)
+ :files {:blog bfiles} :trevor t} e)
(def m (require file))
(def {:template {'render-dict {:value rt}}
:content ct} m)
@@ 43,7 43,7 @@
:site-title st
:css (process-css e)
:file file
- :dev dev})
+ :dev dev :trevor t})
index?
(merge {:markups ms
:posts (filter |(not (index? $)) bfiles)}))))
M good-place/acts/content.janet => good-place/acts/content.janet +4 -4
@@ 1,8 1,8 @@
+(use shawn/act shawn/acts)
(import /mendoza/markup)
(import /mendoza/render)
-(use shawn/act)
-(use shawn/acts)
(import shawn/cocoon)
+(use /good-place/sock/acts)
(use ../utils)
(use ./shared)
@@ 10,14 10,14 @@
(defn render-file [file]
(make-watch
(fn [_ e _]
- (def {:site-title st :dev dev :pkgs-list pl} e)
+ (def {:site-title st :dev dev :pkgs-list pl :trevor t} e)
(def [m fc] [(require file) @""])
(with-dyns [:out fc]
((get-in m [:template 'render-dict :value])
(merge m
{:content (render/render (m :content) @"")
:site-title st :css (process-css e)
- :file file :dev dev})))
+ :file file :dev dev :trevor t})))
[(clear-module file) (save-content file fc)])
(. "render-" file)))
M good-place/acts/shared.janet => good-place/acts/shared.janet +16 -4
@@ 1,6 1,7 @@
(use shawn/acts)
(use spork)
(use ../utils)
+(use /good-place/sock/acts)
(defn copy-file [file ftype]
(make-effect
@@ 20,17 21,28 @@
(fn [_ e] (put-in e [:files dir] files))
(. "save-" dir)))
-(defn save-content [file content]
+(defn log-render [of nf]
+ (make-effect (fn [&] (print "Rendered " of " to " nf))
+ "log-render"))
+
+(defn spit-file [file content]
(make-effect
+ (fn [_ _ _]
+ (def dir (path/dirname file))
+ (if (not (os/stat dir)) (os/mkdir dir))
+ (spit file content))
+ (. "spit-file-" file)))
+
+(defn save-content [file content]
+ (make-watch
(fn [_ {:content c :public p} _]
(def nf
(->> file
(string/replace c p)
mdz->html))
(def dir (path/dirname nf))
- (if (not (os/stat dir)) (os/mkdir dir))
- (spit nf content)
- (print "Rendered " file " to " nf))
+ [(spit-file nf content) (log-render file nf)
+ (alert {:action :rendered :name nf})])
(. "save-content-" file)))
(defn log [& msgs]
M good-place/sock/acts.janet => good-place/sock/acts.janet +19 -16
@@ 9,29 9,20 @@
(import ../sock/app)
(use ../utils)
-(defn type-path [sck]
- ~[:socks ,(sck :type)])
+(defn type-path [sck] [:socks (sck :type)])
-(defn add [sck]
+(defn add-one [sck]
(make-update
(fn [_ e]
- (tour ~[,(type-path sck) (add ,sck)] e)
- e)
+ ((guide ;(type-path sck) (add sck)) e))
"add-sock"))
-(defn remove [sck]
+(defn remove-one [sck]
(make-update
(fn [_ e]
- (tour ~[,(type-path sck) (remove ,sck)] e)
- e)
+ ((guide ;(type-path sck) (remove sck)) e))
"remove-sock"))
-(defn alert [msg]
- (make-effect
- (fn [_ {:socks {:alert ss}} _]
- (each s ss
- (:write s (trevor/text (json/encode {:msg msg})))))))
-
(defn html [t p a]
(make-effect
(fn [_ {:socks ss} _]
@@ 39,6 30,18 @@
(:write s (trevor/text (page* p a)))))
(. "html-" t "-" p)))
+(defn alert [action]
+ (make-watch
+ (fn [_ {:socks {:alert ss}} _]
+ (seq [s :in ss]
+ (def name
+ (peg/replace
+ ~(* (thru "/")) "" (action :name)))
+ (def msg (. name " was " (action :action)))
+ (html :alert "notification"
+ {:msg msg :location name})))
+ (. alert "-" action)))
+
(defn start []
(make-act
{:watch
@@ 46,8 49,8 @@
(def {:trevor {:host host :port port}} e)
(cocoon/give
(chidi/start
- (app/handler {:add add
- :remove remove})
+ (app/handler {:add add-one
+ :remove remove-one})
host port
app/supervisor
trevor/on-connection)))
M good-place/web/acts.janet => good-place/web/acts.janet +7 -9
@@ 1,18 1,16 @@
-(use shawn/act)
-(import shawn/cocoon)
-(import chidi)
-(import ../web)
+(use shawn/act shawn/cocoon chidi)
+(use /good-place/web)
-(defn start [acts]
+(defn open [acts]
(make-act
{:watch
(fn [_ e _]
(def {:chidi {:host host :port port}} e)
- (cocoon/give
- (chidi/start
- (web/handler e acts)
+ (give
+ (start
+ (handler e acts)
host port
- web/supervisor)))
+ supervisor)))
:effect
(fn [_ {:chidi {:host host :port port}} _]
(print "Chidi Present on " host ":" port))}
M good-place/web/init.janet => good-place/web/init.janet +4 -2
@@ 53,6 53,7 @@
(layout @{:title (string "Editing " file)
:site-title st
:css (process-css envelope)
+ :dev true
:content
(page edit
@{:file-content
@@ 65,11 66,12 @@
:file-name file})})))
(defn save [list-content]
- (fn [{:body {"file-name" fnm "file-content" fc}}]
+ (fn [req]
+ (def {:body {"file-name" fnm "file-content" fc} :headers {"HX-Request" hx}} req)
(spit fnm (string/replace-all "\r\n" "\n" fc))
(emerge list-content)
(ev/sleep 0.01) # give monitor time to catch up
- (see-other (vf fnm))))
+ (if hx (no-content) (see-other (vf fnm)))))
(defn pkgs [get-pkgs]
(fn [&]
M templates/edit.temple => templates/edit.temple +2 -2
@@ 3,11 3,11 @@
(def fnm (args :file-name))
(def new? (= fnm new-file-name))
%}
-<form style="max-width: 45rem" action="/__dashboard/save" method="POST">
+<form hx-post="/__dashboard/save" style="max-width: 45rem" action="/__dashboard/save" method="POST">
<textarea name="file-content" cols="80" rows="20">{- (args :file-content) -}</textarea>
{- (if new? `<label for="name">File name</label>`) -}
<input type={- (if new? (. `"text" placeholder="` fnm `"`) `"hidden"`) -}
name="file-name" value="{- (unless new? fnm) -}"/>
<input type="submit" value="Save" />
- <a class="button" href="/__dashboard">Cancel</a>
+ <a class="button" href="/__dashboard">Back to Dashboard</a>
</form>
M => +29 -1
@@ 2,7 2,35 @@
<hstack align-x="center">Good Place 2021 All rights rejected</hstack>
</vstack>
</vstack>
<script src="https://unpkg.com/htmx.org@1.3.3" integrity="sha384-QrlPmoLqMVfnV4lzjmvamY0Sv/Am8ca1W7veO++Sp6PiIGixqkD+0xZ955Nc03qO" crossorigin="anonymous"></script>
{% (when (args :dev) %}
<script src="https://unpkg.com/htmx.org@1.6.1"
integrity="sha384-tvG/2mnCFmGQzYC1Oh3qxQ7CkQ9kMzYjWZSNtrRZygHPDDqottzEJsqS4oUVodhW"
crossorigin="anonymous"></script>
<script src="https://unpkg.com/hyperscript.org@0.9.0"></script>
<script type="text/hyperscript">
def checkNotifications()
if Notification.permission == "denied"
show <#notifications p.disabled />
else if Notification.permission == "default"
show <#notifications button />
else
show <#notifications p.enabled />
end
end
def requestNotification()
if Notification.permission == "denied"
call alert('You have denied the permission to Notification, please remove the block')
else if Notification.permission == "default"
set permission to Notification.requestPermission()
hide <#notifications button />
call checkNotifications()
else
js new Notification("Notifications enabled!") end
end
end
</script>
{% ) %}
</body>
</html>
M templates/head.temple => templates/head.temple +7 -2
@@ 1,3 1,5 @@
+{$ (use marble) $}
+{% (def d (args :dev))(def t (args :trevor)) %}
<!DOCTYPE html>
<html lang="en">
<head>
@@ 15,14 17,17 @@
<img class="logo" src="/logo.svg" />
<span>{{ (args :site-title) }}</span>
</a>
- {% (when (args :dev) %}
+ {% (when d %}
<input id="bmenub" type="checkbox" class="show">
<label for="bmenub" class="burger pseudo button">menu</label>
<div class="menu">
+ <button class="pseudo" _="on click call requestNotification()">Notify</button>
<a href="/__dashboard/edit?file={- (args :file) -}" class="pseudo button">Edit</a>
<a href="/__dashboard" class="pseudo button">Dashboard</a>
</div>
{% ) %}
</nav>
- <vstack spacing="xl" id="page">
+ <vstack spacing="xl" id="page"
+ {- (when (and t d) (. `hx-ws="connect:ws://` (t :host) ":" (t :port) `/"`)) -}>
+ <script id="notification"></script>
<vstack align-x="center">
A templates/notification.temple => templates/notification.temple +4 -0
@@ 0,0 1,4 @@
+<script id="notification">
+ new Notification('{{ (args :msg) }} redirecting there in one sec')
+ setTimeout(() => {window.location = '/{{ (args :location) }}'}, 1000)
+</script>