Skip to content

Commit

Permalink
New clojurescript app stuff, bump to 0.5.0
Browse files Browse the repository at this point in the history
* New syntax for clojurescript apps
* Update lein-template nsfw version
* Update lien-template to use new cs :entry config opt
  • Loading branch information
zk committed Mar 6, 2013
1 parent 9d68a67 commit 9642be0
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 35 deletions.
114 changes: 114 additions & 0 deletions .notes.zk.org
Expand Up @@ -850,4 +850,118 @@ Responsive design.
Box sizing: http://paulirish.com/2012/box-sizing-border-box-ftw/


* 2013-03-04 Mon 18:13

With routes, there should be some common setup, init routes which
watches for changes on the hash and loads new content when the page
changes.

Challenges: How is global set up handled?

The idea is:

1. There's some common page setup, maybe initialization of query
services, polling, websockets connections, whatever. Stuff that's
common to the entire lifecycle of the app.

2. There's per-route setup.


Q: what's the right level of setup done by the initial page load / vs
subsequent js 'page' changes. Should be as easy to make single page
apps as it is to make more traditional 'dynamically enhanced' apps.

What's this mean for routing? Seems like a lot of bookkeeping you have
to do manually.

I'm worried that the overhead of shipping an entire app in one js page
might not be feasable, even with dead code removal.

Maybe I should be opinionated here -- There's one backend route that
ships the entire application, and all other routes are api routes.

I'm pretty comfortable with that for now. Clojurescript app at
root. What about the loader script?

Since we put js tags in the body, the initial page load structure
should ship the loading screen, then get wiped out as a first action
by the javascript. So, we need to have a nice way of providing the
loading screen. Let's look at that now. `webapp.cs` should default to
a nice nsfw loading screen, with the ability to override.

Ok, so now we're shipping a loading screen, but the jump is pretty
jarring. Fade out / fade in? Also, if you're dynamically loading data
in the background that's two jumps. Perhaps a way to signal that the
initial UI is ready to be viewed?

Meh, I'm on the fence on this. It's nice to have the animated
transition, but it's clear that the transition should only happen on
initial page load. Also, maybe it should only load if the :loading
opt is set on `webapp/cs`. If this is the case, then we'll need to
provide some page load helper. So what goes into page load?

+ Getting a handle on data injected into the page
+ Initial js transfer and load.
+ Initial background color for load

Looks like we need to make some state available for the page. This
feels good though, we're starting at the beginning.

JHC just spent the last hour tracking down an Undefined Identifier
error, no line number. Ended up being I was passing in something to
util/timeout without wrapping it in a function first. AARRRGGGGHHH.

Ok so it looks like loading is a non-issue, it dosen't seem like
there's a reliable way to get some page content to load before the js
anyway, so any HTML shipped wouldn't show anyway. It's important to
keep the js as small as possible though, so that's something I'll have
to make easy. Revised initial stuff below:

+ Initial background color for load
+ Getting a handle on data injected into the page
+ Initial js transfer and load.


Order of ops
+ Request comes in
+ One route for the app
+ Load the


+ App Setup
+ Clojurescript app
+ Session storage
+ entry ns
+ route handling
+ css
+ extra js
+ handles all traffic (push state)
+ has the ability to pretty seriously break 404, as all your
routes will resolve as a 200 now. Perhaps can handle this with a
route whitelist, patterns of valid pages.
+ API slug, everything there is handled by api routes



** New clojurescript app syntax

#+begin_src clojure

(def routes
(app/clojurescript
:session-atom session-atom
:entry 'bigboard.app/entry
:css [:bootstrap.min :bootstrap-responsive.min :app]
:data (fn [r]
{:issues (take 10 @!gh-issues)
:user (when-let [gh-user (-> r :session :gh-user)] gh-user)})
:api (app/route
["label-ac"] (label-ac !gh-issues !gh-labels)
["issues" number] {:post (post-issue !gh-issues number)}
["issues"] (fn [{:keys [params]}]
(let [{:keys [d t] :or {d 0 t 10}} params]
{:body (pr-str (->> @!gh-issues
(drop (nu/parse-int d))
(take (nu/parse-int t))))})))))

#+end_src
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -4,6 +4,20 @@ Proving ground for library code.

[![Build Status](https://travis-ci.org/zkim/nsfw.png)](https://travis-ci.org/zkim/nsfw)

## Usage

`lein new nsfw <project name>`

If you get:

```bash
Retrieving nsfw/lein-template/maven-metadata.xml (1k)
from http://clojars.org/repo/
Could not find metadata nsfw:lein-template/maven-metadata.xml in central (http://repo1.maven.org/maven2)
```

Just `rm -rf ./<project dir>` and try again.

## License

Copyright (C) 2010-2012 Zachary Kim
Expand Down
12 changes: 12 additions & 0 deletions bin/local-deploy
@@ -0,0 +1,12 @@
#!/bin/bash

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

REPO=$SCRIPT_DIR/..

cd $SCRIPT_DIR/.. && lein install


REPO=$SCRIPT_DIR/../lein-template

cd $REPO && lein install
6 changes: 3 additions & 3 deletions lein-template/src/leiningen/new/nsfw.clj
Expand Up @@ -16,6 +16,6 @@
["src/clj/{{sanitized}}/run.clj" (render "run.clj" data)]
["src/clj/{{sanitized}}/entry.clj" (render "entry.clj" data)]
["src/cljs/{{sanitized}}/app.cljs" (render "app.cljs" data)]
["src/sass/app.scss" (render "app.scss" data)]
["resources/public/css/bootstrap-responsive.min.css" (render "bootstrap-responsive.min.css" data)]
["resources/public/css/bootstrap.min.css" (render "bootstrap.min.css" data)])))
["src/scss/app.scss" (render "app.scss" data)]
["src/scss/nsfw.scss" (render "nsfw.scss" data)]
["README.md" (render "README.md" data)])))
4 changes: 2 additions & 2 deletions lein-template/src/leiningen/new/nsfw/Procfile
@@ -1,4 +1,4 @@
web: lein run -m {{name}}.run
cljs: lein cljsbuild auto
sass: sass --watch src/sass:resources/public/css
cljs: lein cljsbuild auto dev
sass: sass --watch src/scss:resources/public/css
refresher: lein run -m nsfw.refresher
18 changes: 10 additions & 8 deletions lein-template/src/leiningen/new/nsfw/app.cljs
Expand Up @@ -6,11 +6,13 @@

(def $body (dom/$ "body"))

(dom/append
$body
[:div
[:h1 "Hello {{name}}"]
[:p
"This file can be found at " [:code "src/cljs/{{sanitized}}/app.cljs"] ". "
"Any changes to this file (and any other cljs files) will automatically be "
"reloaded in your browser."]])
(def $page
[:div
[:h1 "Hello {{name}}."]
[:p
"This file can be found at " [:code "src/cljs/{{sanitized}}/app.cljs"] ". "
"Any changes to this file (and any other cljs files) will automatically be "
"reloaded in your browser."]])

(defn entry []
(dom/append $body $page))
4 changes: 2 additions & 2 deletions lein-template/src/leiningen/new/nsfw/build
@@ -1,4 +1,4 @@
#!/bin/sh

lein cljsbuild once
lein with-profile production compile :all
lein cljsbuild once prod
lein with-profile production compile :all
21 changes: 14 additions & 7 deletions lein-template/src/leiningen/new/nsfw/entry.clj
@@ -1,9 +1,16 @@
(ns {{name}}.entry
(:require [nsfw.webapp :as webapp]))
(:require [nsfw.app :as app]))

(def routes
(webapp/routes
[""] (webapp/cs :app
:css [:bootstrap.min
:bootstrap-responsive.min
:app])))
(defonce session (app/session-store :encrypted-cookie))

(def app
(app/clojurescript
:entry '{{name}}.app/entry
:session-store session
:css [:nsfw :app]
:data (fn [r]
;; Key / val pairs are embedded into the page as js vars
{:unique-value (str (gensym))})
:api (app/route
;; Routes mounted at /api
["name"] (fn [r] {:body (pr-str (rand))}))))
1 change: 1 addition & 0 deletions lein-template/src/leiningen/new/nsfw/nsfw.scss
17 changes: 12 additions & 5 deletions lein-template/src/leiningen/new/nsfw/project.clj
Expand Up @@ -2,12 +2,19 @@
:description "A Clojure web app using NSFW."
:min-lein-version "2"
:dependencies [[org.clojure/clojure "1.4.0"]
[nsfw "0.4.3"]]
[nsfw "0.5.0"]]
:source-paths ["src/clj"]
:test-paths ["test/clj"]
:plugins [[lein-cljsbuild "0.2.10"]]
:cljsbuild {:builds
[{:source-path "src/cljs"
:compiler {:output-to "resources/public/js/app.js"
:optimizations :whitespace}
:jar true}]})
{:dev {:source-path "src/cljs"
:compiler {:output-to "resources/public/js/app.js"
:optimizations :whitespace
:pretty-print true}
:jar true}

:prod {:source-path "src/cljs"
:compiler {:output-to "resources/public/js/app.js"
:optimizations :advanced
:pretty-print false}
:jar true}}})
2 changes: 1 addition & 1 deletion lein-template/src/leiningen/new/nsfw/run.clj
Expand Up @@ -9,7 +9,7 @@
(repl/start-server :port port))

(def root-entry
(-> #'entry/routes
(-> #'entry/app
(reload/wrap-reload-modified ["src/clj"])))

(defn -main [& args]
Expand Down
3 changes: 2 additions & 1 deletion project.clj
@@ -1,4 +1,4 @@
(defproject nsfw "0.4.4"
(defproject nsfw "0.5.0"
:description "No Such Framework -- Experimental"
:dependencies [[org.clojure/clojure "1.4.0"]
[clj-stacktrace "0.2.5"]
Expand All @@ -21,6 +21,7 @@
:source-paths ["src/clj" "examples/clj"]
:test-paths ["test/clj"]
:jar-name "nsfw.jar"
:hooks [leiningen.cljsbuild]
:cljsbuild {:builds
[{:source-path "src/cljs"
:compiler {:output-to "resources/test.js"
Expand Down
2 changes: 1 addition & 1 deletion site
Submodule site updated from d67b17 to 1c7390
15 changes: 14 additions & 1 deletion src/clj/nsfw/app.clj
Expand Up @@ -2,7 +2,8 @@
(:use [nsfw.util]
(ring.middleware file file-info resource params nested-params
keyword-params multipart-params session)
[ring.middleware.session.memory :only (memory-store)])
[ring.middleware.session.memory :only (memory-store)]
[ring.middleware.session.cookie :only (cookie-store)])
(:require [net.cgrand.moustache :as moustache]
[nsfw.html :as html]
[nsfw.middleware :as nm]
Expand Down Expand Up @@ -56,6 +57,18 @@
[:script {:type "text/javascript"}
(str entry-js "()")])])})))

(defn session-store
[type & rest]
(condp = type
:atom (if-not (empty? rest)
(memory-store (first rest))
(memory-store))

;; encrypted cookie
(if-not (empty? rest)
(cookie-store (first rest))
(cookie-store))))

(defmacro route [& routes]
`(moustache/app ~@routes))

Expand Down
18 changes: 18 additions & 0 deletions src/cljs/nsfw/console.cljs
Expand Up @@ -117,3 +117,21 @@
(apply str))]
(render-result data)]))))))
$el))

(defn on-cmd-space [el f]
(dom/keydown
js/document
(fn [{:keys [key-code meta-key ctrl-key] :as e}]
(when (and (= 32 key-code)
meta-key)
(f e)))))

(defn panel []
(let [el (dom/$ [:div.console-panel "COMMAND PANEL"])
toggle (util/toggle
#(dom/style el {:display "block"})
#(dom/style el {:display "none"}))]
(on-cmd-space
el
toggle)
el))
10 changes: 6 additions & 4 deletions src/cljs/nsfw/dom.cljs
Expand Up @@ -343,7 +343,9 @@
(if-not so
(conj out fo)
(recur (rest os)
(conj out (assoc fo :done (fn []
((or (:done fo) #()))
(trans* el so))))))))]
(trans* el (first os))))
(conj out (assoc fo
:done (fn []
((or (:done fo) #()))
(trans* el so))))))))]
(trans* el (first os))
el))

0 comments on commit 9642be0

Please sign in to comment.