Merge pull request #45 from Day8/develop

Move to v0.3.1
This commit is contained in:
mike-thompson-day8 2015-04-17 23:11:25 +10:00
commit 192b93c9f6
10 changed files with 112 additions and 89 deletions

View File

@ -1,10 +1,22 @@
## v0.3.1 (2015-04-18)
Various small improvements and bug fixes:
- log-ex middleware added to core api (it was a mistake that it was missing)
- modest improves to simple example. Better comments, layout, etc.
- the anonymous functions in standard middleware now have meaningful
names, which makes stack traces easier to understand.
- #24 - Fix missing paren in README
- #31 - Fix list formatting in README
- #32 - fix a broken wiki link
- #30 - Fix up the enrich docstring
## v0.3.0 (2015-04-15) ## v0.3.0 (2015-04-15)
### Headline ### Headline
- the middleware `after` and `enrich` now call the supplied function `f` with - the middleware `after` and `enrich` now call the supplied function `f` with
both `db` and `v` (previously just `db`). Because javascript is so forgiving both `db` and `v` (previously just `db`). Because javascript is so forgiving
about function arity, this change is backwards compatible. about function arity, this change is backwards compatible.

View File

@ -670,7 +670,7 @@ Let's sketch out the situation described above ...
{:name "c" :val 23 :flag "y"}]) {:name "c" :val 23 :flag "y"}])
(def app-db (reagent/atom {:items L (def app-db (reagent/atom {:items L
:sort-by :name}) ;; sorted by the :name attribute :sort-by :name})) ;; sorted by the :name attribute
``` ```
The subscription-handler might be written: The subscription-handler might be written:
@ -897,7 +897,7 @@ Collectively, event handlers provide the control logic in a re-frame application
An event handler is a pure function of two parameters: An event handler is a pure function of two parameters:
1. current value in `app-db`. Note: that's the map **in** `app-db`, not the atom itself. 1. current value in `app-db`. Note: that's the map **in** `app-db`, not the atom itself.
2 an event (represented as a vector) 2. an event (represented as a vector)
It returns the new value which should be reset! into `app-db`. It returns the new value which should be reset! into `app-db`.

View File

@ -11,7 +11,9 @@
</div> </div>
<script src="target/client.js"></script> <script src="target/client.js"></script>
<script> <script>
simpleexample.core.run(); window.onload = function () {
simpleexample.core.run();
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -1,10 +1,10 @@
(defproject simple-re-frame "0.5.0-alpha3" (defproject simple-re-frame "0.5.0"
:dependencies [[org.clojure/clojure "1.6.0"] :dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-2816"] [org.clojure/clojurescript "0.0-2816"]
[reagent "0.5.0-alpha3"] [reagent "0.5.0"]
[re-frame "0.3.0"] [re-frame "0.3.1"]
[figwheel "0.2.3-SNAPSHOT"]] [figwheel "0.2.6"]]
:plugins [[lein-cljsbuild "1.0.4"] :plugins [[lein-cljsbuild "1.0.4"]
[lein-figwheel "0.2.3-SNAPSHOT"]] [lein-figwheel "0.2.3-SNAPSHOT"]]

View File

@ -5,101 +5,110 @@
path path
register-sub register-sub
dispatch dispatch
dispatch-sync
subscribe]])) subscribe]]))
;; trigger a dispatch every second
(defonce time-updater (js/setInterval (defonce time-updater (js/setInterval
#(dispatch [:timer (js/Date.)]) 1000)) #(dispatch [:timer (js/Date.)]) 1000))
;;; this is the initial state (def initial-state
(defonce initial-state
{:timer (js/Date.) {:timer (js/Date.)
:time-color "#f34"}) :time-color "#f34"})
;; Handlers
;-------------------------------------------------------------
;; This handler sets the initial state ;; -- Event Handlers ----------------------------------------------------------
(register-handler
;; the handler is passed a map (not an atom) and must return the new state
;; of the db (register-handler ;; setup initial state
:initialize :initialize ;; usage: (submit [:initialize])
(fn (fn
[db _] [db _]
(merge db initial-state))) (merge db initial-state))) ;; what it returns becomes the new state
;; This handler changes the color of the displayed time
(register-handler (register-handler
;;; register-handler can take 3 arguments to allow you to insert middleware :time-color ;; usage: (submit [:time-color 34562])
;;; see https://github.com/Day8/re-frame/wiki/Handler-Middleware (path [:time-color]) ;; this is middleware
:time-color
(path [:time-color])
(fn (fn
;; the path handler allows you to get directly to items in the database [time-color [_ value]] ;; path middleware adjusts the first parameter
;; return the value you want assoc'd in
[time-color [_ value]]
value)) value))
;; This handler changes the value of the time
(register-handler (register-handler
:timer :timer
(fn (fn
;; the first item in the second argument is :timer the second is the ;; the first item in the second argument is :timer the second is the
;; new value ;; new value
[db [_ value]] [db [_ value]]
(assoc db :timer value))) (assoc db :timer value))) ;; return the new version of db
;; -- Subscription Handlers ---------------------------------------------------
;; add subscriptions to :timer and :time-color
(register-sub (register-sub
:timer :timer
(fn (fn
[db _] [db _] ;; db is the app-db atom
;; you need to wrap your subscription code in a reaction (reaction (:timer @db)))) ;; wrap the compitation in a reaction
(reaction (:timer @db))))
(register-sub (register-sub
:time-color :time-color
(fn (fn
[db _] [db _]
;; you need to wrap your subscription code in a reaction
(reaction (:time-color @db)))) (reaction (:time-color @db))))
(dispatch [:initialize])
;; -- View Components ---------------------------------------------------------
(defn greeting [message] (defn greeting
[message]
[:h1 message]) [:h1 message])
(defn clock []
(defn clock
[]
(let [time-color (subscribe [:time-color]) (let [time-color (subscribe [:time-color])
timer (subscribe [:timer])] timer (subscribe [:timer])]
;;; wrap your component in a function to use the suscription
(fn []
;; note that the initialize call will not be dispatched immediately
;; as it is an async call
(when @timer
(let [time-str (-> @timer .toTimeString (clojure.string/split " ") first)]
[:div.example-clock
{:style {:color @time-color}}
time-str])))))
(defn color-input [] (fn clock-render
[]
(let [time-str (-> @timer
.toTimeString
(clojure.string/split " ")
first)
style {:style {:color @time-color}}]
[:div.example-clock style time-str]))))
(defn color-input
[]
(let [time-color (subscribe [:time-color])] (let [time-color (subscribe [:time-color])]
;;; wrap your component in a function to use the suscription
(fn []
[:div.color-input
"Time color: "
[:input {:type "text"
:value @time-color
:on-change #(dispatch
[:time-color (-> % .-target .-value)])}]])))
(defn simple-example [] (fn color-input-render
[]
[:div.color-input
"Time color: "
[:input {:type "text"
:value @time-color
:on-change #(dispatch
[:time-color (-> % .-target .-value)])}]])))
(defn simple-example
[]
[:div [:div
[greeting "Hello world, it is now"] [greeting "Hello world, it is now"]
[clock] [clock]
[color-input]]) [color-input]])
(defn ^:export run []
;; -- Entry Point -------------------------------------------------------------
(defn ^:export run
[]
(dispatch-sync [:initialize])
(reagent/render [simple-example] (reagent/render [simple-example]
(js/document.getElementById "app"))) (js/document.getElementById "app")))

View File

@ -1,8 +1,8 @@
(defproject todomvc-re-frame "0.3.0" (defproject todomvc-re-frame "0.3.1"
:dependencies [[org.clojure/clojure "1.6.0"] :dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-2816"] [org.clojure/clojurescript "0.0-2816"]
[reagent "0.5.0"] [reagent "0.5.0"]
[re-frame "0.3.0"] [re-frame "0.3.1"]
[secretary "1.2.1"]] [secretary "1.2.1"]]
:plugins [[lein-cljsbuild "1.0.4"]] :plugins [[lein-cljsbuild "1.0.4"]]

View File

@ -7,17 +7,17 @@
(defn filter-fn-for (defn filter-fn-for
[showing-kw] [showing-kw]
(case showing-kw (case showing-kw
:active (complement :done) :active (complement :done)
:done :done :done :done
:all identity)) :all identity))
(defn completed-count (defn completed-count
"return the count of todos for which :done is true" "return the count of todos for which :done is true"
[todos] [todos]
(count (filter :done (vals todos)))) (count (filter :done (vals todos))))
;; -- Subscription handlers and registration --------------------------------- ;; -- Subscription handlers and registration ---------------------------------
@ -25,26 +25,26 @@
(register-sub (register-sub
:todos ;; usage: (subscribe [:todos]) :todos ;; usage: (subscribe [:todos])
(fn [db _] (fn [db _]
(reaction (vals (:todos @db))))) (reaction (vals (:todos @db)))))
(register-sub (register-sub
:visible-todos :visible-todos
(fn [db _] (fn [db _]
(reaction (let [filter-fn (filter-fn-for (:showing @db)) (reaction (let [filter-fn (filter-fn-for (:showing @db))
todos (vals (:todos @db))] todos (vals (:todos @db))]
(filter filter-fn todos))))) (filter filter-fn todos)))))
(register-sub (register-sub
:completed-count :completed-count
(fn [db _] (fn [db _]
(reaction (completed-count (:todos @db))))) (reaction (completed-count (:todos @db)))))
(register-sub (register-sub
:footer-stats :footer-stats
(fn [db _] (fn [db _]
(reaction (reaction
(let [todos (:todos @db) (let [todos (:todos @db)
completed-count (completed-count todos) completed-count (completed-count todos)
active-count (- (count todos) completed-count) active-count (- (count todos) completed-count)
showing (:showing @db)] showing (:showing @db)]
[active-count completed-count showing])))) ;; tuple [active-count completed-count showing])))) ;; tuple

View File

@ -1,4 +1,4 @@
(defproject re-frame "0.3.0" (defproject re-frame "0.3.1"
:description "A Clojurescript MVC-like Framework For Writing SPAs Using Regent." :description "A Clojurescript MVC-like Framework For Writing SPAs Using Regent."
:url "https://github.com/Day8/re-frame.git" :url "https://github.com/Day8/re-frame.git"
:license {:name "MIT"} :license {:name "MIT"}

View File

@ -23,14 +23,14 @@
(def enrich middleware/enrich) (def enrich middleware/enrich)
(def trim-v middleware/trim-v) (def trim-v middleware/trim-v)
(def after middleware/after) (def after middleware/after)
; (def log-events middleware/log-events) (def log-ex middleware/log-ex)
;; -- Convenience API ------- ;; -- Convenience API -------
;; Almost 100% of handlers will be pure, so make it easy to ;; Almost 100% of handlers will be pure, so make it easy to
;; register with "pure" middleware in the correct position. ;; register with "pure" middleware in the correct (left-hand-side) position.
(defn register-handler (defn register-handler
([id handler] ([id handler]
(handlers/register-base id pure handler)) (handlers/register-base id pure handler))

View File

@ -82,7 +82,7 @@
....) ....)
" "
[handler] [handler]
(fn new-handler (fn trim-v-handler
[db v] [db v]
(handler db (vec (rest v))))) (handler db (vec (rest v)))))
@ -140,16 +140,16 @@
complete reassesment of duplication errors and warnings. Eg: that edit complete reassesment of duplication errors and warnings. Eg: that edit
update might have introduced a new duplicate or removed one. Same with a update might have introduced a new duplicate or removed one. Same with a
todo removal. todo removal.
And to perform this enrichment, a function has inspect all the todos, And to perform this enrichment, a function has to inspect all the todos,
possibly set flags on each, and set some overall list of duplicates. possibly set flags on each, and set some overall list of duplicates.
And this duplicates checking might be just one check amoung a number. And this duplication check might just be one check amoung many.
\"f\" would need to be both adding and removing the duplicate warnings. \"f\" would need to be both adding and removing the duplicate warnings.
By applying \"f\" in middleware, we keep the handlers simple and yet we By applying \"f\" in middleware, we keep the handlers simple and yet we
ensure this important step is not missed. " ensure this important step is not missed."
[f] [f]
(fn middleware (fn middleware
[handler] [handler]
(fn validate-handler (fn enrich-handler
[db v] [db v]
(f (handler db v) v)))) (f (handler db v) v))))