finally sunset old binding
This commit is contained in:
@@ -220,7 +220,7 @@ nav.navbar .navbar-item.is-active {
|
|||||||
margin: 0 -50px;
|
margin: 0 -50px;
|
||||||
padding-left: 50px;
|
padding-left: 50px;
|
||||||
}
|
}
|
||||||
.aside .main .icon {
|
.aside .main .menu-item .icon {
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
color: #A0A0A0;
|
color: #A0A0A0;
|
||||||
|
|||||||
@@ -201,7 +201,7 @@
|
|||||||
" is-danger"
|
" is-danger"
|
||||||
|
|
||||||
value
|
value
|
||||||
"is-success"
|
" is-success"
|
||||||
|
|
||||||
:else
|
:else
|
||||||
""))))))))))))))
|
""))))))))))))))
|
||||||
|
|||||||
@@ -1,55 +1,51 @@
|
|||||||
(ns auto-ap.views.components.date-range-filter
|
(ns auto-ap.views.components.date-range-filter
|
||||||
(:require
|
(:require
|
||||||
[auto-ap.views.utils :refer [bind-field date-picker date->str local-now standard]]
|
[auto-ap.views.utils :refer [date-picker date->str local-now standard]]
|
||||||
[cljs-time.core :as t]
|
[cljs-time.core :as t]
|
||||||
[re-frame.core :as re-frame]))
|
[re-frame.core :as re-frame]
|
||||||
|
[auto-ap.forms.builder :as form-builder]))
|
||||||
|
|
||||||
(defn dispatch-change [on-change-event start end]
|
|
||||||
(fn [_]
|
(defn set-value [on-change-event v]
|
||||||
(re-frame/dispatch (into on-change-event [[:start] start]) )
|
(re-frame/dispatch (conj on-change-event v)))
|
||||||
(re-frame/dispatch (into on-change-event [[:end] end]))))
|
|
||||||
|
|
||||||
(defn date-range-filter [{:keys [value on-change-event]}]
|
(defn date-range-filter [{:keys [value on-change-event]}]
|
||||||
[:div
|
[form-builder/virtual-builder {:value (or value {})
|
||||||
[:div.field.has-addons
|
:on-change (fn [v]
|
||||||
[:p.control [:a.button.is-small {:on-click
|
(set-value on-change-event v))}
|
||||||
(dispatch-change on-change-event
|
|
||||||
(date->str (t/minus (local-now) (t/period :days 7)) standard)
|
[:div
|
||||||
(date->str (local-now) standard))}
|
[:div.field.has-addons
|
||||||
"Week" ]]
|
[:p.control [:a.button.is-small {:on-click
|
||||||
[:p.control [:a.button.is-small {:on-click
|
#(set-value on-change-event
|
||||||
(dispatch-change on-change-event
|
{:start (date->str (t/minus (local-now) (t/period :days 7)) standard)
|
||||||
(date->str (t/minus (local-now) (t/period :months 1)) standard)
|
:end (date->str (local-now) standard)})}
|
||||||
(date->str (local-now) standard))}
|
"Week" ]]
|
||||||
"Month" ]]
|
[:p.control [:a.button.is-small {:on-click
|
||||||
[:p.control [:a.button.is-small {:on-click
|
#(set-value on-change-event
|
||||||
(dispatch-change on-change-event
|
{:start (date->str (t/minus (local-now) (t/period :months 1)) standard)
|
||||||
(date->str (t/minus (local-now) (t/period :years 1)) standard)
|
:end (date->str (local-now) standard)})}
|
||||||
(date->str (local-now) standard))}
|
"Month" ]]
|
||||||
"Year"]]
|
[:p.control [:a.button.is-small {:on-click
|
||||||
[:p.control [:a.button.is-small {:on-click
|
|
||||||
(dispatch-change on-change-event
|
#(set-value on-change-event
|
||||||
nil
|
{:start (date->str (t/minus (local-now) (t/period :years 1)) standard)
|
||||||
nil)}
|
:end (date->str (local-now) standard)})}
|
||||||
"All"]]]
|
"Year"]]
|
||||||
[:div.field.has-addons
|
[:p.control [:a.button.is-small {:on-click
|
||||||
[:div.control
|
#(set-value on-change-event nil)}
|
||||||
[bind-field
|
"All"]]]
|
||||||
[date-picker
|
[:div.field.has-addons
|
||||||
{:event on-change-event
|
[:div.control
|
||||||
:type "date"
|
|
||||||
:placeholder "Start"
|
[form-builder/raw-field-v2 {:field :start}
|
||||||
:class "is-small"
|
[date-picker
|
||||||
:field [:start]
|
{:placeholder "Start"
|
||||||
:subscription value
|
:class "is-small"
|
||||||
:output :text}]]]
|
:output :text}]]]
|
||||||
[:div.control
|
[:div.control
|
||||||
[bind-field
|
[form-builder/raw-field-v2 {:field :end}
|
||||||
[date-picker
|
[date-picker
|
||||||
{:event on-change-event
|
{:class "is-small"
|
||||||
:type "date"
|
:placeholder "End"
|
||||||
:class "is-small"
|
:output :text}]]]]]])
|
||||||
:placeholder "End"
|
|
||||||
:field [:end]
|
|
||||||
:subscription value
|
|
||||||
:output :text}]]]]])
|
|
||||||
|
|||||||
@@ -1,25 +1,21 @@
|
|||||||
(ns auto-ap.views.components.number-filter
|
(ns auto-ap.views.components.number-filter
|
||||||
(:require
|
(:require
|
||||||
[auto-ap.views.utils :refer [bind-field]]
|
[re-frame.core :as re-frame]
|
||||||
[re-frame.core :as re-frame]))
|
[auto-ap.forms.builder :as form-builder]
|
||||||
|
[auto-ap.views.components :as com]))
|
||||||
|
|
||||||
(defn number-filter [{:keys [value on-change-event]}]
|
(defn number-filter [{:keys [value on-change-event]}]
|
||||||
[:div.field
|
[form-builder/virtual-builder {:value (or value {})
|
||||||
[:div.control
|
:on-change (fn [v]
|
||||||
[:div.columns
|
(re-frame/dispatch (conj on-change-event v)))}
|
||||||
[:div.column
|
|
||||||
[bind-field
|
[:div.columns
|
||||||
[:input.input {:type "number"
|
[:div.column
|
||||||
:placeholder ">="
|
[:div.control
|
||||||
:field [:amount-gte]
|
[form-builder/raw-field-v2 {:field :amount-gte}
|
||||||
:step "0.01"
|
[com/money-input {:placeholder ">="}]]]]
|
||||||
:event on-change-event
|
[:div.column
|
||||||
:subscription value}]]]
|
[:div.control
|
||||||
[:div.column
|
[form-builder/raw-field-v2 {:field :amount-lte}
|
||||||
[bind-field
|
[com/money-input {:placeholder "<="}]]]]]]
|
||||||
[:input.input {:type "number"
|
)
|
||||||
:placeholder "<="
|
|
||||||
:field [:amount-lte]
|
|
||||||
:event on-change-event
|
|
||||||
:step "0.01"
|
|
||||||
:subscription value}]]]]]])
|
|
||||||
|
|||||||
@@ -1,29 +1,25 @@
|
|||||||
(ns auto-ap.views.components.vendor-dialog
|
(ns auto-ap.views.components.vendor-dialog
|
||||||
(:require
|
(:require
|
||||||
[auto-ap.entities.contact :as contact]
|
|
||||||
[auto-ap.entities.vendors :as entity]
|
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.forms :as forms]
|
||||||
[auto-ap.forms.builder :as form-builder]
|
[auto-ap.forms.builder :as form-builder]
|
||||||
|
[auto-ap.schema :as schema]
|
||||||
[auto-ap.status :as status]
|
[auto-ap.status :as status]
|
||||||
[auto-ap.views.components.level :refer [left-stack]]
|
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.subs :as subs]
|
||||||
[auto-ap.views.components :as com]
|
[auto-ap.views.components :as com]
|
||||||
[auto-ap.views.components.address :refer [address2-field]]
|
[auto-ap.views.components.address :refer [address2-field]]
|
||||||
|
[auto-ap.views.components.level :refer [left-stack]]
|
||||||
[auto-ap.views.components.modal :as modal]
|
[auto-ap.views.components.modal :as modal]
|
||||||
|
[auto-ap.views.components.multi :refer [multi-field-v2]]
|
||||||
[auto-ap.views.components.number :refer [number-input]]
|
[auto-ap.views.components.number :refer [number-input]]
|
||||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
||||||
[auto-ap.views.components.typeahead.vendor
|
[auto-ap.views.components.typeahead.vendor
|
||||||
:refer [search-backed-typeahead]]
|
:refer [search-backed-typeahead]]
|
||||||
[auto-ap.views.pages.admin.vendors.common :as common]
|
[auto-ap.views.pages.admin.vendors.common :as common]
|
||||||
[auto-ap.views.components.multi :refer [multi-field-v2]]
|
|
||||||
[auto-ap.views.utils
|
[auto-ap.views.utils
|
||||||
:refer [dispatch-event multi-field str->int with-is-admin? with-user]]
|
:refer [dispatch-event str->int with-is-admin? with-user]]
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[reagent.core :as r]
|
|
||||||
[malli.core :as m]
|
[malli.core :as m]
|
||||||
[auto-ap.schema :as schema]
|
[re-frame.core :as re-frame]
|
||||||
[malli.error :as me]))
|
[reagent.core :as r]))
|
||||||
|
|
||||||
;; Remaining cleanup todos:
|
;; Remaining cleanup todos:
|
||||||
;; test minification
|
;; test minification
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
(ns auto-ap.views.pages.admin.accounts.form
|
(ns auto-ap.views.pages.admin.accounts.form
|
||||||
(:require [auto-ap.entities.account :as entity]
|
(:require
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.forms :as forms]
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.forms.builder :as form-builder]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar]]
|
[auto-ap.schema :as schema]
|
||||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
[auto-ap.subs :as subs]
|
||||||
[auto-ap.views.utils :refer [dispatch-event multi-field with-user]]
|
[auto-ap.views.components :as com]
|
||||||
[clojure.spec.alpha :as s]
|
[auto-ap.views.components.layouts :refer [side-bar]]
|
||||||
[clojure.string :as str]
|
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
||||||
[re-frame.core :as re-frame]
|
[auto-ap.views.utils :refer [dispatch-event with-user]]
|
||||||
[auto-ap.forms.builder :as form-builder]
|
[clojure.string :as str]
|
||||||
[vimsical.re-frame.cofx.inject :as inject]
|
[malli.core :as m]
|
||||||
[auto-ap.views.components :as com]
|
[re-frame.core :as re-frame]
|
||||||
[malli.core :as m]
|
[vimsical.re-frame.cofx.inject :as inject]))
|
||||||
[auto-ap.schema :as schema]))
|
|
||||||
|
|
||||||
(def types [:dividend :expense :asset :liability :equity :revenue])
|
(def types [:dividend :expense :asset :liability :equity :revenue])
|
||||||
(def applicabilities [:global :optional :customized])
|
(def applicabilities [:global :optional :customized])
|
||||||
|
|||||||
@@ -15,13 +15,10 @@
|
|||||||
:refer [search-backed-typeahead]]
|
:refer [search-backed-typeahead]]
|
||||||
[auto-ap.views.utils
|
[auto-ap.views.utils
|
||||||
:refer [date-picker
|
:refer [date-picker
|
||||||
dispatch-event
|
dispatch-event]]
|
||||||
horizontal-field
|
|
||||||
multi-field]]
|
|
||||||
[bidi.bidi :as bidi]
|
[bidi.bidi :as bidi]
|
||||||
[cljs-time.coerce :as coerce]
|
[cljs-time.coerce :as coerce]
|
||||||
[cljs-time.core :as t]
|
[cljs-time.core :as t]
|
||||||
[clojure.string :as str]
|
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as r]
|
[reagent.core :as r]
|
||||||
[react-signature-canvas]
|
[react-signature-canvas]
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
::save
|
::save
|
||||||
[ with-user (forms/in-form ::form)]
|
[ with-user (forms/in-form ::form)]
|
||||||
(fn [{:keys [db user]}]
|
(fn [{:keys [db user]}]
|
||||||
{
|
{:http {:token user
|
||||||
:http {:token user
|
|
||||||
:method :post
|
:method :post
|
||||||
:body (pr-str {:excel-rows (:excel-rows (:data db))})
|
:body (pr-str {:excel-rows (:excel-rows (:data db))})
|
||||||
:headers {"Content-Type" "application/edn"}
|
:headers {"Content-Type" "application/edn"}
|
||||||
|
|||||||
@@ -2,37 +2,28 @@
|
|||||||
(:require
|
(:require
|
||||||
[auto-ap.events :as events]
|
[auto-ap.events :as events]
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.forms :as forms]
|
||||||
|
[auto-ap.forms.builder :as form-builder]
|
||||||
[auto-ap.status :as status]
|
[auto-ap.status :as status]
|
||||||
[auto-ap.subs :as subs]
|
[auto-ap.views.components :as com]
|
||||||
[auto-ap.views.components.dropdown
|
[auto-ap.views.components.dropdown
|
||||||
:refer [drop-down drop-down-contents]]
|
:refer [drop-down drop-down-contents]]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||||
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]]
|
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]]
|
||||||
[auto-ap.views.utils :refer [bind-field dispatch-event]]
|
[auto-ap.views.utils :refer [dispatch-event]]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as r]))
|
[reagent.core :as r]))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(defn line->id [{:keys [source id client-code]}]
|
||||||
::loading
|
|
||||||
(fn [db]
|
|
||||||
(-> db ::loading)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
::can-submit
|
|
||||||
(fn [db]
|
|
||||||
true))
|
|
||||||
|
|
||||||
(defn line->id [{:keys [source id client-code date vendor-name] :as line}]
|
|
||||||
(str client-code "-" source "-" id))
|
(str client-code "-" source "-" id))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
::request
|
::request
|
||||||
:<- [::forms/form ::form]
|
:<- [::forms/form ::form]
|
||||||
(fn [{{lines :line-items :as d} :data :as g}]
|
(fn [{{lines :line-items} :data}]
|
||||||
(into []
|
(into []
|
||||||
(for [[external-id lines] (group-by line->id lines)
|
(for [[_ lines] (group-by line->id lines)
|
||||||
:let [{:keys [source id client-code date vendor-name note cleared-against] :as line} (first lines)]]
|
:let [{:keys [source client-code date vendor-name note cleared-against] :as line} (first lines)]]
|
||||||
{:source source
|
{:source source
|
||||||
:external-id (line->id line)
|
:external-id (line->id line)
|
||||||
:client-code client-code
|
:client-code client-code
|
||||||
@@ -139,6 +130,8 @@
|
|||||||
[:form.form
|
[:form.form
|
||||||
(if value
|
(if value
|
||||||
[:div
|
[:div
|
||||||
|
[:a.button {:on-click #(on-change nil)}
|
||||||
|
"reset"]
|
||||||
[:table.table {:style {:width "100%"}}
|
[:table.table {:style {:width "100%"}}
|
||||||
[:thead
|
[:thead
|
||||||
[:tr
|
[:tr
|
||||||
@@ -190,68 +183,72 @@
|
|||||||
(def balance-sheet-content
|
(def balance-sheet-content
|
||||||
(with-meta
|
(with-meta
|
||||||
(fn []
|
(fn []
|
||||||
(let [current-client @(re-frame/subscribe [::subs/client])
|
(let [status @(re-frame/subscribe [::status/single ::import])
|
||||||
user @(re-frame/subscribe [::subs/user])
|
{:keys [data result]} @(re-frame/subscribe [::forms/form ::form]) ]
|
||||||
status @(re-frame/subscribe [::status/single ::import])
|
[form-builder/builder {:id ::form
|
||||||
{:keys [data result active? error id]} @(re-frame/subscribe [::forms/form ::form]) ]
|
:submit-event [::importing]}
|
||||||
[:div
|
[:div
|
||||||
[:div.level
|
[:div.level
|
||||||
[:div.level-left
|
[:div.level-left
|
||||||
[:h1.title "Eternal Import"]]
|
[:h1.title "Eternal Import"]]
|
||||||
|
|
||||||
[:div.level-right
|
[:div.level-right
|
||||||
[:button.button.is-primary.is-pulled-right.is-large {:disabled (or (not data)
|
[form-builder/submit-button "Import"]]]
|
||||||
(= :loading (:state status )))
|
[status/status-notification {:statuses [[::status/single ::import]]} ]
|
||||||
:on-click (dispatch-event [::importing])} "Import"]]]
|
(when result
|
||||||
[status/status-notification {:statuses [[::status/single ::import]]} ]
|
[:div.notification
|
||||||
(when result
|
"Imported with "
|
||||||
[:div.notification
|
(count (:errors result)) " errors, "
|
||||||
"Imported with "
|
(count (:ignored result)) " ignored, "
|
||||||
(count (:errors result)) " errors, "
|
(count (:success result)) " successful."])
|
||||||
(count (:ignored result)) " ignored, "
|
(if (= :loading (:state status ))
|
||||||
(count (:success result)) " successful."])
|
[status/big-loader status]
|
||||||
(if (= :loading (:state status ))
|
|
||||||
[status/big-loader status]
|
|
||||||
[:div
|
|
||||||
[:div.is-clearfix
|
|
||||||
[:div.is-pulled-right
|
|
||||||
[:label.checkbox
|
|
||||||
[bind-field
|
|
||||||
[:input {:type "checkbox"
|
|
||||||
:event [::forms/change ::form]
|
|
||||||
:subscription data
|
|
||||||
:field [:only-show-errors?]}]]
|
|
||||||
"Only show errors"]]]
|
|
||||||
[:div
|
[:div
|
||||||
[bind-field
|
[:div.is-clearfix
|
||||||
[textarea->table {:type "textarea->table"
|
[:div.is-pulled-right
|
||||||
:field [:line-items]
|
[form-builder/raw-field-v2 {:field :only-show-errors?}
|
||||||
:headings [["Id" :id]
|
[com/checkbox {:label "Only show errors"}]]]]
|
||||||
["Client" :client-code]
|
[:div
|
||||||
["Source" :source]
|
[form-builder/raw-field-v2 {:field :line-items}
|
||||||
["Vendor" :vendor-name]
|
[textarea->table {:headings [["Id" :id]
|
||||||
["Date" :date]
|
["Client" :client-code]
|
||||||
["Account" :account-identifier]
|
["Source" :source]
|
||||||
["Location" :location]
|
["Vendor" :vendor-name]
|
||||||
["Debit" :debit]
|
["Date" :date]
|
||||||
["Credit" :credit]
|
["Account" :account-identifier]
|
||||||
["Note" :note]
|
["Location" :location]
|
||||||
["Cleared against" :cleared-against]]
|
["Debit" :debit]
|
||||||
:read-only-headings
|
["Credit" :credit]
|
||||||
[["status" :status]]
|
["Note" :note]
|
||||||
|
["Cleared against" :cleared-against]]
|
||||||
|
:read-only-headings
|
||||||
|
[["status" :status]]
|
||||||
|
|
||||||
:row-filter
|
:row-filter
|
||||||
(fn [{:keys [status-category]}]
|
(fn [{:keys [status-category]}]
|
||||||
(if (:only-show-errors? data)
|
(if (:only-show-errors? data)
|
||||||
(= :error status-category)
|
(= :error status-category)
|
||||||
true))
|
true))}]]]])]]))
|
||||||
|
|
||||||
:event [::forms/change ::form]
|
|
||||||
:subscription data}
|
|
||||||
]]]])]))
|
|
||||||
{}))
|
{}))
|
||||||
|
|
||||||
(defn external-import-page []
|
(re-frame/reg-event-fx
|
||||||
|
::mounted
|
||||||
|
(fn [_ _]
|
||||||
|
{:dispatch [::forms/start-form ::form]}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::unmounted
|
||||||
|
(fn [_ _]
|
||||||
|
{:dispatch [::forms/form-closing ::form]}))
|
||||||
|
|
||||||
|
(defn external-import-page-internal []
|
||||||
[side-bar-layout
|
[side-bar-layout
|
||||||
{:side-bar [ledger-side-bar]
|
{:side-bar [ledger-side-bar]
|
||||||
:main [balance-sheet-content]}])
|
:main [balance-sheet-content]}])
|
||||||
|
|
||||||
|
(defn external-import-page []
|
||||||
|
(r/create-class
|
||||||
|
{:display-name "external-import-page"
|
||||||
|
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])
|
||||||
|
:component-did-mount #(re-frame/dispatch [::mounted])
|
||||||
|
:reagent-render external-import-page-internal}))
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
:refer [appearing-side-bar side-bar-layout]]
|
:refer [appearing-side-bar side-bar-layout]]
|
||||||
[auto-ap.views.components.modal :as modal]
|
[auto-ap.views.components.modal :as modal]
|
||||||
[auto-ap.views.components.switch-field :refer [switch-field]]
|
[auto-ap.views.components.switch-field :refer [switch-field]]
|
||||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
|
||||||
[auto-ap.views.pages.data-page :as data-page]
|
[auto-ap.views.pages.data-page :as data-page]
|
||||||
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]]
|
[auto-ap.views.pages.ledger.side-bar :refer [ledger-side-bar]]
|
||||||
[auto-ap.views.pages.ledger.table :as ledger-table]
|
[auto-ap.views.pages.ledger.table :as ledger-table]
|
||||||
@@ -19,7 +18,6 @@
|
|||||||
date-picker
|
date-picker
|
||||||
dispatch-event
|
dispatch-event
|
||||||
local-today
|
local-today
|
||||||
multi-field
|
|
||||||
query-params
|
query-params
|
||||||
standard
|
standard
|
||||||
str->date
|
str->date
|
||||||
|
|||||||
@@ -51,7 +51,8 @@
|
|||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::unmounted
|
::unmounted
|
||||||
(fn [{:keys [db]} _]
|
(fn [{:keys [db]} _]
|
||||||
{:dispatch [::data-page/dispose :invoices]
|
{:dispatch-n [[::data-page/dispose :invoices]
|
||||||
|
[::forms/form-closing ::form/form]]
|
||||||
::forward/dispose [{:id ::updated}
|
::forward/dispose [{:id ::updated}
|
||||||
{:id ::checks-printed}]
|
{:id ::checks-printed}]
|
||||||
::track/dispose [{:id ::params}]}))
|
::track/dispose [{:id ::params}]}))
|
||||||
|
|||||||
@@ -106,26 +106,6 @@
|
|||||||
(when d
|
(when d
|
||||||
(format/parse f d)))
|
(format/parse f d)))
|
||||||
|
|
||||||
(defn dispatch-date-change [event]
|
|
||||||
(fn [e]
|
|
||||||
(re-frame/dispatch (conj event
|
|
||||||
(if (str/blank? e)
|
|
||||||
e
|
|
||||||
(date->str (t/from-default-time-zone (c/from-date e)) standard))))))
|
|
||||||
|
|
||||||
(defn dispatch-cljs-date-change [event]
|
|
||||||
(fn [e]
|
|
||||||
(re-frame/dispatch (conj event
|
|
||||||
(if (str/blank? e)
|
|
||||||
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 [_ {:keys [type]}]
|
|
||||||
type))
|
|
||||||
|
|
||||||
(defn with-keys [children]
|
(defn with-keys [children]
|
||||||
(map-indexed (fn [i c] ^{:key i} c) children))
|
(map-indexed (fn [i c] ^{:key i} c) children))
|
||||||
|
|
||||||
@@ -178,290 +158,6 @@
|
|||||||
0.0)}}
|
0.0)}}
|
||||||
child])))])])))
|
child])))])])))
|
||||||
|
|
||||||
|
|
||||||
(defn multi-field [{:keys [value]} ]
|
|
||||||
(let [value-repr (reagent/atom (mapv
|
|
||||||
(fn [x]
|
|
||||||
(assoc x :key (random-uuid) :new? false))
|
|
||||||
value))]
|
|
||||||
(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 (or already-has-new-row? disable-new?)
|
|
||||||
value
|
|
||||||
(conj value {:key (random-uuid)
|
|
||||||
:new? true}))]
|
|
||||||
[:div {:style {:margin-bottom "0.25em"}}
|
|
||||||
(for [[i override] (map vector (range) value)
|
|
||||||
:let [is-disabled? (if (= false allow-change?)
|
|
||||||
(not (boolean (:new? override)))
|
|
||||||
nil)]
|
|
||||||
]
|
|
||||||
^{:key (:key override)}
|
|
||||||
[:div.level {:style {:margin-bottom "0.25em"}}
|
|
||||||
[:div.level-left {:style {:padding "0.5em 1em"}
|
|
||||||
:class (cond
|
|
||||||
(and (= i (dec (count value)))
|
|
||||||
(:new? override))
|
|
||||||
"has-background-light"
|
|
||||||
|
|
||||||
(:new? override)
|
|
||||||
"has-background-info-light"
|
|
||||||
:else
|
|
||||||
"")}
|
|
||||||
(let [template (if (fn? template)
|
|
||||||
(template override)
|
|
||||||
template)]
|
|
||||||
|
|
||||||
[:<> (for [[idx template] (map vector (range ) template)]
|
|
||||||
^{:key idx}
|
|
||||||
|
|
||||||
[:div.level-item
|
|
||||||
(update template 1 assoc
|
|
||||||
:value (let [value (get-in override (get-in template [1 :field])) ;; TODO this is really ugly to support maps or strings
|
|
||||||
value (if (map? value)
|
|
||||||
(dissoc value :key :new?)
|
|
||||||
value)]
|
|
||||||
(if (= value {})
|
|
||||||
nil
|
|
||||||
value))
|
|
||||||
:disabled (or is-disabled? (get-in template [1 :disabled]))
|
|
||||||
:on-change (fn [e]
|
|
||||||
(reset! value-repr
|
|
||||||
(into []
|
|
||||||
(filter (fn [r]
|
|
||||||
(not= [:key :new?] (keys r)))
|
|
||||||
(assoc-in value
|
|
||||||
(into [i] (get-in template [1 :field]))
|
|
||||||
(let [this-value (if (and e (.. e -target))
|
|
||||||
(.. e -target -value )
|
|
||||||
e)]
|
|
||||||
(if (map? this-value)
|
|
||||||
(update this-value :key (fnil identity (random-uuid)))
|
|
||||||
this-value))))))
|
|
||||||
(on-change (mapv
|
|
||||||
(fn [v]
|
|
||||||
(dissoc v :new? :key))
|
|
||||||
@value-repr))))])
|
|
||||||
])
|
|
||||||
(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))))
|
|
||||||
|
|
||||||
(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 spec] :as keys} & rest]
|
|
||||||
(let [field (if (keyword? field) [field] field)
|
|
||||||
event (if (keyword? event) [event] event)
|
|
||||||
keys (assoc keys
|
|
||||||
:on-change (dispatch-value-change (conj event field))
|
|
||||||
|
|
||||||
:value (or (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)
|
|
||||||
options (if allow-nil?
|
|
||||||
(with-keys (conj rest [:option {:value nil}]))
|
|
||||||
(with-keys rest))]
|
|
||||||
(into [dom (dissoc keys :allow-nil?)] options)))
|
|
||||||
|
|
||||||
|
|
||||||
(defmethod do-bind "radio" [dom {:keys [field subscription event class value spec] :as keys} & rest]
|
|
||||||
(let [field (if (keyword? field) [field] field)
|
|
||||||
event (if (keyword? event) [event] event)
|
|
||||||
keys (assoc keys
|
|
||||||
:on-change (dispatch-value-change (conj event field))
|
|
||||||
:checked (= (get-in subscription field) value)
|
|
||||||
: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 "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
|
|
||||||
:on-change (dispatch-event (-> event
|
|
||||||
(conj field)
|
|
||||||
(conj (not (get-in subscription field)))))
|
|
||||||
:checked (boolean (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 "multi-field" [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
|
|
||||||
:on-change (fn [value]
|
|
||||||
(re-frame/dispatch (conj (conj event field) value)))
|
|
||||||
: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 "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
|
|
||||||
:on-change (fn [selected]
|
|
||||||
(re-frame/dispatch (conj (conj event field) selected))
|
|
||||||
#_(when text-field
|
|
||||||
(re-frame/dispatch (conj (conj (or text-event event) text-field) text-value))))
|
|
||||||
: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 "date" [dom {:keys [field event subscription class spec] :as keys} & rest]
|
|
||||||
(let [field (if (keyword? field) [field] field)
|
|
||||||
event (if (keyword? event) [event] event)
|
|
||||||
selected (get-in subscription field)
|
|
||||||
keys (assoc keys
|
|
||||||
:on-change (fn [v]
|
|
||||||
(re-frame/dispatch (-> event (conj field) (conj v))))
|
|
||||||
|
|
||||||
:value selected
|
|
||||||
: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 "expense-accounts" [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
|
|
||||||
:value (get-in subscription field)
|
|
||||||
:event (conj event field)
|
|
||||||
:class (str class
|
|
||||||
(when (and spec (not (s/valid? spec (get-in subscription field))))
|
|
||||||
" is-danger")))
|
|
||||||
keys (dissoc keys :field :subscription :spec)]
|
|
||||||
(into [dom keys] (with-keys rest))))
|
|
||||||
|
|
||||||
|
|
||||||
(defmethod do-bind "button-radio" [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
|
|
||||||
:value (get-in subscription field)
|
|
||||||
:on-change (fn [v]
|
|
||||||
(re-frame/dispatch (-> event (conj field) (conj v))))
|
|
||||||
:class (str class
|
|
||||||
(when (and spec (not (s/valid? spec (get-in subscription field))))
|
|
||||||
" is-danger")))
|
|
||||||
keys (dissoc keys :field :event :subscription :spec)]
|
|
||||||
(into [dom keys] (with-keys 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
|
|
||||||
:on-change (fn [e]
|
|
||||||
(.preventDefault e)
|
|
||||||
(re-frame/dispatch (-> event
|
|
||||||
(conj field)
|
|
||||||
(conj (let [val (.. e -target -value)]
|
|
||||||
(cond (and val
|
|
||||||
(re-matches #"[\-]?(\d+)(\.\d{2})?" val))
|
|
||||||
(js/parseFloat val)
|
|
||||||
|
|
||||||
(str/blank? val )
|
|
||||||
nil
|
|
||||||
|
|
||||||
: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} & rest]
|
|
||||||
(let [field (if (keyword? field) [field] field)
|
|
||||||
event (if (keyword? event) [event] event)
|
|
||||||
keys (assoc keys
|
|
||||||
:on-change (fn [x]
|
|
||||||
(re-frame/dispatch (-> event
|
|
||||||
(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")))
|
|
||||||
keys (dissoc keys :field :subscription :event :spec)]
|
|
||||||
(into [dom keys] (with-keys rest))))
|
|
||||||
|
|
||||||
(defmethod do-bind "money" [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
|
|
||||||
:on-change (fn [x]
|
|
||||||
(re-frame/dispatch (-> event
|
|
||||||
(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")))
|
|
||||||
keys (dissoc keys :field :subscription :event :spec)]
|
|
||||||
(into [dom keys] (with-keys rest))))
|
|
||||||
|
|
||||||
(defmethod do-bind :default [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
|
|
||||||
:on-change (dispatch-value-change (conj event field))
|
|
||||||
: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))))
|
|
||||||
|
|
||||||
(defn bind-field [all]
|
|
||||||
(apply do-bind all))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn horizontal-field [label & controls]
|
|
||||||
[:div.field.is-horizontal
|
|
||||||
(when label
|
|
||||||
[:div.field-label
|
|
||||||
label
|
|
||||||
])
|
|
||||||
(into
|
|
||||||
[:div.field-body]
|
|
||||||
(with-keys (map (fn [x] [:div.field x]) controls)))])
|
|
||||||
|
|
||||||
(defn coerce-date [d]
|
(defn coerce-date [d]
|
||||||
(cond (and (string? d)
|
(cond (and (string? d)
|
||||||
(some->> (re-find #"^(\d{4})" d)
|
(some->> (re-find #"^(\d{4})" d)
|
||||||
|
|||||||
Reference in New Issue
Block a user