Last active
October 23, 2020 00:17
-
-
Save olivergeorge/29f189ab794527c3692e3160b0232246 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns app.statecharts | |
(:require [app.utils :as utils] | |
[statecharts.core :as fsm] | |
[interop.anomalies :as anom] | |
[re-frame.core :as rf])) | |
; Guards | |
(defn offline? [state event] (not (get-in state [:db :app/online?]))) | |
(defn has-errors? [state event] (seq (utils/login-form-errors (get-in state [:db :app/login-form])))) | |
(defn incorrect? [state event] (anom/incorrect? (:data event))) | |
(defn anomaly? [state event] (anom/anomaly? (:data event))) | |
; Actions | |
(defn api-token-auth | |
[state event] | |
(let [{:login-form/keys [username password]} (get-in state [:db :app/login-form]) | |
data {:username username | |
:password password | |
:resolve [::transition :auth/api-token-auth.resolved] | |
:reject [::transition :auth/api-token-auth.rejected]}] | |
(update state :fx conj [:app.fx/api-token-auth data]))) | |
(defn save-token [state event] | |
(update-in state [:db :auth/token] (get-in event [:data "token"]))) | |
(defn store-token [state event] | |
(update state :fx conj [:app.fx/set-token {:token (get-in event [:data "token"]) | |
:resolve [::transaction :auth/set-token.resolved] | |
:reject [::transaction :auth/set-token.rejected]}])) | |
(defn oopsie [msg] | |
(fn [s] (update s :fx conj [:app.fx/alert-modal {:title "Oopsie" :message msg}]))) | |
(def report-offline (oopsie "We're offline")) | |
(def report-errors (oopsie "Form has errors")) | |
(def report-failed (oopsie "Unable to authenticate with details provided")) | |
(def report-anomaly (oopsie "Unexpected error authenticating")) | |
; Machine | |
(def auth-machine | |
{:id :auth | |
:initial :auth/idle | |
:states {:auth/idle {:on {:submit [{:target :auth/idle :guard offline? :actions report-offline} | |
{:target :auth/idle :guard has-errors? :actions report-errors} | |
{:target :auth/post :actions api-token-auth}]}} | |
:auth/post {:entry api-token-auth | |
:on {:api-token-auth.resolved | |
[{:target :auth/idle :guard incorrect? :actions report-failed} | |
{:target :auth/idle :guard anomaly? :actions report-anomaly} | |
{:target :auth/idle :actions [save-token store-token]}] | |
:api-token-auth.rejected | |
[{:target :auth/idle :actions report-anomaly}]}}}}) | |
; Reframe | |
(def machine-path [::machine]) | |
(defn get-state-with-context | |
[{:keys [db]}] | |
(let [s2 (get-in db machine-path)] | |
(assoc s2 :db db))) | |
(defn do-execute | |
[{:keys [db _actions] :as s}] | |
(reduce (fn [s' f] | |
(f s')) | |
{:fx [] :db (assoc-in db machine-path (dissoc s :db :_actions))} | |
_actions)) | |
(defn do-initialise | |
[{:keys [db]}] | |
{:db (assoc-in db machine-path (fsm/initialize (fsm/machine machine)))}) | |
(defn do-transition | |
[ctx [_ type data]] | |
(let [s1 (get-state-with-context ctx) | |
s2 (fsm/transition machine s1 {:type type :data data} {:exec false})] | |
(do-execute s2))) | |
(rf/reg-event-fx ::init do-initialise) | |
(rf/reg-event-fx ::transition do-transition) | |
(comment | |
(rf/dispatch [::init]) | |
(rf/dispatch [::transition :submit])) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment