(ns auto-ap.forms (:require [re-frame.core :as re-frame] [re-frame.interceptor :as i] [auto-ap.status :as status] [malli.core :as m])) (re-frame/reg-sub ::form (fn [db [_ x]] (update (get (-> db ::forms) x) :visited (fn [v] (or v #{}))))) (re-frame/reg-sub ::field (fn [db [_ x f]] (-> (get (-> db ::forms) x) :data (get-in f)))) (defn start-form ([db form data] (start-form db form data nil)) ([db form data complete-listener] (-> db (assoc-in [::forms form] {:error nil :active? true :id (random-uuid) :visited #{} :status nil :data data :complete-listener complete-listener}) (assoc-in [::status/status form] nil)))) (re-frame/reg-event-db ::start-form (fn [db [_ id data]] (start-form db id data))) (defn triggers-saved [form data-key] (i/->interceptor :id :triggers-saved :before (fn [context] context) :after (fn [context] (let [db (i/get-coeffect context :db) result (get-in (i/get-coeffect context :event) [1 data-key])] (cond-> context true (i/assoc-effect :db (update-in db [::forms form] assoc :error nil :status nil :data result)) (get-in db [::forms form :complete-listener]) (i/assoc-effect :dispatch (conj (get-in db [::forms form :complete-listener ]) result))))))) (defn stop-form [db form] (update db ::forms dissoc form)) (re-frame/reg-event-db ::form-closing (fn [db [_ f]] (-> db (stop-form f)))) (defn in-form [form-name] (re-frame/path [::forms form-name])) (re-frame/reg-event-db ::change (fn [db [_ form & path-pairs]] (reduce (fn [db [path value]] (assoc-in db (into [::forms form :data] path) value)) db (partition 2 path-pairs)))) (re-frame/reg-event-db ::reset (fn [db [_ form v]] (assoc-in db [::forms form :data] v))) (re-frame/reg-event-db ::visited (fn [db [_ form & paths]] (update-in db [::forms form :visited] (fn [v] (set (into v paths)))))) (re-frame/reg-event-db ::check-problems (fn [db [_ form schema]] (assoc-in db [::forms form :problems] (when schema (m/explain schema (get-in db [::forms form :data])))))) (re-frame/reg-event-db ::attempted-submit (fn [db [_ form ]] (assoc-in db [::forms form :attempted-submit?] true))) (defn change-handler [form customize-fn] (fn [db [_ & path-pairs]] (reduce (fn [db [path value]] (let [updated (assoc-in db (into [::forms form :data] path) value)] (reduce (fn [updated [path value ]] (assoc-in updated (into [::forms form :data] path) value)) updated (partition 2 (customize-fn (get-in updated [::forms form :data]) path value))))) db (partition 2 path-pairs)))) (re-frame/reg-event-db ::save-error (fn [db [_ form result]] (println result) (-> db (assoc-in [::forms form :status] :error) (assoc-in [::forms form :error] (or (:message (first result)) result))))) ;; TODO ^:deprecated (defn loading [db id] (-> db (assoc-in [::forms id :status] :loading) (assoc-in [::forms id :error] nil))) #_{:clj-kondo/ignore [:clojure-lsp/unused-public-var]} (defn settles [{:keys [event time key]}] (i/->interceptor :id :settles :before (fn [context] context) :after (fn [context] (i/assoc-effect context :dispatch-debounce {:event event :time time :key key})))) (defn triggers-loading [form] (re-frame/enrich (fn [db _] (loading db form)))) (defn triggers-stop [form] (re-frame/enrich (fn [db _] (stop-form db form)))) (defn triggers-stop-loading [form] (re-frame/enrich (fn [db _] (assoc-in db [::forms form :status] nil)))) (defn save-succeeded [db id] (-> db (assoc-in [::forms id :status] nil) (assoc-in [::forms id :error] nil)))