update examples

This commit is contained in:
Gered 2016-05-30 17:25:57 -04:00
parent 047db2e158
commit 391e8fe5af
8 changed files with 109 additions and 125 deletions

View file

@ -16,7 +16,7 @@
[reagent-data-views "0.2.0-SNAPSHOT"]
[reagent-data-views-browserchannel "0.1.0-SNAPSHOT"]
[clj-pebble "0.2.0"]
[hiccup "1.0.5"]
[reagent "0.6.0-alpha2"]
[cljsjs/bootstrap "3.3.6-1"]
[cljs-ajax "0.5.4"]
@ -33,8 +33,10 @@
[:cljsbuild :builds :main :compiler :output-to]]
:cljsbuild {:builds {:main
{:source-paths ["src"]
:compiler {:output-to "resources/public/cljs/app.js"
:compiler {:main class-registry.client
:output-to "resources/public/cljs/app.js"
:output-dir "resources/public/cljs/target"
:asset-path "cljs/target"
:source-map true
:optimizations :none
:pretty-print true}}}}

View file

@ -1,25 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Class Registry</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<!-- CSRF token that ring's anti-forgery middleware is expecting.
we pick it up in class-registry.client and add it to the headers
that cljs-ajax uses -->
<meta name="anti-forgery-token" content="{{ csrfToken }}">
</head>
<body>
<input type="hidden" id="anti-forgery-token" value="{{ csrfToken }}">
<div id="app"></div>
{% if dev %}<script type="text/javascript" src="cljs/target/goog/base.js"></script>{% endif %}
<script type="text/javascript" src="cljs/app.js"></script>
{% if dev %}<script type="text/javascript">goog.require('class_registry.client');</script>{% endif %}
<script type="text/javascript">
class_registry.client.run();
</script>
</body>
</html>

View file

@ -5,7 +5,7 @@
[ajax.core :refer [POST default-interceptors to-interceptor]]
[net.thegeez.browserchannel.client :as browserchannel]
[reagent-data-views.client.component :refer [view-cursor] :refer-macros [defvc]]
[reagent-data-views.browserchannel.client :as rdv-browserchannel]))
[reagent-data-views.browserchannel.client :as rdv]))
;; Class Registry - Reagent Data Views example app
;;
@ -361,8 +361,8 @@
(defn get-anti-forgery-token
[]
(if-let [tag (aget (.querySelectorAll js/document "meta[name='anti-forgery-token']") 0)]
(.-content tag)))
(if-let [hidden-field (.getElementById js/document "__anti-forgery-token")]
(.-value hidden-field)))
(def csrf-interceptor
(to-interceptor {:name "CSRF Interceptor"
@ -376,8 +376,7 @@
(defn ^:export run
[]
(enable-console-print!)
(rdv-browserchannel/configure!)
(browserchannel/connect! {} {:middleware [rdv-browserchannel/middleware]})
(rdv/configure!)
(browserchannel/connect! {} {:middleware [rdv/middleware]})
(r/render-component [class-registry-app] (.getElementById js/document "app")))

View file

@ -4,18 +4,19 @@
[compojure.core :refer [routes GET POST]]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
[ring.middleware.format :refer [wrap-restful-format]]
[ring.util.anti-forgery :refer [anti-forgery-field]]
[ring.util.response :refer [response]]
[net.thegeez.browserchannel.server :refer [wrap-browserchannel]]
[net.thegeez.browserchannel.immutant-async-adapter :refer [wrap-immutant-async-adapter]]
[immutant.web :as immutant]
[clj-pebble.core :as pebble]
[hiccup.page :refer [html5 include-css include-js]]
[hiccup.element :refer [javascript-tag]]
[environ.core :refer [env]]
[clojure.java.jdbc :as jdbc]
[views.sql.core :refer [vexec! with-view-transaction]]
[views.sql.view :refer [view]]
[reagent-data-views.browserchannel.server :as rdv-browserchannel]))
[reagent-data-views.browserchannel.server :as rdv]))
(def dev? (boolean (env :dev)))
@ -134,6 +135,25 @@
;; main page html
(defn render-page
[]
(html5
[:head
[:title "Class Registry"]
[:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
(include-css
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
"app.css")
(include-js "cljs/app.js")]
[:body
(anti-forgery-field)
[:div#app [:h1 "This will be replaced by the Class Registry app when the ClojureScript is compiled."]]
(javascript-tag "class_registry.client.run();")]))
;; Compojure routes and Ring handler
(def app-routes
@ -151,10 +171,7 @@
(POST "/registry/remove" [id] (remove-registration! id))
; main page
(GET "/" [] (pebble/render-resource
"html/app.html"
{:dev dev?
:csrfToken *anti-forgery-token*}))
(GET "/" [] (render-page))
(route/resources "/")
(route/not-found "not found")))
@ -163,19 +180,18 @@
(-> app-routes
(wrap-restful-format :formats [:transit-json])
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] (not dev?)))
(wrap-browserchannel {} {:middleware [(rdv-browserchannel/->middleware view-system)]})
(wrap-browserchannel {} {:middleware [(rdv/->middleware view-system)]})
(wrap-immutant-async-adapter)))
;; Web server startup & main
(defn run-server []
(pebble/set-options! :cache (not dev?))
(rdv-browserchannel/init-views! view-system {:views views})
(defn run-server
[]
(rdv/init-views! view-system {:views views})
(immutant/run handler {:port 8080}))
(defn -main [& args]
(defn -main
[& args]
(run-server))

View file

@ -8,18 +8,16 @@
[org.clojure/java.jdbc "0.6.1"]
[org.postgresql/postgresql "9.4.1208.jre7"]
[gered/clj-browserchannel "0.3.1"]
[gered/clj-browserchannel "0.3.2"]
[gered/clj-browserchannel-immutant-adapter "0.0.3"]
[gered/views "1.5-SNAPSHOT"]
[gered/views-sql "0.1.0-SNAPSHOT"]
[reagent-data-views "0.2.0-SNAPSHOT"]
[reagent-data-views-browserchannel "0.1.0-SNAPSHOT"]
[clj-pebble "0.2.0"]
[hiccup "1.0.5"]
[reagent "0.6.0-alpha2"]
[cljs-ajax "0.5.4"]
; only being used to get a <meta> tag value with the CSRF token in it
[prismatic/dommy "1.1.0"]
[environ "1.0.3"]]
@ -33,8 +31,10 @@
[:cljsbuild :builds :main :compiler :output-to]]
:cljsbuild {:builds {:main
{:source-paths ["src"]
:compiler {:output-to "resources/public/cljs/app.js"
:compiler {:main todomvc.client
:output-to "resources/public/cljs/app.js"
:output-dir "resources/public/cljs/target"
:asset-path "cljs/target"
:source-map true
:optimizations :none
:pretty-print true}}}}

View file

@ -1,26 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>todomvc with reagent</title>
<link rel="stylesheet" href="todos.css">
<link rel="stylesheet" href="todosanim.css">
<!-- include CSRF token that ring's anti-forgery middleware is expecting.
clj-browserchannel's client-side init will pick this meta tag up
automatically and include the token in all of browserchannel's
requests to the server. -->
<meta name="anti-forgery-token" content="{{ csrfToken }}">
</head>
<body>
<div id="app">
<h1>This will become todomvc when the ClojureScript is compiled</h1>
</div>
{% if dev %}<script type="text/javascript" src="cljs/target/goog/base.js"></script>{% endif %}
<script type="text/javascript" src="cljs/app.js"></script>
{% if dev %}<script type="text/javascript">goog.require('todomvc.client');</script>{% endif %}
<script type="text/javascript">
todomvc.client.run();
</script>
</body>
</html>

View file

@ -2,10 +2,9 @@
(:require
[reagent.core :as r]
[ajax.core :refer [POST default-interceptors to-interceptor]]
[dommy.core :refer-macros [sel1]]
[net.thegeez.browserchannel.client :as browserchannel]
[reagent-data-views.client.component :refer [view-cursor] :refer-macros [defvc]]
[reagent-data-views.browserchannel.client :as rdv-browserchannel]))
[reagent-data-views.browserchannel.client :as rdv]))
;; Todo MVC - Reagent Implementation
;;
@ -34,7 +33,8 @@
;; UI Components
(defn todo-input [{:keys [title on-save on-stop]}]
(defn todo-input
[{:keys [title on-save on-stop]}]
(let [val (r/atom title)
stop #(do (reset! val "")
(if on-stop (on-stop)))
@ -53,7 +53,8 @@
(def todo-edit (with-meta todo-input
{:component-did-mount #(.focus (r/dom-node %))}))
(defn todo-stats [{:keys [filt active done]}]
(defn todo-stats
[{:keys [filt active done]}]
(let [props-for (fn [name]
{:class (if (= name @filt) "selected")
:on-click #(reset! filt name)})]
@ -68,7 +69,8 @@
[:button#clear-completed {:on-click clear-done}
"Clear completed " done])]))
(defn todo-item []
(defn todo-item
[]
(let [editing (r/atom false)]
(fn [{:keys [id done title]}]
[:li {:class (str (if done "completed ")
@ -108,7 +110,8 @@
;; NOTE:
;; view-cursor cannot be used in a Reagent component that was created using defn.
(defvc todo-app [props]
(defvc todo-app
[props]
(let [filt (r/atom :all)]
(fn []
(let [items (view-cursor :todos)
@ -144,12 +147,12 @@
;; Some unfortunately necessary set up to ensure we send the CSRF token back with
;; AJAX requests (clj-browserchannel handles this automatically for it's own HTTP
;; requests, so the set up we do is only for our own application code).
;; AJAX requests
(defn get-anti-forgery-token []
(if-let [tag (sel1 "meta[name='anti-forgery-token']")]
(.-content tag)))
(defn get-anti-forgery-token
[]
(if-let [hidden-field (.getElementById js/document "__anti-forgery-token")]
(.-value hidden-field)))
(def csrf-interceptor
(to-interceptor {:name "CSRF Interceptor"
@ -161,9 +164,10 @@
;; Page load
(defn ^:export run []
(defn ^:export run
[]
; Configure reagent-data-views and then BrowserChannel.
(rdv-browserchannel/configure!)
(rdv/configure!)
; NOTE: We are passing in an empty map for the BrowserChannel event handlers only
; because this todo app is not using BrowserChannel for any purpose other
@ -171,6 +175,6 @@
; wanted to use it for client/server messaging in our application as well,
; we could pass in any event handlers we want here and it would not intefere
; with reagent-data-views.
(browserchannel/connect! {} {:middleware [rdv-browserchannel/middleware]})
(browserchannel/connect! {} {:middleware [rdv/middleware]})
(r/render-component [todo-app] (.getElementById js/document "app")))

View file

@ -4,17 +4,18 @@
[compojure.core :refer [routes GET POST]]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
[ring.util.anti-forgery :refer [anti-forgery-field]]
[ring.util.response :refer [response]]
[net.thegeez.browserchannel.server :refer [wrap-browserchannel]]
[net.thegeez.browserchannel.immutant-async-adapter :refer [wrap-immutant-async-adapter]]
[immutant.web :as immutant]
[clj-pebble.core :as pebble]
[hiccup.page :refer [html5 include-css include-js]]
[hiccup.element :refer [javascript-tag]]
[environ.core :refer [env]]
[clojure.java.jdbc :as jdbc]
[views.sql.core :refer [vexec! with-view-transaction]]
[views.sql.view :refer [view]]
[reagent-data-views.browserchannel.server :as rdv-browserchannel]))
[reagent-data-views.browserchannel.server :as rdv]))
(def dev? (boolean (env :dev)))
@ -28,14 +29,8 @@
;; View system atom
;;
;; We just declare it, don't need to fill it with anything. The call to views.core/init!
;; will handle initializing it (or reagent-data-views.browserchannel.server/init-views!
;; in this example app's case -- it works exactly the same and is a drop-in replacement
;; for views.core/init!)
;;
;; Depending on your exact needs, you can also opt to not pass in any atom to the init
;; call in which case one is created for you automatically. This may be more convenient
;; when using Component/Mount for example, but is entirely optional.
;; We just declare it, don't need to fill it with anything. The call below to
;; reagent-data-views.browserchannel.server/init-views! will take care of it.
(defonce view-system (atom {}))
@ -54,7 +49,8 @@
;; the actual SQL query and is followed by any number of parameters to be used in
;; the query.
(defn todos-list []
(defn todos-list
[]
["SELECT id, title, done FROM todos ORDER BY title"])
@ -83,19 +79,23 @@
;; analyzes the SQL query being run and dispatches "hints" to the view system which
;; trigger view refrehses for all subscribers of the views that the hints match.
(defn add-todo! [title]
(defn add-todo!
[title]
(vexec! view-system db ["INSERT INTO todos (title) VALUES (?)" title])
(response "ok"))
(defn delete-todo! [id]
(defn delete-todo!
[id]
(vexec! view-system db ["DELETE FROM todos WHERE id = ?" id])
(response "ok"))
(defn update-todo! [id title]
(defn update-todo!
[id title]
(vexec! view-system db ["UPDATE todos SET title = ? WHERE id = ?" title id])
(response "ok"))
(defn toggle-todo! [id]
(defn toggle-todo!
[id]
; note that a transaction is obviously not necessary here as we could have used
; just a single UPDATE query. however, it is being done this way to demonstrate
; using transactions with vexec!.
@ -106,16 +106,34 @@
(vexec! view-system dt ["UPDATE todos SET done = ? WHERE id = ?" (not done?) id]))
(response "ok")))
(defn mark-all! [done?]
(defn mark-all!
[done?]
(vexec! view-system db ["UPDATE todos SET done = ?" done?])
(response "ok"))
(defn delete-all-done! []
(defn delete-all-done!
[]
(vexec! view-system db ["DELETE FROM todos WHERE done = true"])
(response "ok"))
;; main page html
(defn render-page
[]
(html5
[:head
[:title "todomvc with reagent"]
(include-css "todos.css" "todosanim.css")
(include-js "cljs/app.js")]
[:body
(anti-forgery-field)
[:div#app [:h1 "This will become todomvc when the ClojureScript is compiled"]]
(javascript-tag "todomvc.client.run();")]))
;; Compojure routes and Ring handler
(def app-routes
@ -129,44 +147,40 @@
(POST "/todos/delete-all-done" [] (delete-all-done!))
; main page
(GET "/" [] (pebble/render-resource
"html/app.html"
{:dev dev?
:csrfToken *anti-forgery-token*}))
(GET "/" [] (render-page))
(route/resources "/")
(route/not-found "not found")))
(def handler
(-> app-routes
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] (not dev?)))
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] true #_(not dev?)))
; NOTE: We are passing in an empty map for the BrowserChannel event handlers only
; because this todo app is not using BrowserChannel for any purpose other
; then to provide client/server messaging for reagent-data-views. If we
; wanted to use it for client/server messaging in our application as well,
; we could pass in any event handlers we want here and it would not intefere
; with reagent-data-views.
(wrap-browserchannel {} {:middleware [(rdv-browserchannel/->middleware view-system)]})
(wrap-browserchannel {} {:middleware [(rdv/->middleware view-system)]})
(wrap-immutant-async-adapter)))
;; Web server startup & main
(defn run-server []
(pebble/set-options! :cache (not dev?))
; init-views! takes care of initialization views and reagent-data-views at the same
(defn run-server
[]
; init-views! takes care of initialization of views and reagent-data-views at the same
; time. As a result, we do not need to also call views.core/init! anywhere. The
; same arguments and options you are able to pass to views.core/init! can also be
; passed in here and they will be forwarded along, as this function is a drop-in
; replacement for views.core/init!.
;
; passed in here and they will be forwarded along, as this function is intended to be
; a drop-in replacement for views.core/init!.
; if you need to shutdown the views system (e.g. if you're using something like
; Component or Mount), you can just call views.core/shutdown!.
(rdv-browserchannel/init-views! view-system {:views views})
(rdv/init-views! view-system {:views views})
(immutant/run handler {:port 8080}))
(defn -main [& args]
(defn -main
[& args]
(run-server))