Removed undo functionality as it is not handled in day8.re-frame/undo
This commit is contained in:
parent
17a4fb8f5a
commit
faae34822c
|
@ -5,7 +5,6 @@
|
|||
[re-frame.fx :as fx]
|
||||
[re-frame.router :as router]
|
||||
[re-frame.loggers :as loggers]
|
||||
[re-frame.undo :as undo]
|
||||
[re-frame.middleware :as middleware]))
|
||||
|
||||
|
||||
|
@ -56,13 +55,6 @@
|
|||
(events/register-base id [fx middleware] handler)))
|
||||
|
||||
|
||||
;; -- Undo API -----
|
||||
;; The docs are here: https://github.com/Day8/re-frame/wiki/Undo-&-Redo
|
||||
|
||||
(def undoable undo/undoable)
|
||||
(def undo-config! undo/undo-config!)
|
||||
|
||||
|
||||
;; -- Logging -----
|
||||
;; Internally, re-frame uses the logging functions: warn, log, error, group and groupEnd
|
||||
;; By default, these functions map directly to the js/console implementations,
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
(ns re-frame.core
|
||||
(:require
|
||||
[re-frame.events :as events]
|
||||
[re-frame.subs :as subs]
|
||||
[re-frame.fx :as fx]
|
||||
[re-frame.router :as router]
|
||||
[re-frame.loggers :as loggers]
|
||||
[re-frame.middleware :as middleware]))
|
||||
|
||||
|
||||
;; -- dispatch
|
||||
(def dispatch router/dispatch)
|
||||
(def dispatch-sync router/dispatch-sync)
|
||||
|
||||
|
||||
;; -- subscribe
|
||||
(def def-sub-raw subs/register)
|
||||
(def def-sub subs/register-pure)
|
||||
(def clear-all-subs! subs/clear-all-handlers!)
|
||||
(def subscribe subs/subscribe)
|
||||
|
||||
;; -- effects
|
||||
(def def-fx fx/register)
|
||||
(def clear-fx! fx/clear-handler!)
|
||||
(def clear-all-fx! fx/clear-all-handlers!)
|
||||
|
||||
|
||||
;; -- middleware
|
||||
(def pure middleware/pure)
|
||||
(def fx fx/fx)
|
||||
(def debug middleware/debug)
|
||||
(def path middleware/path)
|
||||
(def enrich middleware/enrich)
|
||||
(def trim-v middleware/trim-v)
|
||||
(def after middleware/after)
|
||||
(def on-changes middleware/on-changes)
|
||||
|
||||
;; -- Events
|
||||
(def clear-all-events! events/clear-all-handlers!)
|
||||
(def clear-event! events/clear-handler!)
|
||||
|
||||
;; Registers a pure event handler. Places pure middleware in the correct, LHS position.
|
||||
(defn def-event
|
||||
([id handler]
|
||||
(events/register-base id pure handler))
|
||||
([id middleware handler]
|
||||
(events/register-base id [pure middleware] handler)))
|
||||
|
||||
|
||||
;; Registers an effectful event handler. Places fx middleware in the correct, LHS position.
|
||||
(defn def-event-fx
|
||||
([id handler]
|
||||
(events/register-base id fx handler))
|
||||
([id middleware handler]
|
||||
(events/register-base id [fx middleware] handler)))
|
||||
|
||||
|
||||
; ;; -- Undo API -----
|
||||
; ;; The docs are here: https://github.com/Day8/re-frame/wiki/Undo-&-Redo
|
||||
|
||||
; (def undoable undo/undoable)
|
||||
; (def undo-config! undo/undo-config!)
|
||||
|
||||
|
||||
;; -- Logging -----
|
||||
;; Internally, re-frame uses the logging functions: warn, log, error, group and groupEnd
|
||||
;; By default, these functions map directly to the js/console implementations,
|
||||
;; but you can override with your own fns (set or subset).
|
||||
;; Example Usage:
|
||||
;; (defn my-fn [& args] (post-it-somewhere (apply str args)))
|
||||
;; (re-frame.core/set-loggers! {:warn my-fn :log my-fn}) ;; I should override the rest of them too.
|
||||
(def set-loggers! loggers/set-loggers!)
|
||||
|
||||
;; If you are writing an extension to re-frame, like perhaps
|
||||
;; an effeects handler, you may want to use re-frame logging.
|
||||
;;
|
||||
;; usage: (console :error "this is bad: " a-variable " and " anotherv)
|
||||
;; (console :warn "possible breach of containment wall at: " dt)
|
||||
(def console loggers/console)
|
||||
|
||||
|
||||
;; -- Event Procssing Callbacks
|
||||
|
||||
(defn add-post-event-callback
|
||||
"Registers a callback function 'f'.
|
||||
f will be called after each dispatched event is procecessed
|
||||
f will be called with two arguments:
|
||||
- the event's vector. That which was dispatched orignally.
|
||||
- the further event queue - what is still to be processed. A PersistentQueue.
|
||||
|
||||
This is useful in advanced cases like:
|
||||
- you are implementing a complex bootstrap pipeline
|
||||
- you want to create your own handling infrastructure, with perhaps multiple
|
||||
handlers for the one event, etc. Hook in here.
|
||||
- libraries providing 'isomorphic javascript' rendering on Nodejs or Nashorn.
|
||||
"
|
||||
[f]
|
||||
(router/add-post-event-callback re-frame.router/event-queue f))
|
||||
|
||||
|
||||
(defn remove-post-event-callback
|
||||
[f]
|
||||
(router/remove-post-event-callback re-frame.router/event-queue f))
|
|
@ -40,10 +40,6 @@
|
|||
;; when this reaction is nolonger being used, remove it from the cache
|
||||
(add-on-dispose! r #(do (swap! query->reaction dissoc cache-key)
|
||||
(console :log "Removing subscription: " cache-key)))
|
||||
|
||||
(console :log "Dispatch site: ")
|
||||
(console :log (:dispatch-site (meta query-v)))
|
||||
|
||||
;; cache this reaction, so it can be used to deduplicate other, identical subscriptions
|
||||
(swap! query->reaction assoc cache-key r)
|
||||
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
(ns re-frame.undo
|
||||
(:require
|
||||
[re-frame.loggers :refer [console]]
|
||||
[re-frame.db :refer [app-db]]
|
||||
[re-frame.events :as handlers]
|
||||
[re-frame.interop :refer [make-reaction ratom]]
|
||||
[re-frame.subs :as subs]))
|
||||
|
||||
|
||||
;; background docs: https://github.com/Day8/re-frame/wiki/Undo-&-Red
|
||||
|
||||
|
||||
;; -- Configuration ----------------------------------------------------------
|
||||
|
||||
(def ^:private config (atom {:max-undos 50 ;; Maximum number of undo states maintained
|
||||
:harvest-fn deref
|
||||
:reinstate-fn reset!}))
|
||||
|
||||
(defn undo-config!
|
||||
[new-config]
|
||||
(if-let [unknown-keys (seq (clojure.set/difference (-> new-config keys set) (-> @config keys set)))]
|
||||
(console :warn "re-frame: you called undo-config! within unknown keys: " unknown-keys)
|
||||
(swap! config merge new-config)))
|
||||
|
||||
|
||||
(defn- max-undos
|
||||
[]
|
||||
(:max-undos @config))
|
||||
|
||||
|
||||
|
||||
;; -- State history ----------------------------------------------------------
|
||||
|
||||
(def ^:private undo-list "A list of history states" (ratom []))
|
||||
(def ^:private redo-list "A list of future states, caused by undoing" (ratom []))
|
||||
|
||||
;; -- Explanations -----------------------------------------------------------
|
||||
;;
|
||||
;; Each undo has an associated explanation which can be displayed to the user.
|
||||
;;
|
||||
;; Seems really ugly to have mirrored vectors, but ...
|
||||
;; the code kinda falls out when you do. I'm feeling lazy.
|
||||
(def ^:private app-explain "Mirrors app-db" (ratom ""))
|
||||
(def ^:private undo-explain-list "Mirrors undo-list" (ratom []))
|
||||
(def ^:private redo-explain-list "Mirrors redo-list" (ratom []))
|
||||
|
||||
(defn- clear-undos!
|
||||
[]
|
||||
(reset! undo-list [])
|
||||
(reset! undo-explain-list []))
|
||||
|
||||
|
||||
(defn- clear-redos!
|
||||
[]
|
||||
(reset! redo-list [])
|
||||
(reset! redo-explain-list []))
|
||||
|
||||
|
||||
(defn clear-history!
|
||||
[]
|
||||
(clear-undos!)
|
||||
(clear-redos!)
|
||||
(reset! app-explain ""))
|
||||
|
||||
|
||||
(defn store-now!
|
||||
"Stores the value currently in app-db, so the user can later undo"
|
||||
[explanation]
|
||||
(clear-redos!)
|
||||
(reset! undo-list (vec (take-last
|
||||
(max-undos)
|
||||
(conj @undo-list ((:harvest-fn @config) app-db)))))
|
||||
(reset! undo-explain-list (vec (take-last
|
||||
(max-undos)
|
||||
(conj @undo-explain-list @app-explain))))
|
||||
(reset! app-explain explanation))
|
||||
|
||||
|
||||
(defn undos?
|
||||
"Returns true if undos exist, false otherwise"
|
||||
[]
|
||||
(seq @undo-list))
|
||||
|
||||
(defn redos?
|
||||
"Returns true if redos exist, false otherwise"
|
||||
[]
|
||||
(seq @redo-list))
|
||||
|
||||
(defn undo-explanations
|
||||
"Returns a vector of undo descriptions, perhaps empty"
|
||||
[]
|
||||
(if (undos?)
|
||||
(conj @undo-explain-list @app-explain)
|
||||
[]))
|
||||
|
||||
;; -- subscriptions -----------------------------------------------------------------------------
|
||||
|
||||
(subs/register
|
||||
:undos? ;; usage: (subscribe [:undos?])
|
||||
(fn handler
|
||||
; "returns true if anything is stored in the undo list, otherwise false"
|
||||
[_ _]
|
||||
(make-reaction undos?)))
|
||||
|
||||
(subs/register
|
||||
:redos?
|
||||
(fn handler
|
||||
; "returns true if anything is stored in the redo list, otherwise false"
|
||||
[_ _]
|
||||
(make-reaction redos?)))
|
||||
|
||||
|
||||
(subs/register
|
||||
:undo-explanations
|
||||
(fn handler
|
||||
; "returns a vector of string explanations ordered oldest to most recent"
|
||||
[_ _]
|
||||
(make-reaction undo-explanations)))
|
||||
|
||||
(subs/register
|
||||
:redo-explanations
|
||||
(fn handler
|
||||
; "returns a vector of string explanations ordered from most recent undo onward"
|
||||
[_ _]
|
||||
(make-reaction #(deref redo-explain-list))))
|
||||
|
||||
;; -- event handlers ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
(defn- undo
|
||||
[harvester reinstater undos cur redos]
|
||||
(let [u @undos
|
||||
r (cons (harvester cur) @redos)]
|
||||
(reinstater cur (last u))
|
||||
(reset! redos r)
|
||||
(reset! undos (pop u))))
|
||||
|
||||
|
||||
(defn- undo-n
|
||||
"undo n steps or until we run out of undos"
|
||||
[n]
|
||||
(when (and (pos? n) (undos?))
|
||||
(undo (:harvest-fn @config) (:reinstate-fn @config) undo-list app-db redo-list)
|
||||
(undo deref reset! undo-explain-list app-explain redo-explain-list)
|
||||
(recur (dec n))))
|
||||
|
||||
(handlers/register-base ;; not a pure handler
|
||||
:undo ;; usage: (dispatch [:undo n]) n is optional, defaults to 1
|
||||
(fn handler
|
||||
[_ [_ n]]
|
||||
(if-not (undos?)
|
||||
(console :warn "re-frame: you did a (dispatch [:undo]), but there is nothing to undo.")
|
||||
(undo-n (or n 1)))))
|
||||
|
||||
|
||||
(defn- redo
|
||||
[harvester reinstater undos cur redos]
|
||||
(let [u (conj @undos (harvester cur))
|
||||
r @redos]
|
||||
(reinstater cur (first r))
|
||||
(reset! redos (rest r))
|
||||
(reset! undos u)))
|
||||
|
||||
(defn- redo-n
|
||||
"redo n steps or until we run out of redos"
|
||||
[n]
|
||||
(when (and (pos? n) (redos?))
|
||||
(redo (:harvest-fn @config) (:reinstate-fn @config) undo-list app-db redo-list)
|
||||
(redo deref reset! undo-explain-list app-explain redo-explain-list)
|
||||
(recur (dec n))))
|
||||
|
||||
(handlers/register-base ;; not a pure handler
|
||||
:redo ;; usage: (dispatch [:redo n])
|
||||
(fn handler ;; if n absent, defaults to 1
|
||||
[_ [_ n]]
|
||||
(if-not (redos?)
|
||||
(console :warn "re-frame: you did a (dispatch [:redo]), but there is nothing to redo.")
|
||||
(redo-n (or n 1)))))
|
||||
|
||||
(handlers/register-base ;; not a pure handler
|
||||
:purge-redos ;; usage: (dispatch [:purge-redos])
|
||||
(fn handler
|
||||
[_ _]
|
||||
(if-not (redos?)
|
||||
(console :warn "re-frame: you did a (dispatch [:purge-redos]), but there is nothing to redo.")
|
||||
(clear-redos!))))
|
||||
|
||||
|
||||
|
||||
;; -- Middleware ----------------------------------------------------------
|
||||
|
||||
(defn- undoable_
|
||||
"A Middleware factory which stores an undo checkpoint.
|
||||
\"explanation\" can be either a string or a function. If it is a
|
||||
function then must be: (db event-vec) -> string.
|
||||
\"explanation\" can be nil. in which case \"\" is recorded.
|
||||
"
|
||||
[explanation]
|
||||
(fn undoable-middleware
|
||||
[handler]
|
||||
(fn undoable-handler
|
||||
[db event-vec]
|
||||
(let [explanation (cond
|
||||
(fn? explanation) (explanation db event-vec)
|
||||
(string? explanation) explanation
|
||||
(nil? explanation) ""
|
||||
:else (console :error "re-frame: \"undoable\" middleware given a bad parameter. Got: " explanation))]
|
||||
(store-now! explanation)
|
||||
(handler db event-vec)))))
|
||||
|
||||
(def undoable (with-meta undoable_ {:re-frame-factory-name "undoable"}))
|
|
@ -6,7 +6,6 @@
|
|||
[devtools.core :as devtools]
|
||||
;; Test Namespaces -------------------------------
|
||||
[re-frame.middleware-test]
|
||||
[re-frame.undo-test]
|
||||
[re-frame.subs-test]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
@ -20,7 +19,6 @@
|
|||
(defn ^:export run-html-tests []
|
||||
(cljs-test/run-tests
|
||||
're-frame.middleware-test
|
||||
're-frame.undo-test
|
||||
're-frame.subs-test))
|
||||
|
||||
;; ---- KARMA -----------------------------------------------------------------
|
||||
|
@ -29,5 +27,4 @@
|
|||
(karma/run-tests
|
||||
karma
|
||||
're-frame.middleware-test
|
||||
're-frame.undo-test
|
||||
're-frame.subs-test))
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
(ns re-frame.undo-test
|
||||
(:require [cljs.test :refer-macros [is deftest]]
|
||||
[re-frame.undo :as undo]
|
||||
[re-frame.db :as db]
|
||||
[re-frame.core :as re-frame]))
|
||||
|
||||
|
||||
|
||||
(deftest test-undos
|
||||
;; Create undo history
|
||||
(undo/undo-config! {:max-undos 5})
|
||||
|
||||
(undo/clear-history!)
|
||||
(is (not (undo/undos?)))
|
||||
(is (not (undo/redos?)))
|
||||
|
||||
(doseq [i (range 10)]
|
||||
(reset! db/app-db {i i})
|
||||
(undo/store-now! i))
|
||||
|
||||
;; Check the undo state is correct
|
||||
(is (undo/undos?))
|
||||
(is (not (undo/redos?)))
|
||||
(is (= [4 5 6 7 8 9] (undo/undo-explanations)))
|
||||
(is (= [{5 5} {6 6} {7 7} {8 8} {9 9}] @undo/undo-list))
|
||||
|
||||
;; Undo the actions
|
||||
(re-frame/dispatch-sync [:undo])
|
||||
(is (= @db/app-db {9 9}))
|
||||
(is (undo/redos?))
|
||||
(re-frame/dispatch-sync [:undo])
|
||||
(is (= @db/app-db {8 8}))
|
||||
(re-frame/dispatch-sync [:undo])
|
||||
(is (= @db/app-db {7 7}))
|
||||
(re-frame/dispatch-sync [:undo])
|
||||
(is (= @db/app-db {6 6}))
|
||||
(re-frame/dispatch-sync [:undo])
|
||||
(is (= @db/app-db {5 5}))
|
||||
(is (not (undo/undos?)))
|
||||
(is (undo/redos?))
|
||||
|
||||
;; Redo them again
|
||||
(re-frame/dispatch-sync [:redo 5])
|
||||
(is (= @db/app-db {9 9}))
|
||||
(is (not (undo/redos?)))
|
||||
(is (undo/undos?))
|
||||
(is (= [{5 5} {6 6} {7 7} {8 8} {9 9}] @undo/undo-list))
|
||||
|
||||
;; Clear history
|
||||
(undo/clear-history!)
|
||||
(is (not (undo/undos?)))
|
||||
(is (not (undo/redos?))))
|
Loading…
Reference in New Issue