Allows users to self set up square

This commit is contained in:
2022-04-06 08:22:52 -07:00
parent 982a0f3bed
commit 3a49ba971c
9 changed files with 303 additions and 239 deletions

View File

@@ -31,7 +31,8 @@
[:address [:street1 :street2 :city :state :zip]]])
(defn client-query [token]
(cond-> [:id :name :signature-file :code :email :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits :locations :locked-until
(cond-> [:id :name :signature-file :code :email :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits :locations :locked-until :square-auth-token
[:square-locations [:square-id :id :name :client-location]]
[:emails [:id :email :description]]
[:location-matches [:id :location :match]]
[:bank-accounts [:id :start-date :numeric-code :code :number :bank-name :bank-code :check-number :name :routing :type :sort-order :visible :yodlee-account-id

View File

@@ -108,6 +108,12 @@
:name (:name new-client-data)
:code (:code new-client-data) ;; TODO add validation can't change
:emails (:emails new-client-data)
:square-auth-token (:square-auth-token new-client-data)
:square-locations (map
(fn [x]
{:id (:id x)
:client-location (:client-location x)})
(:square-locations new-client-data))
:locked-until (cond (not (:locked-until new-client-data))
nil
@@ -654,5 +660,24 @@
:style {:width "7em"}
:field [:amount]
:step "0.01"}]]}])]]
(field "Square Authentication Token"
[:input.input {:type "text"
:field [:square-auth-token]}])
[:div.field
[:label.label "Square Locations"]
[:div.control
(raw-field
[multi-field {:type "multi-field"
:field :square-locations
:template [[:input.input {:type "text"
:style {:width "15em"}
:disabled true
:field [:name]}]
[:input.input {:type "text"
:style {:width "4em"}
:field [:client-location]
:step "0.01"}]]
:disable-remove? true
:disable-new? true}])]]
(error-notification)
(submit-button "Save")])]]))

View File

@@ -1,22 +1,22 @@
(ns auto-ap.views.utils
(:require [re-frame.core :as re-frame]
[reagent.core :as reagent]
[react-transition-group :as react-transition-group]
[react-datepicker]
[clojure.spec.alpha :as s]
[cljs-time.coerce :as c]
[cljs-time.core :as time]
[auto-ap.subs :as subs]
[cljs-time.format :as format]
[goog.i18n.NumberFormat.Format]
[cljs-time.core :as t]
[clojure.string :as str]
[goog.crypt.base64 :as base64]
[cljs.tools.reader.edn :as edn]
[reagent.core :as r])
(:require
[cemerick.url]
[cljs-time.coerce :as c]
[cljs-time.core :as t]
[cljs-time.format :as format]
[cljs.tools.reader.edn :as edn]
[clojure.spec.alpha :as s]
[clojure.string :as str]
[goog.crypt.base64 :as base64]
[re-frame.core :as re-frame]
[react-transition-group :as react-transition-group]
#_{:clj-kondo/ignore [:unused-namespace]}
[react-datepicker :as react-datepicker]
[reagent.core :as reagent])
(:import
(goog.i18n NumberFormat)
(goog.i18n.NumberFormat Format)))
(def nff
(NumberFormat. Format/CURRENCY))
@@ -27,8 +27,6 @@
(defn ->$ [x]
(nf x))
(defn- nf%
[num]
(.format (doto
@@ -59,7 +57,7 @@
(defn delayed-dispatch [e]
(fn [x]
(fn [_]
(js/setTimeout #(re-frame/dispatch e) 151)
false))
@@ -72,7 +70,7 @@
(re-frame/dispatch-sync event)))
(defn dispatch-event-with-propagation [event]
(fn [e]
(fn [_]
(re-frame/dispatch-sync event)))
(def pretty-long (format/formatter "MM/dd/yyyy HH:mm:ss"))
@@ -94,23 +92,23 @@
(format/parse f d)))
(defn dispatch-date-change [event]
(fn [e g]
(fn [e]
(re-frame/dispatch (conj event
(if (str/blank? e)
e
(date->str (time/from-default-time-zone (c/from-date e)) standard))))))
(date->str (t/from-default-time-zone (c/from-date e)) standard))))))
(defn dispatch-cljs-date-change [event]
(fn [e g]
(fn [e]
(re-frame/dispatch (conj event
(if (str/blank? e)
e
(time/from-default-time-zone (c/from-date e)))))))
(c/to-local-date e))))))
;; TODO inline on-changes causes each field to be rerendered each time. When we fix this
;; let's make sure that we find away not to trigger a re-render for every component any time any form field
;; changes
(defmulti do-bind (fn [a {:keys [type] :as x}]
(defmulti do-bind (fn [_ {:keys [type]}]
type))
(defn with-keys [children]
@@ -121,7 +119,7 @@
(reagent/adapt-react-class react-transition-group/CSSTransition))
(defn appearing [{:keys [visible? enter-class exit-class timeout]} & children ]
(defn appearing [{:keys [visible? enter-class exit-class timeout]}]
(let [final-state (reagent/atom visible?)]
(fn [{:keys [visible?]} & children]
[css-transition-group {:in visible? :class-names {:exit exit-class :enter enter-class} :timeout timeout :onEnter (fn [] (reset! final-state true )) :onExited (fn [] (reset! final-state false))}
@@ -130,15 +128,15 @@
[:span])])))
(defn multi-field [{:keys [change-event data value template on-change allow-change?]} ]
(let [value-repr (r/atom (mapv
(defn multi-field [{:keys [value]} ]
(let [value-repr (reagent/atom (mapv
(fn [x]
(assoc x :key (random-uuid) :new? false))
value))]
(fn [{:keys [change-event data value template on-change allow-change?]} ]
(fn [{:keys [template on-change allow-change? disable-new? disable-remove?]} ]
(let [value @value-repr
already-has-new-row? (= [:key :new?] (keys (last value)))
value (if already-has-new-row?
value (if (or already-has-new-row? disable-new?)
value
(conj value {:key (random-uuid)
:new? true}))]
@@ -153,7 +151,7 @@
[:div.level-item
(if (:new? override)
[:div.icon.is-medium {:class (if (not= i (dec (count value)))
[:div.icon.is-medium {:class (when (not= i (dec (count value)))
"has-text-info")}
[:i.fa.fa-plus]]
[:div.icon.is-medium])]
@@ -169,7 +167,7 @@
(if (= value {})
nil
value))
:disabled is-disabled?
:disabled (or is-disabled? (get-in template [1 :disabled]))
:on-change (fn [e]
(reset! value-repr
(into []
@@ -184,29 +182,27 @@
(dissoc v :new? :key))
@value-repr))))])
]
[:div.level-item
[:a.button.level-item
{:disabled is-disabled?
:on-click (fn []
(when-not disable-remove?
[:div.level-item
[:a.button.level-item
{:disabled is-disabled?
:on-click (fn []
(when-not is-disabled?
(reset! value-repr (into []
(filter (fn [{:keys [key ]}]
(not= key (:key override)))
(filter (fn [r]
(not= [:key :new?] (keys r)))
value))))
(when-not is-disabled?
(reset! value-repr (into []
(filter (fn [{:keys [key ] :as v}]
(not= key (:key override)))
(filter (fn [r]
(not= [:key :new?] (keys r)))
value))))
(on-change (mapv
(fn [v]
(dissoc v :new? :key))
@value-repr))))}
[:span.icon [:span.icon-remove]]]]
(on-change (mapv
(fn [v]
(dissoc v :new? :key))
@value-repr))))}
[:span.icon [:span.icon-remove]]]])
]])]))))
(defmethod do-bind "select" [dom {:keys [field allow-nil? subscription event class value spec] :as keys} & rest]
(defmethod do-bind "select" [dom {:keys [field allow-nil? subscription event class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -235,7 +231,7 @@
keys (dissoc keys :field :subscription :event :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind "checkbox" [dom {:keys [field subscription event class value spec] :as keys} & rest]
(defmethod do-bind "checkbox" [dom {:keys [field subscription event class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -253,7 +249,7 @@
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
:on-change (fn [selected text-description text-value]
:on-change (fn [selected text-value]
(re-frame/dispatch (conj (conj event field) selected))
(when text-field
(re-frame/dispatch (conj (conj (or text-event event) text-field) text-value))))
@@ -278,7 +274,7 @@
(into [dom keys] (with-keys rest))))
(defmethod do-bind "typeahead-entity" [dom {:keys [field event text-event subscription class spec match->text] :as keys} & rest]
(defmethod do-bind "typeahead-entity" [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -293,7 +289,7 @@
keys (dissoc keys :field :subscription :event :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind "typeahead-v3" [dom {:keys [field event text-event subscription class spec match->text] :as keys} & rest]
(defmethod do-bind "typeahead-v3" [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -314,10 +310,10 @@
selected (get-in subscription field)
selected (cond (string? selected)
(c/to-date (time/to-default-time-zone (time/from-default-time-zone (str->date selected standard))))
(c/to-date (t/to-default-time-zone (t/from-default-time-zone (str->date selected standard))))
(instance? goog.date.DateTime selected)
(c/to-date (time/to-default-time-zone (time/from-default-time-zone selected)))
(c/to-date (t/to-default-time-zone (t/from-default-time-zone selected)))
(instance? goog.date.Date selected)
(c/to-date selected)
@@ -361,7 +357,7 @@
keys (dissoc keys :field :event :subscription :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind "number" [dom {:keys [field precision event subscription class spec] :as keys :or {precision 2}} & rest]
(defmethod do-bind "number" [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -380,14 +376,13 @@
:else
val))))))
:value (get-in subscription field)
:class (str class
(when (and spec (not (s/valid? spec (get-in subscription field))))
" is-danger")))
keys (dissoc keys :field :subscription :event :spec)]
(into [dom keys] (with-keys rest))))
(defmethod do-bind "textarea->table" [dom {:keys [field event subscription class spec] :as keys :or {precision 2}} & rest]
(defmethod do-bind "textarea->table" [dom {:keys [field event subscription class spec] :as keys} & rest]
(let [field (if (keyword? field) [field] field)
event (if (keyword? event) [event] event)
keys (assoc keys
@@ -396,7 +391,6 @@
(conj field)
(conj x))))
:value (get-in subscription field)
:class (str class
(when (and spec (not (s/valid? spec (get-in subscription field))))
" is-danger")))
@@ -446,8 +440,7 @@
(with-keys (map (fn [x] [:div.field x]) controls)))])
(def date-picker
(do
(reagent/adapt-react-class (.-default react-datepicker))))
(reagent/adapt-react-class (.-default react-datepicker)))
(defn date-picker-friendly [params]
[date-picker (assoc params
@@ -506,15 +499,6 @@
{}
(:query (cemerick.url/url (.-location js/window)))))
(defn loading [db]
(-> db
(assoc-in [:status] :loading)
(assoc-in [:error] nil)))
(defn triggers-loading [form]
(re-frame/enrich
(fn [db event]
(loading db))))
(defn action-cell-width [cnt]
(str (inc (* cnt 51)) "px"))