Makes reports page work with new tailwind
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
[clj-time.coerce :as c]
|
||||
[datomic.api :as dc]))
|
||||
|
||||
(def default-read '[:db/id :report/client :report/created :report/url :report/name :report/creator])
|
||||
|
||||
(defn raw-graphql-ids [db args]
|
||||
(let [query (cond-> {:query {:find []
|
||||
:in ['$ ]
|
||||
@@ -43,8 +45,7 @@
|
||||
(apply-pagination args))))
|
||||
|
||||
(defn graphql-results [ids db args]
|
||||
(let [results (->> (pull-many db '[:db/id :report/client :report/created :report/url :report/name :report/creator]
|
||||
ids)
|
||||
(let [results (->> (pull-many db default-read ids)
|
||||
(map #(update % :report/created c/from-date))
|
||||
(group-by :db/id))]
|
||||
(->> ids
|
||||
@@ -63,8 +64,3 @@
|
||||
|
||||
[(->> (graphql-results ids-to-retrieve db args))
|
||||
matching-count]))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[auto-ap.ssr.components :as com]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.ui :refer [base-page]]
|
||||
[auto-ap.ssr.utils :refer [html-response]]
|
||||
[auto-ap.ssr.utils :refer [html-response form-data->map path->name]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
@@ -53,7 +53,6 @@
|
||||
[(>= ?d #inst "2022-01-01T08:00")]
|
||||
[(< ?d #inst "2023-01-01T08:00")]
|
||||
[?p :payment/type :payment-type/check]
|
||||
|
||||
[?p :payment/amount ?a]
|
||||
[?p :payment/vendor ?v]]
|
||||
(dc/db conn)
|
||||
@@ -113,7 +112,6 @@
|
||||
[(>= ?d #inst "2022-01-01T08:00")]
|
||||
[(< ?d #inst "2023-01-01T08:00")]
|
||||
[?p :payment/type :payment-type/check]
|
||||
|
||||
[?p :payment/amount ?a]
|
||||
[?p :payment/vendor ?v]]
|
||||
(dc/db conn)
|
||||
@@ -125,134 +123,97 @@
|
||||
[(:client/code client ) amount]))
|
||||
(into []))))
|
||||
|
||||
(defn row* [{:keys [client vendor amount flash?]}]
|
||||
(com/data-grid-row
|
||||
{:class (when flash?
|
||||
"live-added")}
|
||||
(com/data-grid-cell {} (:client/code client))
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
[:div.flex.whitespace-nowrap.items-center.gap-4
|
||||
[:div [:div (:vendor/name vendor)]
|
||||
[:div.text-sm.text-gray-400
|
||||
(or (-> vendor :vendor/legal-entity-name not-empty)
|
||||
(str (-> vendor :vendor/legal-entity-first-name) " "
|
||||
(-> vendor :vendor/legal-entity-middle-name) " "
|
||||
(-> vendor :vendor/legal-entity-last-name)))]]
|
||||
(when-let [t99-type (some-> vendor :vendor/legal-entity-1099-type :db/ident name)]
|
||||
(com/pill
|
||||
{:class "text-xs font-medium"
|
||||
:color :primary}
|
||||
(str/capitalize t99-type))
|
||||
)])
|
||||
(com/data-grid-cell
|
||||
{:class "hidden md:table-cell"}
|
||||
[:div.flex.gap-4
|
||||
(when-let [tin (-> vendor :vendor/legal-entity-tin)]
|
||||
[:span {:class "text-xs font-medium py-0.5 "}
|
||||
tin])
|
||||
(when-let [tin-type (some-> vendor :vendor/legal-entity-tin-type :db/ident name)]
|
||||
(com/pill {:class "text-xs font-medium"
|
||||
:color :yellow}
|
||||
(name tin-type)))])
|
||||
(com/data-grid-cell
|
||||
{:class "hidden lg:table-cell"}
|
||||
(if (-> vendor :vendor/address :address/street1)
|
||||
[:div
|
||||
[:div (-> vendor :vendor/address :address/street1)] " "
|
||||
[:div
|
||||
(-> vendor :vendor/address :address/street2)] " "
|
||||
[:div
|
||||
(-> vendor :vendor/address :address/city) " "
|
||||
(-> vendor :vendor/address :address/state) ","
|
||||
(-> vendor :vendor/address :address/zip)]]
|
||||
[:p.text-sm.italic.text-gray-400 "No address"]))
|
||||
(com/data-grid-cell {}
|
||||
(com/pill {:class "text-xs font-medium"
|
||||
:color :primary}
|
||||
"Paid $" (Math/round amount)))
|
||||
(com/data-grid-right-stack-cell
|
||||
{}
|
||||
(if (cannot-overwrite? vendor)
|
||||
[:div (com/link {:href "mailto:ben@integreatconsult.com"} "Contact Integreat")]
|
||||
(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-dialog
|
||||
:vendor-id (:db/id vendor))
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
svg/pencil)))))
|
||||
(defn table* [{:keys [identity session query-params hx-query-params]} & {:keys [flash-id]}]
|
||||
(println hx-query-params)
|
||||
(let [start (or (some-> (or (get query-params "start") (get hx-query-params "start")) not-empty (Long/parseLong ))
|
||||
(let [start (or (some-> (or (get query-params "start") (get hx-query-params "start")) not-empty (Long/parseLong ))
|
||||
0)
|
||||
per-page (or (some-> (or (get query-params "per-page") (get hx-query-params "per-page")) not-empty (Long/parseLong ))
|
||||
per-page (or (some-> (or (get query-params "per-page") (get hx-query-params "per-page")) not-empty (Long/parseLong ))
|
||||
30)
|
||||
companies (get-1099-companies identity session)
|
||||
total (count companies)
|
||||
total (count companies)
|
||||
companies (subvec companies (Math/min start total) (Math/min (+ start per-page) total))]
|
||||
[:div#vendor-table {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-table
|
||||
:request-method :get)
|
||||
:hx-trigger "clientSelected from:body"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
(com/content-card {}
|
||||
[:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
|
||||
[:div
|
||||
[:h1.text-2xl.mb-3.font-bold "1099 Vendor Info"]
|
||||
[:div {:class "flex items-center flex-1 space-x-4"}
|
||||
[:h5
|
||||
[:span "Total Vendors:"]
|
||||
[:span {:class "dark:text-white pl-4"} (count companies)]]]]
|
||||
[:div {:class "flex flex-col flex-shrink-0 space-y-3 md:flex-row md:items-center lg:justify-end md:space-y-0 md:space-x-3"}
|
||||
(com/button {:color :primary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Add new product")
|
||||
(com/button {:color :secondary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Update stocks 1/250")
|
||||
(com/icon-button {}
|
||||
svg/upload)]]
|
||||
[:div {:class "overflow-x-auto"}
|
||||
(apply com/data-grid {:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {} "Vendor Name")
|
||||
(com/data-grid-header {:class "hidden md:table-cell"} "TIN")
|
||||
(com/data-grid-header {:class "hidden lg:table-cell"} "Address")
|
||||
(com/data-grid-header {})
|
||||
(com/data-grid-header {})]}
|
||||
(for [[client vendor amount] companies]
|
||||
(com/data-grid-row
|
||||
{:class (when (= flash-id
|
||||
(:db/id vendor))
|
||||
"live-added")}
|
||||
(com/data-grid-cell {} (:client/code client))
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
[:div.flex.whitespace-nowrap.items-center.gap-4
|
||||
[:div [:div (:vendor/name vendor)]
|
||||
[:div.text-sm.text-gray-400
|
||||
(or (-> vendor :vendor/legal-entity-name not-empty)
|
||||
(str (-> vendor :vendor/legal-entity-first-name) " "
|
||||
(-> vendor :vendor/legal-entity-middle-name) " "
|
||||
(-> vendor :vendor/legal-entity-last-name)))]]
|
||||
(when-let [t99-type (some-> vendor :vendor/legal-entity-1099-type :db/ident name)]
|
||||
(com/pill
|
||||
{:class "text-xs font-medium"
|
||||
:color :primary}
|
||||
(str/capitalize t99-type))
|
||||
)])
|
||||
(com/data-grid-cell
|
||||
{:class "hidden md:table-cell"}
|
||||
[:div.flex.gap-4
|
||||
(when-let [tin (-> vendor :vendor/legal-entity-tin)]
|
||||
[:span {:class "text-xs font-medium py-0.5 "}
|
||||
tin])
|
||||
(when-let [tin-type (some-> vendor :vendor/legal-entity-tin-type :db/ident name)]
|
||||
(com/pill {:class "text-xs font-medium"
|
||||
:color :yellow}
|
||||
(name tin-type)))])
|
||||
(com/data-grid-cell
|
||||
{:class "hidden lg:table-cell"}
|
||||
(if (-> vendor :vendor/address :address/street1)
|
||||
[:div
|
||||
[:div (-> vendor :vendor/address :address/street1)] " "
|
||||
[:div
|
||||
(-> vendor :vendor/address :address/street2)] " "
|
||||
[:div
|
||||
(-> vendor :vendor/address :address/city) " "
|
||||
(-> vendor :vendor/address :address/state) ","
|
||||
(-> vendor :vendor/address :address/zip)]]
|
||||
[:p.text-sm.italic.text-gray-400 "No address"]))
|
||||
(com/data-grid-cell {}
|
||||
(com/pill {:class "text-xs font-medium"
|
||||
:color :primary}
|
||||
"Paid $" (Math/round amount)))
|
||||
(com/data-grid-right-stack-cell
|
||||
{}
|
||||
(if (cannot-overwrite? vendor)
|
||||
[:div (com/link {:href "mailto:ben@integreatconsult.com"} "Contact Integreat")]
|
||||
(com/icon-button {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-dialog
|
||||
:vendor-id (:db/id vendor))
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
svg/pencil))))))]
|
||||
(com/paginator {:start start
|
||||
:end (Math/min (+ start per-page) total)
|
||||
:per-page per-page
|
||||
:total total
|
||||
:a-params (fn [page]
|
||||
{:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099-vendor-table
|
||||
:request-method :get)
|
||||
"?start=" (* page per-page))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML show:#app:top"})}))]))
|
||||
|
||||
(defn form-data->map [form-data]
|
||||
(reduce-kv
|
||||
(fn [acc k v]
|
||||
(cond (and (string? v)
|
||||
(empty? v))
|
||||
acc
|
||||
|
||||
:else
|
||||
(assoc-in acc (->> (str/split k #"_")
|
||||
(mapv #(apply keyword (str/split % #"/"))))
|
||||
v)))
|
||||
{}
|
||||
form-data))
|
||||
|
||||
(defn path->name [k]
|
||||
(cond (keyword? k)
|
||||
(str (namespace k) "/" (name k))
|
||||
|
||||
(seq k)
|
||||
(str/join "_" (map path->name k))
|
||||
:else k))
|
||||
(com/data-grid-card {:id "vendor-table"
|
||||
:title "1099 Vendor Info"
|
||||
:entity-name "vendors"
|
||||
:route :company-1099-vendor-table
|
||||
:start start
|
||||
:per-page per-page
|
||||
:total total
|
||||
:action-buttons [(com/button {:color :primary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Add new product")
|
||||
(com/button {:color :secondary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Update stocks 1/250")
|
||||
(com/icon-button {}
|
||||
svg/upload)]
|
||||
:rows (for [[client vendor amount] companies]
|
||||
(row* {:client client
|
||||
:vendor vendor
|
||||
:amount amount
|
||||
:flash? (= flash-id
|
||||
(:db/id vendor))}))
|
||||
:headers [(com/data-grid-header {} "Client")
|
||||
(com/data-grid-header {} "Vendor Name")
|
||||
(com/data-grid-header {:class "hidden md:table-cell"} "TIN")
|
||||
(com/data-grid-header {:class "hidden lg:table-cell"} "Address")
|
||||
(com/data-grid-header {})
|
||||
(com/data-grid-header {})]})))
|
||||
|
||||
(defn vendor-save [{:keys [form-params identity route-params] :as request}]
|
||||
(when-not (cannot-overwrite? (dc/pull (dc/db conn) '[*] (Long/parseLong (:vendor-id route-params))))
|
||||
@@ -265,8 +226,6 @@
|
||||
(table* request :flash-id (Long/parseLong (:vendor-id route-params)))
|
||||
:headers {"hx-trigger" "closeModal"}))
|
||||
|
||||
|
||||
|
||||
(defn vendor-dialog [request]
|
||||
(let [vendor (dc/pull (dc/db conn) '[* {:vendor/legal-entity-1099-type [:db/ident]
|
||||
:vendor/legal-entity-tin-type [:db/ident]}] (Long/parseLong (:vendor-id (:params request))))] ;; TODO perms
|
||||
@@ -276,86 +235,86 @@
|
||||
:company-1099-vendor-save
|
||||
:request-method :post
|
||||
:vendor-id (Long/parseLong (:vendor-id (:params request)))))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
[:fieldset {:class "hx-disable"}
|
||||
(com/modal-card {}
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
|
||||
[:div.space-y-6
|
||||
[:div.grid.grid-cols-6.gap-4
|
||||
[:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 1"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street1])
|
||||
:value (-> vendor :vendor/address :address/street1)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true}))]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 2"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street2])
|
||||
:value (-> vendor :vendor/address :address/street2)
|
||||
:placeholder "Suite 200"}))]
|
||||
[:div.col-span-3
|
||||
(com/field {:label "City"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/city])
|
||||
:value (-> vendor :vendor/address :address/city)
|
||||
:placeholder "Cupertino"}))]
|
||||
[:div.col-span-1
|
||||
(com/field {:label "State"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/state])
|
||||
:value (-> vendor :vendor/address :address/state)
|
||||
:placeholder "CA"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Zip"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/zip])
|
||||
:value (-> vendor :vendor/address :address/zip)
|
||||
:placeholder "98102"}))]
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Legal Entity Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-name])
|
||||
:value (-> vendor :vendor/legal-entity-name)
|
||||
:placeholder "Good Restaurant LLC"}))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "First Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-first-name])
|
||||
:value (-> vendor :vendor/legal-entity-first-name)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Middle Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
|
||||
:value (-> vendor :vendor/legal-entity-middle-name)
|
||||
:placeholder "C."}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Last Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-last-name])
|
||||
:value (-> vendor :vendor/legal-entity-last-name)
|
||||
:placeholder "Riley"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-tin])
|
||||
:value (-> vendor :vendor/legal-entity-tin)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-tin-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "1099 Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-1099-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
|
||||
:options [["none" "None"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]}))]
|
||||
[:div.col-span-6
|
||||
(com/button {:color :primary}
|
||||
"Save")]]]
|
||||
[:div])]]))))
|
||||
:hx-target "#vendor-table"
|
||||
:hx-swap "outerHTML swap:300ms"}
|
||||
[:fieldset {:class "hx-disable"}
|
||||
(com/modal-card {}
|
||||
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
|
||||
[:div.space-y-6
|
||||
[:div.grid.grid-cols-6.gap-4
|
||||
[:h4.text-xl.border-b.col-span-6 "Address"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 1"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street1])
|
||||
:value (-> vendor :vendor/address :address/street1)
|
||||
:placeholder "1700 Pennsylvania Ave"
|
||||
:autofocus true}))]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Street 2"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/street2])
|
||||
:value (-> vendor :vendor/address :address/street2)
|
||||
:placeholder "Suite 200"}))]
|
||||
[:div.col-span-3
|
||||
(com/field {:label "City"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/city])
|
||||
:value (-> vendor :vendor/address :address/city)
|
||||
:placeholder "Cupertino"}))]
|
||||
[:div.col-span-1
|
||||
(com/field {:label "State"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/state])
|
||||
:value (-> vendor :vendor/address :address/state)
|
||||
:placeholder "CA"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Zip"}
|
||||
(com/text-input {:name (path->name [:vendor/address :address/zip])
|
||||
:value (-> vendor :vendor/address :address/zip)
|
||||
:placeholder "98102"}))]
|
||||
[:h4.text-xl.border-b.col-span-6 "Legal Entity"]
|
||||
[:div.col-span-6
|
||||
(com/field {:label "Legal Entity Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-name])
|
||||
:value (-> vendor :vendor/legal-entity-name)
|
||||
:placeholder "Good Restaurant LLC"}))]
|
||||
[:div.col-span-6.text-center " - OR -"]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "First Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-first-name])
|
||||
:value (-> vendor :vendor/legal-entity-first-name)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Middle Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
|
||||
:value (-> vendor :vendor/legal-entity-middle-name)
|
||||
:placeholder "C."}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "Last Name"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-last-name])
|
||||
:value (-> vendor :vendor/legal-entity-last-name)
|
||||
:placeholder "Riley"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN"}
|
||||
(com/text-input {:name (path->name [:vendor/legal-entity-tin])
|
||||
:value (-> vendor :vendor/legal-entity-tin)
|
||||
:placeholder "John"}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "TIN Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-tin-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
|
||||
:options [["ein" "EIN"]
|
||||
["ssn" "SSN"]]}))]
|
||||
[:div.col-span-2
|
||||
(com/field {:label "1099 Type"}
|
||||
(com/select {:name (path->name [:vendor/legal-entity-1099-type])
|
||||
:allow-blank? true
|
||||
:value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
|
||||
:options [["none" "None"]
|
||||
["misc" "Misc"]
|
||||
["landlord" "Landlord"]]}))]
|
||||
[:div.col-span-6
|
||||
(com/button {:color :primary}
|
||||
"Save")]]]
|
||||
[:div])]]))))
|
||||
|
||||
(defn vendor-table [request]
|
||||
(html-response (table* request)
|
||||
|
||||
120
src/clj/auto_ap/ssr/company/reports.clj
Normal file
120
src/clj/auto_ap/ssr/company/reports.clj
Normal file
@@ -0,0 +1,120 @@
|
||||
(ns auto-ap.ssr.company.reports
|
||||
(:require
|
||||
[amazonica.aws.s3 :as s3]
|
||||
[auto-ap.datomic :refer [conn]]
|
||||
[auto-ap.datomic.reports :as r]
|
||||
[auto-ap.graphql.utils :refer [assert-admin is-admin?]]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.components :as com]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.ui :refer [base-page]]
|
||||
[auto-ap.ssr.utils :refer [html-response]]
|
||||
[auto-ap.time :as atime]
|
||||
[bidi.bidi :as bidi]
|
||||
[config.core :refer [env]]
|
||||
[datomic.api :as dc]
|
||||
[hiccup2.core :as hiccup]))
|
||||
|
||||
(defn row* [{:keys [flash? report identity delete-after-settle?]}]
|
||||
(com/data-grid-row
|
||||
{:class (when flash?
|
||||
"live-added")
|
||||
"_" (hiccup/raw (when delete-after-settle?" on htmx:afterSettle wait 400ms then remove me"))}
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(:report/name report))
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(when (:report/creator report)
|
||||
(com/pill {:color :primary }
|
||||
(:report/creator report))))
|
||||
(com/data-grid-cell
|
||||
{}
|
||||
(atime/unparse-local (:report/created report)
|
||||
atime/normal-date))
|
||||
(com/data-grid-right-stack-cell
|
||||
{}
|
||||
(com/a-icon-button {:href (:report/url report)}
|
||||
svg/download)
|
||||
(when (is-admin? identity)
|
||||
[:form
|
||||
[:input {:type :hidden :name "id" :value (:db/id report)}]
|
||||
(com/icon-button {:hx-delete (str (bidi/path-for ssr-routes/only-routes
|
||||
:company-reports-delete
|
||||
:request-method :delete))
|
||||
:hx-target "closest tr"}
|
||||
svg/trash)]))))
|
||||
|
||||
(defn table* [{:keys [client start per-page identity session flash-id]}]
|
||||
(let [start (or start 0)
|
||||
per-page (or per-page 30)
|
||||
[reports total] (r/get-graphql {:id identity
|
||||
:start start
|
||||
:per-page per-page
|
||||
:client-id (:db/id client)
|
||||
:sort nil})]
|
||||
(com/data-grid-card {:id "report-table"
|
||||
:title "Reports"
|
||||
:entity-name "reports"
|
||||
:route :company-reports-table
|
||||
:start start
|
||||
:per-page per-page
|
||||
:total total
|
||||
:action-buttons [(com/button {:color :primary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Add new product")
|
||||
(com/button {:color :secondary}
|
||||
(com/button-icon {} svg/refresh)
|
||||
"Update stocks 1/250")
|
||||
(com/icon-button {}
|
||||
svg/upload)]
|
||||
:rows (for [report reports]
|
||||
(row* {:report report
|
||||
:flash? (= flash-id
|
||||
(:db/id report))
|
||||
:identity identity}))
|
||||
:headers [(com/data-grid-header {} "Name")
|
||||
(com/data-grid-header {:class "hidden md:table-cell"} "Created by")
|
||||
(com/data-grid-header {:class "hidden md:table-cell"} "Created")
|
||||
(com/data-grid-header {})]})))
|
||||
|
||||
(defn delete-report [{:keys [query-params hx-query-params form-params identity session] :as request}]
|
||||
(let [[id-to-delete key] (first (dc/q '[:find ?i ?k
|
||||
:in $ ?i
|
||||
:where [?i :report/key ?k]]
|
||||
(dc/db conn)
|
||||
(some-> (get form-params "id") not-empty Long/parseLong)))
|
||||
report (dc/pull (dc/db conn) r/default-read id-to-delete)]
|
||||
(when id-to-delete
|
||||
(s3/delete-object :bucket-name (:data-bucket env)
|
||||
:key key)
|
||||
@(dc/transact conn [[:db/retractEntity id-to-delete]]))
|
||||
(html-response
|
||||
(row* {:report report
|
||||
:flash? true
|
||||
:identity identity
|
||||
:delete-after-settle? true}))))
|
||||
|
||||
(defn reports-table [{:keys [query-params hx-query-params identity session] :as request}]
|
||||
(html-response (table* {:client (:client (:session request))
|
||||
:start (some-> (or (get query-params "start") (get hx-query-params "start")) not-empty (Long/parseLong ))
|
||||
:per-page (some-> (or (get query-params "per-page") (get hx-query-params "per-page")) not-empty (Long/parseLong ))
|
||||
:identity identity
|
||||
:session session})
|
||||
:headers {"hx-push-url" (str "?start=" (get (:query-params request) "start"))}))
|
||||
|
||||
(defn page [{:keys [query-params hx-query-params identity session] :as request}]
|
||||
(base-page
|
||||
request
|
||||
(com/page {:nav (com/company-aside-nav)
|
||||
:active-client (:client (:session request))
|
||||
:identity (:identity request)}
|
||||
(com/breadcrumbs {}
|
||||
[:a {:href "#"} "My Company"]
|
||||
[:a {:href "#"} "Reports"])
|
||||
(table* {:client (:client (:session request))
|
||||
:start (some-> (or (get query-params "start") (get hx-query-params "start")) not-empty (Long/parseLong ))
|
||||
:per-page (some-> (or (get query-params "per-page") (get hx-query-params "per-page")) not-empty (Long/parseLong ))
|
||||
:identity identity
|
||||
:session session}))
|
||||
nil))
|
||||
@@ -12,14 +12,14 @@
|
||||
|
||||
(defn dropdown-search-results* [{:keys [options]}]
|
||||
[:ul
|
||||
(for [option options]
|
||||
(for [[id company-name]options]
|
||||
[:li
|
||||
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
|
||||
|
||||
[:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
|
||||
"_" (hiccup/raw "on click set value of <#company-search-value/> to @data-value then send selected to #company-dropdown")
|
||||
:data-value (get option "key")}
|
||||
(get option "value")]]])])
|
||||
:data-value id}
|
||||
company-name]]])])
|
||||
|
||||
(defn get-clients [identity query]
|
||||
(dc/q '[:find ?c ?n
|
||||
@@ -33,10 +33,7 @@
|
||||
|
||||
(defn dropdown-search-results [{:keys [identity] :as request}]
|
||||
(html-response
|
||||
(dropdown-search-results* {:options (->> (get-clients identity (get (:query-params request) "search-text"))
|
||||
(map (fn [[k v]]
|
||||
{"key" k
|
||||
"value" v})))
|
||||
(dropdown-search-results* {:options (get-clients identity (get (:query-params request) "search-text"))
|
||||
:client (:client (:session request))})))
|
||||
|
||||
(defn dropdown [{:keys [client]}]
|
||||
@@ -79,14 +76,7 @@
|
||||
:hx-target "#company-search-results"
|
||||
:hx-swap "innerHTML"} ]]
|
||||
[:input#company-search-value {:type "hidden"
|
||||
:autocomplete "off"
|
||||
:name "search-client"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "change changed"} ]]
|
||||
:name "search-client"}]]
|
||||
[:div.divide-y.divide-gray-100
|
||||
[:div#company-search-results {:class "h-48 px-3 pb-3 overflow-y-auto text-sm text-gray-700 dark:text-gray-200"}]
|
||||
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
[auto-ap.ssr.components.navbar :as navbar]
|
||||
[auto-ap.ssr.components.page :as page]
|
||||
[auto-ap.ssr.components.data-grid :as data-grid]
|
||||
[auto-ap.ssr.components.tags :as tags]))
|
||||
[auto-ap.ssr.components.tags :as tags]
|
||||
[auto-ap.ssr.components.paginator :as paginator]))
|
||||
|
||||
|
||||
(def breadcrumbs breadcrumbs/breadcrumbs-)
|
||||
(def button buttons/button-)
|
||||
(def button-icon buttons/button-icon-)
|
||||
(def icon-button buttons/icon-button-)
|
||||
(def a-icon-button buttons/a-icon-button-)
|
||||
(def modal dialog/modal-)
|
||||
(def modal-card dialog/modal-card-)
|
||||
|
||||
@@ -44,62 +46,9 @@
|
||||
:class (str "font-medium text-blue-600 dark:text-blue-500 hover:underline " class)}]
|
||||
children))
|
||||
|
||||
(defn bound [x y z]
|
||||
(cond
|
||||
(< z x)
|
||||
x
|
||||
(< y x)
|
||||
x
|
||||
(> y z)
|
||||
z
|
||||
:else
|
||||
y))
|
||||
|
||||
(def elipsis-button
|
||||
[:p {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400"} "..."])
|
||||
|
||||
(defn paginator- [{:keys [start per-page end total a-params]}]
|
||||
(let [per-page (or per-page 20)
|
||||
max-buttons 5
|
||||
buttons-before (Math/floor (/ max-buttons 2))
|
||||
total-pages (long (Math/max (long 1) (long (Math/ceil (/ total per-page)))))
|
||||
current-page (long (Math/floor (/ start per-page)))
|
||||
first-page-button (bound 0 (- current-page buttons-before) (- total-pages max-buttons))
|
||||
all-buttons (into [] (for [x (range total-pages)]
|
||||
[:li
|
||||
[:a (-> (a-params x)
|
||||
(update
|
||||
:class #(cond-> %
|
||||
true (str " flex items-center justify-center px-3 py-2 text-sm leading-tight border ")
|
||||
|
||||
(= current-page x)
|
||||
(str " text-primary-600 bg-primary-50 border-primary-300 hover:bg-primary-100 hover:text-primary-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white")
|
||||
|
||||
(not= current-page x)
|
||||
(str " text-gray-500 bg-white border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white")))
|
||||
(assoc :href "#"))
|
||||
(inc x)]]))
|
||||
|
||||
|
||||
last-page-button (Math/min (long total-pages) (long (+ max-buttons first-page-button)))
|
||||
|
||||
extended-last-page-button (when (not= last-page-button total-pages)
|
||||
(list
|
||||
elipsis-button
|
||||
(last all-buttons)))
|
||||
(def paginator paginator/paginator-)
|
||||
(def data-grid-card data-grid/data-grid-card-)
|
||||
|
||||
extended-first-page-button (when (not= first-page-button 0)
|
||||
(list
|
||||
(first all-buttons)
|
||||
elipsis-button))]
|
||||
[:nav
|
||||
[:ul {:class "inline-flex items-stretch -space-x-px"}
|
||||
extended-first-page-button
|
||||
(apply list (subvec all-buttons first-page-button last-page-button))
|
||||
extended-last-page-button]]))
|
||||
|
||||
(defn paginator [{:keys [start per-page end total a-params] :as params}]
|
||||
[:nav {:class "flex flex-col items-start justify-between p-4 space-y-3 md:flex-row md:items-center md:space-y-0", :aria-label "Table navigation"}
|
||||
[:span {:class "text-sm font-normal text-gray-500 dark:text-gray-400"}
|
||||
[:span {:class "font-semibold text-gray-900 dark:text-white"} (str (inc start)) "-" (str end) " of " (str total)]]
|
||||
(paginator- params)])
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
(ns auto-ap.ssr.components.aside
|
||||
(:require [auto-ap.ssr.svg :as svg]
|
||||
[hiccup2.core :as hiccup]))
|
||||
[hiccup2.core :as hiccup]
|
||||
[bidi.bidi :as bidi]
|
||||
[auto-ap.ssr-routes :as ssr-routes]))
|
||||
|
||||
(defn menu-button- [params & children]
|
||||
[:a (-> params
|
||||
@@ -188,7 +190,9 @@
|
||||
[:ul {:class "space-y-2"}
|
||||
|
||||
[:li
|
||||
(menu-button- {:icon svg/report}
|
||||
(menu-button- {:icon svg/report
|
||||
:href (bidi/path-for ssr-routes/only-routes
|
||||
:company-reports)}
|
||||
"Reports")]
|
||||
[:li
|
||||
(menu-button- {:icon svg/bank}
|
||||
@@ -198,5 +202,8 @@
|
||||
"Vendors")]
|
||||
|
||||
[:li
|
||||
(menu-button- {:icon svg/government-building}
|
||||
"1099 Vendor Info")]])
|
||||
(menu-button- {:icon svg/government-building
|
||||
:href (bidi/path-for ssr-routes/only-routes
|
||||
:company-1099)}
|
||||
"1099 Vendor Info"
|
||||
)]])
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
(defn icon-button- [params & children]
|
||||
(into
|
||||
[:button (update params :class str " inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center p-3 text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100")
|
||||
[:div.htmx-indicator.flex.items-center
|
||||
(svg/spinner {:class "inline w-4 h-4 text-white"})]
|
||||
[:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center (into [:div.h-4.w-4] children)]]))
|
||||
|
||||
(defn a-icon-button- [params & children]
|
||||
(into
|
||||
[:a (update params :class str " inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center p-3 text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100")
|
||||
[:div.h-4.w-4 children]]))
|
||||
|
||||
(defn save-button- [params & children]
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
(ns auto-ap.ssr.components.data-grid)
|
||||
(ns auto-ap.ssr.components.data-grid
|
||||
(:require
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.components.card :refer [content-card-]]
|
||||
[auto-ap.ssr.components.paginator :refer [paginator-]]
|
||||
[bidi.bidi :as bidi]))
|
||||
|
||||
(defn header- [params & rest]
|
||||
(into [:th.px-4.py-3 {:scope "col" :class (:class params)} ] rest))
|
||||
|
||||
|
||||
(defn row- [params & rest]
|
||||
(into [:tr {:class (cond-> "border-b dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700"
|
||||
|
||||
(:class params) (str " " (:class params)))}] rest))
|
||||
(into [:tr (update params
|
||||
:class str " border-b dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700")] rest))
|
||||
|
||||
(defn cell- [params & rest]
|
||||
(into [:td.px-4.py-2 {:class (:class params)}] rest))
|
||||
@@ -32,3 +36,50 @@
|
||||
(into
|
||||
[:tbody]
|
||||
rest)])
|
||||
|
||||
(defn data-grid-card- [{:keys [id
|
||||
route
|
||||
title
|
||||
entity-name
|
||||
action-buttons
|
||||
total
|
||||
start
|
||||
per-page
|
||||
flash-id
|
||||
headers
|
||||
rows] :as params}]
|
||||
[:div {:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
route
|
||||
:request-method :get)
|
||||
:hx-trigger "clientSelected from:body"
|
||||
:hx-swap "outerHTML swap:300ms"
|
||||
:id id}
|
||||
(content-card-
|
||||
{}
|
||||
[:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
|
||||
[:div
|
||||
[:h1.text-2xl.mb-3.font-bold title]
|
||||
[:div {:class "flex items-center flex-1 space-x-4"}
|
||||
[:h5
|
||||
[:span (format "Total %s:" entity-name)]
|
||||
[:span {:class "dark:text-white pl-4"} total]]]]
|
||||
(into [:div {:class "flex flex-col flex-shrink-0 space-y-3 md:flex-row md:items-center lg:justify-end md:space-y-0 md:space-x-3"}
|
||||
]
|
||||
action-buttons)]
|
||||
[:div {:class "overflow-x-auto"}
|
||||
(data-grid- {:headers headers
|
||||
}
|
||||
rows
|
||||
|
||||
)]
|
||||
(paginator- {:start start
|
||||
:end (Math/min (+ start per-page) total)
|
||||
:per-page per-page
|
||||
:total total
|
||||
:a-params (fn [page]
|
||||
{:hx-get (str (bidi/path-for ssr-routes/only-routes
|
||||
route
|
||||
:request-method :get)
|
||||
"?start=" (* page per-page))
|
||||
:hx-target (str "#" id)
|
||||
:hx-swap "outerHTML show:#app:top"})}))])
|
||||
|
||||
61
src/clj/auto_ap/ssr/components/paginator.clj
Normal file
61
src/clj/auto_ap/ssr/components/paginator.clj
Normal file
@@ -0,0 +1,61 @@
|
||||
(ns auto-ap.ssr.components.paginator)
|
||||
|
||||
(defn bound [x y z]
|
||||
(cond
|
||||
(< z x)
|
||||
x
|
||||
(< y x)
|
||||
x
|
||||
(> y z)
|
||||
z
|
||||
:else
|
||||
y))
|
||||
|
||||
(def elipsis-button
|
||||
[:p {:href "#", :class "flex items-center justify-center px-3 py-2 text-sm leading-tight text-gray-500 bg-white border border-gray-300 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400"} "..."])
|
||||
|
||||
(defn paginator-internal- [{:keys [start per-page end total a-params]}]
|
||||
(let [per-page (or per-page 20)
|
||||
max-buttons 5
|
||||
buttons-before (Math/floor (/ max-buttons 2))
|
||||
total-pages (long (Math/max (long 1) (long (Math/ceil (/ total per-page)))))
|
||||
current-page (long (Math/floor (/ start per-page)))
|
||||
first-page-button (bound 0 (- current-page buttons-before) (- total-pages max-buttons))
|
||||
all-buttons (into [] (for [x (range total-pages)]
|
||||
[:li
|
||||
[:a (-> (a-params x)
|
||||
(update
|
||||
:class #(cond-> %
|
||||
true (str " flex items-center justify-center px-3 py-2 text-sm leading-tight border ")
|
||||
|
||||
(= current-page x)
|
||||
(str " text-primary-600 bg-primary-50 border-primary-300 hover:bg-primary-100 hover:text-primary-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white")
|
||||
|
||||
(not= current-page x)
|
||||
(str " text-gray-500 bg-white border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white")))
|
||||
(assoc :href "#"))
|
||||
(inc x)]]))
|
||||
|
||||
|
||||
last-page-button (Math/min (long total-pages) (long (+ max-buttons first-page-button)))
|
||||
|
||||
extended-last-page-button (when (not= last-page-button total-pages)
|
||||
(list
|
||||
elipsis-button
|
||||
(last all-buttons)))
|
||||
|
||||
extended-first-page-button (when (not= first-page-button 0)
|
||||
(list
|
||||
(first all-buttons)
|
||||
elipsis-button))]
|
||||
[:nav
|
||||
[:ul {:class "inline-flex items-stretch -space-x-px"}
|
||||
extended-first-page-button
|
||||
(apply list (subvec all-buttons first-page-button last-page-button))
|
||||
extended-last-page-button]]))
|
||||
|
||||
(defn paginator- [{:keys [start per-page end total a-params] :as params}]
|
||||
[:nav {:class "flex flex-col items-start justify-between p-4 space-y-3 md:flex-row md:items-center md:space-y-0", :aria-label "Table navigation"}
|
||||
[:span {:class "text-sm font-normal text-gray-500 dark:text-gray-400"}
|
||||
[:span {:class "font-semibold text-gray-900 dark:text-white"} (str (inc start)) "-" (str end) " of " (str total)]]
|
||||
(paginator-internal- params)])
|
||||
@@ -8,6 +8,7 @@
|
||||
[auto-ap.ssr.company.company-1099 :as company-1099]
|
||||
[auto-ap.ssr.search :as search]
|
||||
[auto-ap.ssr.company-dropdown :as company-dropdown]
|
||||
[auto-ap.ssr.company.reports :as company-reports]
|
||||
[auto-ap.routes.ezcater-xls :as ezcater-xls]))
|
||||
|
||||
;; from auto-ap.ssr-routes, because they're shared
|
||||
@@ -24,6 +25,9 @@
|
||||
:company-1099-vendor-table (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-table))
|
||||
:company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))
|
||||
:company-1099-vendor-save (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-save))
|
||||
:company-reports (wrap-client-redirect-unauthenticated (wrap-secure company-reports/page))
|
||||
:company-reports-table (wrap-client-redirect-unauthenticated (wrap-secure company-reports/reports-table))
|
||||
:company-reports-delete (wrap-client-redirect-unauthenticated (wrap-admin company-reports/delete-report))
|
||||
:transaction-insights (wrap-client-redirect-unauthenticated (wrap-secure insights/page))
|
||||
:transaction-insight-table (wrap-client-redirect-unauthenticated (wrap-secure insights/insight-table))
|
||||
:transaction-insight-rows (wrap-client-redirect-unauthenticated (wrap-secure insights/transaction-rows))
|
||||
|
||||
@@ -197,3 +197,77 @@
|
||||
(def drop-down
|
||||
[:svg {:class "w-4 h-4 ml-2", :aria-hidden "true", :fill "none", :stroke "currentColor", :viewbox "0 0 24 24", :xmlns "http://www.w3.org/2000/svg"}
|
||||
[:path {:stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "M19 9l-7 7-7-7"}]])
|
||||
|
||||
(def download
|
||||
[:svg
|
||||
{:xmlns "http://www.w3.org/2000/svg", :viewBox "0 0 24 24"}
|
||||
[:defs]
|
||||
[:title "download-thick-bottom"]
|
||||
[:path
|
||||
{:d
|
||||
"M5.5,11.5c-.275,0-.341.159-.146.354l6.292,6.293a.5.5,0,0,0,.709,0l6.311-6.275c.2-.193.13-.353-.145-.355L15.5,11.5V1.5a1,1,0,0,0-1-1h-5a1,1,0,0,0-1,1V11a.5.5,0,0,1-.5.5Z",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:path
|
||||
{:d "M23.5,18.5v4a1,1,0,0,1-1,1H1.5a1,1,0,0,1-1-1v-4",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]])
|
||||
|
||||
(def trash
|
||||
[:svg
|
||||
{:xmlns "http://www.w3.org/2000/svg", :viewBox "0 0 24 24"}
|
||||
[:defs]
|
||||
[:title "bin-1"]
|
||||
[:path
|
||||
{:d
|
||||
"M21,4.5,19.188,21.709A2,2,0,0,1,17.2,23.5H6.8a2,2,0,0,1-1.989-1.791L3,4.5",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:line
|
||||
{:x1 "0.5",
|
||||
:y1 "4.5",
|
||||
:x2 "23.5",
|
||||
:y2 "4.5",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:path
|
||||
{:d "M7.5,4.5v-3a1,1,0,0,1,1-1h7a1,1,0,0,1,1,1v3",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:line
|
||||
{:x1 "12",
|
||||
:y1 "9",
|
||||
:x2 "12",
|
||||
:y2 "19.5",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:line
|
||||
{:x1 "16.5",
|
||||
:y1 "9",
|
||||
:x2 "16",
|
||||
:y2 "19.5",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]
|
||||
[:line
|
||||
{:x1 "7.5",
|
||||
:y1 "9",
|
||||
:x2 "8",
|
||||
:y2 "19.5",
|
||||
:fill "none",
|
||||
:stroke "currentColor",
|
||||
:stroke-linecap "round",
|
||||
:stroke-linejoin "round"}]])
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
(:require
|
||||
[auto-ap.logging :as alog]
|
||||
[config.core :refer [env]]
|
||||
[hiccup2.core :as hiccup]))
|
||||
[hiccup2.core :as hiccup]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn html-response [hiccup & {:keys [status headers] :or {status 200 headers {}}}]
|
||||
{:status status
|
||||
@@ -39,3 +40,24 @@
|
||||
(ex-message e)]
|
||||
:status 500)))))))
|
||||
|
||||
(defn form-data->map [form-data]
|
||||
(reduce-kv
|
||||
(fn [acc k v]
|
||||
(cond (and (string? v)
|
||||
(empty? v))
|
||||
acc
|
||||
|
||||
:else
|
||||
(assoc-in acc (->> (str/split k #"_")
|
||||
(mapv #(apply keyword (str/split % #"/"))))
|
||||
v)))
|
||||
{}
|
||||
form-data))
|
||||
|
||||
(defn path->name [k]
|
||||
(cond (keyword? k)
|
||||
(str (namespace k) "/" (name k))
|
||||
|
||||
(seq k)
|
||||
(str/join "_" (map path->name k))
|
||||
:else k))
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
"/1099" :company-1099
|
||||
"/1099/table" {:get :company-1099-vendor-table}
|
||||
"/1099/vendor-dialog" {["/" [#"\d+" :vendor-id]] {:get :company-1099-vendor-dialog
|
||||
:post :company-1099-vendor-save}}}})
|
||||
:post :company-1099-vendor-save}}
|
||||
"/reports" {"" {:get :company-reports
|
||||
:delete :company-reports-delete}}
|
||||
"/reports/table" :company-reports-table
|
||||
}})
|
||||
|
||||
|
||||
(def only-routes ["/" routes])
|
||||
|
||||
Reference in New Issue
Block a user