Lots of less customization when creating and editing forms

This commit is contained in:
2023-10-20 11:38:29 -07:00
parent e3443a3dd8
commit c0db7eb763
7 changed files with 318 additions and 91 deletions

View File

@@ -109,7 +109,7 @@
.choices__list--multiple {
}
.choices__inner {
@apply bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 dark:bg-gray-700 p-1 !important;
@apply bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 dark:bg-gray-700 p-1 group-[.has-error]:bg-red-50 group-[.has-error]:border-red-500 group-[.has-error]:text-red-900 group-[.has-error]:placeholder-red-700 group-[.has-error]:focus:ring-red-500 group-[.has-error]:dark:bg-gray-700 group-[.has-error]:focus:border-red-500 group-[.has-error]:dark:text-red-500 group-[.has-error]:dark:placeholder-red-500 group-[.has-error]:dark:border-red-500 !important;
}
.choices:focus-within .choices__inner {

View File

@@ -2571,6 +2571,32 @@ input:checked + .toggle-bg {
--tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
}
.group.has-error .choices__inner {
--tw-border-opacity: 1 !important;
border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
--tw-bg-opacity: 1 !important;
background-color: rgb(255 230 230 / var(--tw-bg-opacity)) !important;
--tw-text-opacity: 1 !important;
color: rgb(51 1 1 / var(--tw-text-opacity)) !important;
}
.group.has-error .choices__inner::-moz-placeholder {
--tw-placeholder-opacity: 1 !important;
color: rgb(153 2 2 / var(--tw-placeholder-opacity)) !important;
}
.group.has-error .choices__inner::placeholder {
--tw-placeholder-opacity: 1 !important;
color: rgb(153 2 2 / var(--tw-placeholder-opacity)) !important;
}
.group.has-error .choices__inner:focus {
--tw-border-opacity: 1 !important;
border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
--tw-ring-opacity: 1 !important;
--tw-ring-color: rgb(255 3 3 / var(--tw-ring-opacity)) !important;
}
:is(.dark .choices__inner) {
--tw-border-opacity: 1 !important;
border-color: rgb(75 85 99 / var(--tw-border-opacity)) !important;
@@ -2597,6 +2623,25 @@ input:checked + .toggle-bg {
--tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
}
.group.has-error :is(.dark .choices__inner) {
--tw-border-opacity: 1 !important;
border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
--tw-bg-opacity: 1 !important;
background-color: rgb(55 65 81 / var(--tw-bg-opacity)) !important;
--tw-text-opacity: 1 !important;
color: rgb(255 3 3 / var(--tw-text-opacity)) !important;
}
.group.has-error :is(.dark .choices__inner)::-moz-placeholder {
--tw-placeholder-opacity: 1 !important;
color: rgb(255 3 3 / var(--tw-placeholder-opacity)) !important;
}
.group.has-error :is(.dark .choices__inner)::placeholder {
--tw-placeholder-opacity: 1 !important;
color: rgb(255 3 3 / var(--tw-placeholder-opacity)) !important;
}
.choices:focus-within .choices__inner {
--tw-border-opacity: 1 !important;
border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
@@ -2945,6 +2990,41 @@ input:checked + .toggle-bg {
color: rgb(17 24 39 / var(--tw-text-opacity));
}
.group.has-error .group-\[\.has-error\]\:border-red-500 {
--tw-border-opacity: 1;
border-color: rgb(255 3 3 / var(--tw-border-opacity));
}
.group.has-error .group-\[\.has-error\]\:bg-red-50 {
--tw-bg-opacity: 1;
background-color: rgb(255 230 230 / var(--tw-bg-opacity));
}
.group.has-error .group-\[\.has-error\]\:text-red-900 {
--tw-text-opacity: 1;
color: rgb(51 1 1 / var(--tw-text-opacity));
}
.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(153 2 2 / var(--tw-placeholder-opacity));
}
.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(153 2 2 / var(--tw-placeholder-opacity));
}
.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus {
--tw-border-opacity: 1;
border-color: rgb(255 3 3 / var(--tw-border-opacity));
}
.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(255 3 3 / var(--tw-ring-opacity));
}
:is(.dark .dark\:block) {
display: block;
}
@@ -3125,6 +3205,11 @@ input:checked + .toggle-bg {
color: rgb(255 53 53 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-red-500) {
--tw-text-opacity: 1;
color: rgb(255 3 3 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-white) {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity));
@@ -3135,11 +3220,6 @@ input:checked + .toggle-bg {
color: rgb(250 202 21 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-red-500) {
--tw-text-opacity: 1;
color: rgb(255 3 3 / var(--tw-text-opacity));
}
:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity));
@@ -3282,6 +3362,31 @@ input:checked + .toggle-bg {
color: rgb(255 255 255 / var(--tw-text-opacity));
}
.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500) {
--tw-border-opacity: 1;
border-color: rgb(255 3 3 / var(--tw-border-opacity));
}
.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700) {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
}
.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500) {
--tw-text-opacity: 1;
color: rgb(255 3 3 / var(--tw-text-opacity));
}
.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder {
--tw-placeholder-opacity: 1;
color: rgb(255 3 3 / var(--tw-placeholder-opacity));
}
.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder {
--tw-placeholder-opacity: 1;
color: rgb(255 3 3 / var(--tw-placeholder-opacity));
}
@media (min-width: 640px) {
.sm\:block {
display: block;

View File

@@ -341,8 +341,6 @@
(nat-int? value) (dc/pull (dc/db conn) d-accounts/default-read))
client-id)))})])
(defn- transaction-rule-account-row*
[transaction-rule account]
(com/data-grid-row {}
@@ -352,56 +350,58 @@
(com/hidden {:name (fc/field-name)
:value (fc/field-value)}))
(fc/with-field :transaction-rule-account/account
(com/data-grid-cell {}
[:div {:hx-trigger (hx/trigger-field-change :name "transaction-rule/client"
:from "#edit-form")
:hx-include "#edit-form"
:hx-vals (hx/vals {:name account-name})
:hx-ext "rename-params"
:hx-rename-params-ex (hx/json {:transaction-rule/client "client-id"
:name "name"
account-name "value"})
:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
:hx-swap "innerHTML"}
(account-typeahead* {:value (fc/field-value)
:client-id (:db/id (:transaction-rule/client transaction-rule))
:name (fc/field-name)})
(println "HERE" (cursor/path fc/*current*))
(println "DATA "fc/*form-data*)
(println "ERR" fc/*form-errors*)
(println (fc/field-errors))
(com/errors {:errors (fc/field-errors)})]))
(com/data-grid-cell
{}
(com/validated-field
{:errors (fc/field-errors)}
[:div {:hx-trigger (hx/trigger-field-change :name "transaction-rule/client"
:from "#edit-form")
:hx-include "#edit-form"
:hx-vals (hx/vals {:name account-name})
:hx-ext "rename-params"
:hx-rename-params-ex (hx/json {:transaction-rule/client "client-id"
:name "name"
account-name "value"})
:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
:hx-swap "innerHTML"}
(account-typeahead* {:value (fc/field-value)
:client-id (:db/id (:transaction-rule/client transaction-rule))
:name (fc/field-name)})])))
(fc/with-field :transaction-rule-account/location
(com/data-grid-cell {}
[:div [:div {:hx-trigger (hx/triggers
(hx/trigger-field-change :name "transaction-rule/client"
:from "#edit-form")
(hx/trigger-field-change :name account-name
:from "#edit-form"))
:hx-include "#edit-form"
:hx-vals (hx/vals {:name (fc/field-name)})
:hx-ext "rename-params"
:hx-rename-params-ex (hx/json {"transaction-rule/client" "client-id"
account-name "account-id"
"name" "name"
(fc/field-name) "value"})
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
:hx-swap "innerHTML"}
(location-select* {:name (fc/field-name)
:account-location (:account/location (cond->> (:transaction-rule-account/account @account)
(nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
'[:account/location])))
:client-locations (:client/locations (:transaction-rule/client transaction-rule))
:value (fc/field-value)})]
(com/errors {:errors (fc/field-errors)})]
))
(com/data-grid-cell
{}
(com/validated-field
{:errors (fc/field-errors)}
[:div [:div {:hx-trigger (hx/triggers
(hx/trigger-field-change :name "transaction-rule/client"
:from "#edit-form")
(hx/trigger-field-change :name account-name
:from "#edit-form"))
:hx-include "#edit-form"
:hx-vals (hx/vals {:name (fc/field-name)})
:hx-ext "rename-params"
:hx-rename-params-ex (hx/json {"transaction-rule/client" "client-id"
account-name "account-id"
"name" "name"
(fc/field-name) "value"})
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
:hx-swap "innerHTML"}
(location-select* {:name (fc/field-name)
:account-location (:account/location (cond->> (:transaction-rule-account/account @account)
(nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
'[:account/location])))
:client-locations (:client/locations (:transaction-rule/client transaction-rule))
:value (fc/field-value)})]])))
(fc/with-field :transaction-rule-account/percentage
(com/data-grid-cell (com/money-input {:name (fc/field-name)
:class "w-16"
:value (some-> (fc/field-value)
(* 100 )
(long ))})
(com/errors {:errors (fc/field-errors)})))))
(com/data-grid-cell
{}
(com/validated-field
{:errors (fc/field-errors)}
(com/money-input {:name (fc/field-name)
:class "w-16"
:value (some-> (fc/field-value)
(* 100 )
(long ))}))))))
(com/data-grid-cell
(com/a-icon-button
{"_" (hiccup/raw "on click halt the event then transition the closest <tr />'s opacity to 0 then remove closest <tr />")
@@ -434,6 +434,7 @@
:errors (fc/field-errors)}
[:div.w-96
(com/typeahead {:name (fc/field-name)
:error? (fc/error?)
:class "w-96"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :company-search)
@@ -465,6 +466,7 @@
(com/validated-field {:label "Description"
:errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
:error? (fc/error?)
:placeholder "HOME DEPOT"
:class "w-96"
:value (fc/field-value)})))
@@ -489,19 +491,19 @@
(com/field {:label "Day of month"}
[:div.flex.gap-2
(fc/with-field :transaction-rule/dom-gte
[:div.flex.flex-col
(com/int-input {:name (fc/field-name)
:placeholder ">="
:class "w-24"
:value (fc/field-value)})
(com/errors {:errors (fc/field-errors)})])
(com/validated-field
{:errors (fc/field-errors)}
(com/int-input {:name (fc/field-name)
:placeholder ">="
:class "w-24"
:value (fc/field-value)})))
(fc/with-field :transaction-rule/dom-lte
[:div.flex.flex-col
(com/int-input {:name (fc/field-name)
:placeholder ">="
:class "w-24"
:value (fc/field-value)})
(com/errors {:errors (fc/field-errors)})])])
(com/validated-field
{:errors (fc/field-errors)}
(com/int-input {:name (fc/field-name)
:placeholder ">="
:class "w-24"
:value (fc/field-value)})))])
[:h2.text-lg "Outcomes"]
(fc/with-field :transaction-rule/vendor
@@ -625,7 +627,7 @@
(def transaction-rule-schema (mc/schema
[:map
[:db/id {:optional true} [:maybe entity-id]]
[:transaction-rule/client entity-id]
[:transaction-rule/client {:optional true} [:maybe entity-id]]
[:transaction-rule/description [:and regex
[:string {:min 3}]]]
[:transaction-rule/bank-account [:maybe entity-id]]
@@ -639,7 +641,7 @@
(many-entity {:min 1}
[:db/id [:or entity-id temp-id]]
[:transaction-rule-account/account entity-id]
[:transaction-rule-account/location :string]
[:transaction-rule-account/location [:string {:min 1 :error/message "required"}]]
[:transaction-rule-account/percentage percentage])]]))
(def key->handler

View File

@@ -1,17 +1,28 @@
(ns auto-ap.ssr.components.inputs
(:require
[hiccup2.core :as hiccup]
[auto-ap.ssr.hiccup-helper :as hh]
[clojure.string :as str]))
(def default-input-classes
["bg-gray-50" "border" "text-sm" "rounded-lg" "" "block"
"p-2.5" "border-gray-300" "text-gray-900" "focus:ring-blue-500" "focus:border-blue-500"
"dark:bg-gray-700" "dark:border-gray-600" "dark:placeholder-gray-400" "dark:text-white"
"dark:focus:ring-blue-500" "dark:focus:border-blue-500"
"group-[.has-error]:bg-red-50" "group-[.has-error]:border-red-500" "group-[.has-error]:text-red-900"
"group-[.has-error]:placeholder-red-700" "group-[.has-error]:focus:ring-red-500"
"group-[.has-error]:dark:bg-gray-700" "group-[.has-error]:focus:border-red-500"
"group-[.has-error]:dark:text-red-500" "group-[.has-error]:dark:placeholder-red-500"
"group-[.has-error]:dark:border-red-500"])
(defn select- [params & children]
(into
[:select (-> params
(dissoc :allow-blank? :value :options)
(update
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
)
:class (fnil hh/add-class "") default-input-classes))
(cond->>
(map (fn [[k v]]
[:option {:value k :selected (= k (:value params))} v])
@@ -62,21 +73,22 @@ c.clearChoices();
(if (= :small size)
(str " " "text-xs p-2")
(str " " "text-sm p-2.25")))
(defn text-input- [{:keys [size] :as params}]
(defn text-input- [{:keys [size error?] :as params}]
[:input
(-> params
(dissoc :error?)
(update
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
(update :class #(str % (use-size size)))
)
])
:class (fnil hh/add-class "") default-input-classes)
(update :class #(str % (use-size size))))])
(defn money-input- [{:keys [size] :as params}]
[:input
(-> params
(update
:class str " bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-blue-500 focus:border-blue-500 block dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 text-right appearance-none"
)
(update :class (fnil hh/add-class "") default-input-classes)
(update :class hh/add-class "appearance-none text-right")
(update :class #(str % (use-size size)))
(assoc :type "number"
:step "0.01")
@@ -85,21 +97,18 @@ c.clearChoices();
(defn int-input- [{:keys [size] :as params}]
[:input
(-> params
(update
:class str " bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-blue-500 focus:border-blue-500 block dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 text-right appearance-none"
)
(update :class (fnil hh/add-class "") default-input-classes)
(update :class hh/add-class "appearance-none text-right")
(update :class #(str % (use-size size)))
(assoc :type "number"
:step "1")
(dissoc :size))
])
(dissoc :size))])
(defn date-input- [{:keys [size] :as params}]
[:div
[:input
(-> params
(update
:class str " bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-blue-500 focus:border-blue-500 block dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
(update :class (fnil hh/add-class "") default-input-classes)
(assoc :type "text")
(assoc "_" (hiccup/raw "init initDatepicker(me)"))
(assoc "hx-on" (hiccup/raw "changeDate: htmx.trigger(this, \"change\")
@@ -115,8 +124,9 @@ c.clearChoices();
[:p.mt-2.text-xs.text-red-600.dark:text-red-500.h-4 (str/join ", " errors)]))
(defn field- [params & rest]
[:div {:id (:id params)}
[:label {:class "block mb-2 text-sm font-medium text-gray-900 dark:text-white"} (:label params)]
[:div {:id (:id params) :class (hh/add-class "group" (:class params))}
(when (:label params)
[:label {:class "block mb-2 text-sm font-medium text-gray-900 dark:text-white"} (:label params)])
rest
(when (:error-source params)
(field-errors- {:source (:error-source params)
@@ -128,7 +138,9 @@ c.clearChoices();
(str/join ", " (filter string? errors)))])
(defn validated-field- [params & rest]
(field- (dissoc params :errors)
(field- (cond-> params
true (dissoc :errors)
(sequential? (:errors params)) (update :class #(hh/add-class (or % "") "has-error")))
rest
(errors- {:errors (:errors params)})))

View File

@@ -35,4 +35,12 @@
([cursor]
(get-in *form-errors* (cursor/path cursor))))
(defn error?
([]
(error? *current*))
([cursor]
(let [errors (get-in *form-errors* (cursor/path cursor))]
(and (sequential? errors)
(every? string? errors)))))

View File

@@ -0,0 +1,98 @@
(ns auto-ap.ssr.hiccup-helper
(:require [clojure.string :as str]
[hiccup2.core :as hiccup]
[hiccup.util :as hu]
[clojure.set :as set]))
(defprotocol ClassHelper
(add-class [this add])
(remove-class [this remove])
(replace-class [this remove add])
(remove-wildcard [this wildcard])
(replace-wildcard [this wildcard add])
(replace-tw [this add]))
(defn string->class-list [n]
(let [class-set (atom (set (str/split (or n "") #" ")))]
(reify
ClassHelper
(add-class [this add]
(if (sequential? add)
(swap! class-set into add)
(swap! class-set into (str/split (str (or add "")) #" ")))
this)
(remove-class [this remove]
(if (sequential? remove)
(swap! class-set set/difference (set remove))
(swap! class-set disj remove))
this)
(replace-class [this remove add]
(remove-class this remove)
(add-class this add)
this)
(remove-wildcard [this wildcard]
(if (sequential? wildcard)
(reduce
remove-wildcard
this
wildcard)
(reduce
remove-class
this
(filter (fn [c]
(str/starts-with? c wildcard)
) @class-set)))
this)
(replace-wildcard [this wildcard add]
(remove-wildcard this wildcard)
(add-class this add)
this)
(replace-tw [this add]
;; TODO
)
Object
(toString [this]
(str/join " " @class-set)))))
(extend-protocol ClassHelper
String
(add-class [this add]
(add-class (string->class-list this) add))
(remove-class [this remove]
(remove-class (string->class-list this) remove)
)
(replace-class [this remove add]
(replace-class (string->class-list this) remove add))
(remove-wildcard [this wildcard]
(remove-wildcard (string->class-list this) wildcard))
(replace-wildcard [this wildcard add]
(replace-wildcard (string->class-list this) wildcard add))
(add-tw [this tw]
(replace-tw (string->class-list this)
tw)
))
(str (hiccup/html [:div {:class (-> "hello bryce hello-1 hello-2"
(replace-wildcard ["hello-" "b"] ["hi" "there"]))}]))

View File

@@ -0,0 +1,2 @@
(ns auto-ap.ssr.tailwind-util)