Add vendor pre-population for bulk code and individual edit forms

- Add vendor-changed HTMX handlers for both bulk code and individual edit
- Pre-populate default account at 100% when vendor is selected and no accounts exist
- Fix render-accounts-section to render from step-params correctly
- Change bulk code vendor-changed from hx-get to hx-post to include form data
- Add routes for vendor-changed endpoints
- Update e2e tests to cover vendor pre-population
- Run lein cljfmt fix across codebase
This commit is contained in:
2026-05-21 14:45:19 -07:00
parent 8bd0cee1b1
commit ba87805d4c
210 changed files with 8694 additions and 9627 deletions

View File

@@ -1,39 +1,37 @@
(ns auto-ap.ssr.grid-page-helper
(:require
[auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.logging :as alog]
[auto-ap.query-params :as query-params]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.hiccup-helper :as hh]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.ui :refer [base-page]]
[auto-ap.ssr.utils :refer [html-response main-transformer]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[cemerick.url :as url]
[clojure.string :as str]
[hiccup.util :as hu]
[malli.core :as m]
[malli.transform :as mt2]
[taoensso.encore :refer [filter-vals]]
[clojure.java.io :as io]
[clojure.data.csv :as csv]))
(ns auto-ap.ssr.grid-page-helper
(:require
[auto-ap.graphql.utils :refer [extract-client-ids]]
[auto-ap.logging :as alog]
[auto-ap.query-params :as query-params]
[auto-ap.routes.utils
:refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.hiccup-helper :as hh]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.ui :refer [base-page]]
[auto-ap.ssr.utils :refer [html-response main-transformer]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[cemerick.url :as url]
[clojure.string :as str]
[hiccup.util :as hu]
[malli.core :as m]
[malli.transform :as mt2]
[taoensso.encore :refer [filter-vals]]
[clojure.java.io :as io]
[clojure.data.csv :as csv]))
(defn row* [{:keys [check-box-warning? check-boxes?] :as gridspec} user entity {:keys [flash? delete-after-settle? request class] :as options}]
(let [cells (if check-boxes?
[(com/data-grid-cell {:class "relative"}
[(com/data-grid-cell {:class "relative"}
(let [cb (com/checkbox {:name "id" :value ((:id-fn gridspec) entity)
:x-model "selected"})]
(if (and check-box-warning? (check-box-warning? entity))
(do
[:div.bg-yellow-100.absolute.inset-0.flex.items-center.px-4.py-2
[:div {:class "absolute inset-0 bg-yellow-50 z-0",
(if (and check-box-warning? (check-box-warning? entity))
(do
[:div.bg-yellow-100.absolute.inset-0.flex.items-center.px-4.py-2
[:div {:class "absolute inset-0 bg-yellow-50 z-0",
:style "background-image: linear-gradient(135deg, rgba(0, 0, 0, 0.1) 12.5%, transparent 12.5%, transparent 50%, rgba(0, 0, 0, 0.1) 50%, rgba(0, 0, 0, 0.1) 62.5%, transparent 62.5%, transparent);\n background-size: 10px 10px;"}]
@@ -63,7 +61,7 @@
(cond-> {:class (cond-> (or class "")
flash? (hh/add-class "live-added group"))
:data-id ((:id-fn gridspec) entity)}
delete-after-settle?
delete-after-settle?
(assoc "@htmx:after-settle.camel" "setTimeout(() => $el.remove(), 400)"))
cells)))
@@ -89,7 +87,7 @@
[:div.h-4.w-4 svg/x]]]]))
"default sort"))
(defn create-break-table-fn [break-table grid-spec ]
(defn create-break-table-fn [break-table grid-spec]
(let [last (atom nil)]
(fn [request entity]
(let [break-table-value (break-table request entity)]
@@ -106,7 +104,6 @@
"desc")))
s)))
(defn table* [grid-spec user {{:keys [start per-page flash-id sort]} :parsed-query-params :as request}]
(alog/info ::TABLE-QP
:qp (:query-params request)
@@ -123,7 +120,7 @@
:raw? (:raw? grid-spec)
:title [:div.flex.gap-2 (if (string? (:title grid-spec))
(:title grid-spec)
((:title grid-spec) request)) ]
((:title grid-spec) request))]
:route (:route grid-spec)
:root-params {:x-data (hx/json {:sort (sort->query sort)})
"x-hx-val:sort" "sort"}
@@ -154,11 +151,11 @@
"selected" "all-selected"))
:color :secondary-light}
[:div.w-4.h-4 svg/download])))
:rows
(let [break-table-fn (some-> grid-spec :break-table ( create-break-table-fn grid-spec))]
:rows
(let [break-table-fn (some-> grid-spec :break-table (create-break-table-fn grid-spec))]
(for [entity entities
row (if-let [break-table-row (when break-table-fn (break-table-fn request entity))]
[break-table-row (row* grid-spec user entity {:flash? (= flash-id ((:id-fn grid-spec) entity)) :request request})]
[(row* grid-spec user entity {:flash? (= flash-id ((:id-fn grid-spec) entity)) :request request})])]
row))
@@ -203,9 +200,6 @@
[])))
(com/data-grid-header {}))})))
(defn wrap-trim-client-ids [handler]
(fn trim-client-ids [request]
(let [valid-clients (extract-client-ids (:clients request)
@@ -218,8 +212,7 @@
set)]
(handler (assoc request :trimmed-clients valid-clients)))))
(defn table-route [grid-spec & {:keys [push-url?] :or { push-url? true}}]
(defn table-route [grid-spec & {:keys [push-url?] :or {push-url? true}}]
(cond-> (fn table [{:keys [identity] :as request}]
(html-response (table*
@@ -247,7 +240,7 @@
;; make it so that it rerenders the date range component, along with a hx-trigger change header
(defn csv-route [{:keys [fetch-page headers page->csv-entities]} & {:keys []}]
(cond-> (fn csv-route [{:keys [identity] :as request}]
(let [page-results (fetch-page (assoc-in request [:query-params :per-page] Long/MAX_VALUE))
csv-entities ((or page->csv-entities (fn [[entities]] entities)) page-results)
csv-content (with-open [i (java.io.StringWriter.)]
@@ -255,13 +248,13 @@
(into [(for [h headers
:when ((:render-for h #{:html :csv}) :csv)]
(:name h))]
(for [e csv-entities ]
(for [e csv-entities]
(for [h headers
:when ((:render-for h #{:html :csv})
:csv)]
((or (:render-csv h) (comp str (:render h))) e)))))
(.toString i))]
{:headers {"Content-Type" "text/csv"}
:body csv-content}))
true (wrap-trim-client-ids)
@@ -285,7 +278,7 @@
:request request}
(apply com/breadcrumbs {} (:breadcrumbs grid-spec))
(when (:above-grid grid-spec)
( (:above-grid grid-spec) request))
((:above-grid grid-spec) request))
[:div {:x-data (hx/json {:selected [] :all_selected false :type (:entity-name grid-spec)})
"x-on:copy" "if (selected.length > 0) {$clipboard(JSON.stringify({'type': type, 'selected': selected}))}"
"x-on:client-selected.document" "selected=[]; all_selected=false"