(ns auto-ap.forms (:require [re-frame.core :as re-frame] [re-frame.interceptor :as i] [auto-ap.status :as status] [auto-ap.views.utils :refer [dispatch-event bind-field]])) (re-frame/reg-sub ::form (fn [db [_ x]] (get (-> db ::forms) x))) (re-frame/reg-sub ::is-loading? (fn [db [_ x]] (if (#{"loading" :loading} (get-in db [::forms x :status]) ) true false))) (re-frame/reg-sub ::loading-class (fn [db [_ x]] (if (#{"loading" :loading} (get-in db [::forms x :status]) ) "is-loading" ""))) (defn start-form ([db form data] (start-form db form data nil)) ([db form data complete-listener] (assoc-in db [::forms form] {:error nil :active? true :id (random-uuid) :status nil :data data :complete-listener complete-listener}))) (defn ^:depracated saved-form [db form data] (update-in db [::forms form] assoc :error nil :status nil :data 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)))) (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))))) (defn ^:deprecated side-bar-form [{:keys [form]} children] [:div [:a.delete.is-pulled-right {:on-click (dispatch-event [::form-closing form])}] [:div children]]) ;; TODO ^:deprecated (defn loading [db id] (-> db (assoc-in [::forms id :status] :loading) (assoc-in [::forms id :error] nil))) (defn settles [{:keys [event time key]}] (i/->interceptor :id :settles :befor (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 event] (loading db form)))) (defn triggers-stop [form] (re-frame/enrich (fn [db event] (stop-form db form)))) (defn triggers-stop-loading [form] (re-frame/enrich (fn [db event] (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))) (defn vertical-form [{:keys [can-submit id change-event submit-event ]}] {:form (fn [{:keys [title] :as params} & children] (let [{:keys [data active? error]} @(re-frame/subscribe [::form id]) can-submit @(re-frame/subscribe can-submit)] [:form { :on-submit (fn [e] (when (.-stopPropagation e) (.stopPropagation e) (.preventDefault e)) (when can-submit (re-frame/dispatch-sync (vec (conj submit-event params)))))} [:h1.title.is-2 title] [:<> children]])) :form-inline (fn [{:keys [title] :as params} children] (let [{:keys [data active? error]} @(re-frame/subscribe [::form id]) can-submit @(re-frame/subscribe can-submit)] [:form { :on-submit (fn [e] (when (.-stopPropagation e) (.stopPropagation e) (.preventDefault e)) (when can-submit (re-frame/dispatch-sync (vec (conj submit-event params)))))} (when title [:h1.title.is-2 title]) children])) :raw-field (fn [control] (let [{:keys [data]} @(re-frame/subscribe [::form id])] [bind-field (-> control (assoc-in [1 :subscription] data) (assoc-in [1 :event] change-event))])) :field-holder (fn [label control] [:div.field (when label [:p.help label]) [:div.control control]]) :field ^{:key "field"} (fn [label control] (let [{:keys [data]} @(re-frame/subscribe [::form id])] [:div.field (when label [:p.help label]) [:div.control [bind-field (-> control (assoc-in [1 :subscription] data) (assoc-in [1 :event] change-event))]]])) :error-notification (fn [] (when-let [error (:error @(re-frame/subscribe [::form id]))] ^{:key error} [:div.has-text-danger.animated.fadeInUp {} error])) :submit-button (fn [child] (let [error (:error @(re-frame/subscribe [::form id])) status @(re-frame/subscribe [::status/single id]) can-submit @(re-frame/subscribe can-submit)] [:button.button.is-medium.is-primary.is-fullwidth {:disabled (or (status/disabled-for status) (not can-submit)) :class (status/class-for status) } child]))})