Makes groups possible

This commit is contained in:
2024-02-08 11:41:03 -08:00
parent d5e8545ec8
commit fcefbd5d6d
20 changed files with 364 additions and 276 deletions

View File

@@ -160,6 +160,7 @@
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/> <field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="name" multiValued="true" stored="true" type="text_general"/> <field name="name" multiValued="true" stored="true" type="text_general"/>
<field name="exact" multiValued="true" stored="true" type="string"/> <field name="exact" multiValued="true" stored="true" type="string"/>
<field name="groups" multiValued="true" stored="true" type="string"/>
<field name="code" type="string" multiValued="false" indexed="true" required="true" stored="true"/> <field name="code" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<dynamicField name="*_txt_en_split_tight" type="text_en_splitting_tight" indexed="true" stored="true"/> <dynamicField name="*_txt_en_split_tight" type="text_en_splitting_tight" indexed="true" stored="true"/>
<dynamicField name="*_descendent_path" type="descendent_path" indexed="true" stored="true"/> <dynamicField name="*_descendent_path" type="descendent_path" indexed="true" stored="true"/>

View File

@@ -117,10 +117,8 @@
"fig:min" ["run" "-m" "figwheel.main" "-O" "whitespace" "-bo" "min"]} "fig:min" ["run" "-m" "figwheel.main" "-O" "whitespace" "-bo" "min"]}
:profiles { :profiles {:dev
:dev {:resource-paths ["resources" "target"]
{
:resource-paths ["resources" "target"]
:dependencies [#_[binaryage/devteols "1.0.2"] :dependencies [#_[binaryage/devteols "1.0.2"]
[postgresql/postgresql "9.3-1102.jdbc41"] [postgresql/postgresql "9.3-1102.jdbc41"]
[org.clojure/tools.namespace "1.4.5"] [org.clojure/tools.namespace "1.4.5"]
@@ -147,10 +145,10 @@
:jvm-opts ["-Dconfig=config/dev.edn" "-Xms4G" "-Xmx20G" "-XX:-OmitStackTraceInFastThrow"]} :jvm-opts ["-Dconfig=config/dev.edn" "-Xms4G" "-Xmx20G" "-XX:-OmitStackTraceInFastThrow"]}
:uberjar :uberjar
{ {:java-cmd "/usr/lib/jvm/java-11-openjdk/bin/java"
:java-cmd "/usr/lib/jvm/java-11-openjdk/bin/java" :main auto-ap.main
:prep-tasks ["fig:min"] :prep-tasks ["fig:min"]
:aot [auto-ap.server auto-ap.time clj-time.core clj-time.coerce clj-time.format clojure.tools.logging.impl ] :aot [auto-ap.main auto-ap.time clj-time.core clj-time.coerce clj-time.format clojure.tools.logging.impl]
:dependencies [[com.bhauman/figwheel-main "0.2.18" :exclusions [org.clojure/clojurescript :dependencies [[com.bhauman/figwheel-main "0.2.18" :exclusions [org.clojure/clojurescript
ring ring
ring/ring-core ring/ring-core
@@ -177,11 +175,8 @@
[re-frame-utils "0.1.0"] [re-frame-utils "0.1.0"]
[com.andrewmcveigh/cljs-time "0.5.2"] [com.andrewmcveigh/cljs-time "0.5.2"]
[cljs-http "0.1.46"] [cljs-http "0.1.46"]
[kibu/pushy "0.3.8"]]} [kibu/pushy "0.3.8"]]}}
}
:main auto-ap.server
:uberjar-name "auto-ap.jar" :uberjar-name "auto-ap.jar"
:test-paths ["test/clj"] :test-paths ["test/clj"]
:test-selectors {:integration (fn [m] :test-selectors {:integration (fn [m]

View File

@@ -337,6 +337,10 @@
:db/cardinality #:db{:ident :db.cardinality/many}, :db/cardinality #:db{:ident :db.cardinality/many},
:db/doc "A client's locations", :db/doc "A client's locations",
:db/ident :client/locations} :db/ident :client/locations}
{:db/valueType #:db{:ident :db.type/string},
:db/cardinality #:db{:ident :db.cardinality/many},
:db/doc "The groups that this client belongs in, for fast lookup",
:db/ident :client/groups}
{:db/valueType #:db{:ident :db.type/ref}, {:db/valueType #:db{:ident :db.type/ref},
:db/isComponent true, :db/isComponent true,
:db/cardinality #:db{:ident :db.cardinality/one}, :db/cardinality #:db{:ident :db.cardinality/one},

View File

@@ -79,6 +79,7 @@
(defn get-minimal [] (defn get-minimal []
(->> (dc/q '[:find (pull ?e [:client/name :client/code :client/locations :db/id (->> (dc/q '[:find (pull ?e [:client/name :client/code :client/locations :db/id
:client/groups
{:client/bank-accounts [{:bank-account/type [:db/ident]} {:client/bank-accounts [{:bank-account/type [:db/ident]}
:bank-account/name :bank-account/name
:bank-account/sort-order :bank-account/sort-order

View File

@@ -102,6 +102,7 @@
:locked_until {:type :iso_date} :locked_until {:type :iso_date}
:code {:type 'String} :code {:type 'String}
:feature_flags {:type '(list String)} :feature_flags {:type '(list String)}
:groups {:type '(list String)}
:square_auth_token {:type 'String} :square_auth_token {:type 'String}
:signature_file {:type 'String} :signature_file {:type 'String}
:square_integration_status {:type :integration_status} :square_integration_status {:type :integration_status}

View File

@@ -193,6 +193,16 @@
(= :mine x-clients) (= :mine x-clients)
(map :db/id (:user/clients identity)) (map :db/id (:user/clients identity))
(= :group (first x-clients))
(->>
(dc/q '[:find ?c
:in $ ?g
:where [?c :client/groups ?g]]
(dc/db conn)
(str/upper-case (or (second x-clients) "INVALID")))
(map first)
set)
(seq x-clients) (seq x-clients)
(->> x-clients (->> x-clients
(map (fn [c] (map (fn [c]
@@ -229,6 +239,8 @@
(let [x-clients (edn/read-string (get headers "x-clients")) (let [x-clients (edn/read-string (get headers "x-clients"))
x-clients (try (if-let [client-id (and x-clients x-clients (try (if-let [client-id (and x-clients
(sequential? x-clients) (sequential? x-clients)
(first x-clients)
(not= :group (first x-clients))
(first x-clients))] (first x-clients))]
(do (do
(assert-can-see-client identity (cond-> client-id (assert-can-see-client identity (cond-> client-id
@@ -296,6 +308,4 @@
#_(wrap-reload) #_(wrap-reload)
(wrap-params) (wrap-params)
(mp/wrap-multipart-params) (mp/wrap-multipart-params)
(wrap-edn-params) (wrap-edn-params)))
))

107
src/clj/auto_ap/main.clj Normal file
View File

@@ -0,0 +1,107 @@
(ns auto-ap.main
(:gen-class)
(:require
[auto-ap.handler :refer [app]]
[auto-ap.server :as server]
[auto-ap.jobs.restore-from-backup :as job-restore-from-backup]
[auto-ap.jobs.bulk-journal-import :as job-bulk-journal-import]
[auto-ap.jobs.close-auto-invoices :as job-close-auto-invoices]
[auto-ap.jobs.current-balance-cache :as job-current-balance-cache]
[auto-ap.jobs.ezcater-upsert :as job-ezcater-upsert]
[auto-ap.jobs.import-uploaded-invoices :as job-import-uploaded-invoices]
[auto-ap.jobs.intuit :as job-intuit]
[auto-ap.jobs.ntg :as job-ntg]
#_[auto-ap.backup :as backup]
[auto-ap.jobs.ledger-reconcile :as job-reconcile-ledger]
[auto-ap.jobs.load-historical-sales :as job-load-historical-sales]
[auto-ap.jobs.plaid :as job-plaid]
[auto-ap.jobs.register-invoice-import :as job-register-invoice-import]
[auto-ap.jobs.square :as job-square]
[auto-ap.jobs.sysco :as job-sysco]
[auto-ap.jobs.vendor-usages :as job-vendor-usages]
[auto-ap.jobs.yodlee2 :as job-yodlee2]
[auto-ap.logging :as alog]
[com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]]
[mount.core :as mount]
[nrepl.server :refer [start-server]]
[ring.adapter.jetty :refer [run-jetty]]
[yang.scheduler :as scheduler]
[auto-ap.jobs.insight-outcome-recommendation :as insight-outcome-recommendation])
(:import
(org.eclipse.jetty.server.handler StatisticsHandler)
(org.eclipse.jetty.server.handler.gzip GzipHandler)))
(defn add-shutdown-hook! [^Runnable f]
(.addShutdownHook (Runtime/getRuntime)
(Thread. f)))
(defn shutdown-mount []
(mount/stop))
(defn -main [& _]
(let [job (System/getenv "INTEGREAT_JOB")]
(println "JOB is" job)
(cond (= job "square-import-job")
(job-square/-main)
(= job "reconcile-ledger")
(job-reconcile-ledger/-main)
(= job "current-balance-cache")
(job-current-balance-cache/-main)
(= job "yodlee2")
(job-yodlee2/-main)
(= job "yodlee2-accounts")
(job-yodlee2/accounts-only)
(= job "plaid")
(job-plaid/-main)
(= job "intuit")
(job-intuit/-main)
(= job "vendor-usages")
(job-vendor-usages/-main)
(= job "import-uploaded-invoices")
(job-import-uploaded-invoices/-main)
(= job "sysco")
(job-sysco/-main)
(= job "close-auto-invoices")
(job-close-auto-invoices/-main)
(= job "ezcater-upsert")
(job-ezcater-upsert/-main)
(= job "register-invoice-import")
(job-register-invoice-import/-main)
(= job "load-historical-sales")
(job-load-historical-sales/-main)
(= job "bulk-journal-import")
(job-bulk-journal-import/-main)
(= job "restore-from-backup")
(job-restore-from-backup/-main)
(= job "insight-outcome-recommendation")
(insight-outcome-recommendation/-main)
;; (= job "export-backup")
;; (backup/-main)
(= job "ntg")
(job-ntg/-main)
:else
(do
(add-shutdown-hook! shutdown-mount)
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
(mount/start)
#_(alter-var-root #'nrepl.middleware.print/*print-fn* (constantly clojure.pprint/pprint))))))

View File

@@ -1,41 +1,14 @@
(ns auto-ap.server (ns auto-ap.server
(:gen-class) (:require [auto-ap.handler :refer [app]]
(:require
[auto-ap.handler :refer [app]]
[auto-ap.jobs.restore-from-backup :as job-restore-from-backup]
[auto-ap.jobs.bulk-journal-import :as job-bulk-journal-import]
[auto-ap.jobs.close-auto-invoices :as job-close-auto-invoices]
[auto-ap.jobs.current-balance-cache :as job-current-balance-cache]
[auto-ap.jobs.ezcater-upsert :as job-ezcater-upsert]
[auto-ap.jobs.import-uploaded-invoices :as job-import-uploaded-invoices]
[auto-ap.jobs.intuit :as job-intuit]
[auto-ap.jobs.ntg :as job-ntg]
#_[auto-ap.backup :as backup]
[auto-ap.jobs.ledger-reconcile :as job-reconcile-ledger]
[auto-ap.jobs.load-historical-sales :as job-load-historical-sales]
[auto-ap.jobs.plaid :as job-plaid]
[auto-ap.jobs.register-invoice-import :as job-register-invoice-import]
[auto-ap.jobs.square :as job-square]
[auto-ap.jobs.sysco :as job-sysco]
[auto-ap.jobs.vendor-usages :as job-vendor-usages]
[auto-ap.jobs.yodlee2 :as job-yodlee2]
[auto-ap.logging :as alog] [auto-ap.logging :as alog]
[com.unbounce.dogstatsd.core :as statsd] [com.unbounce.dogstatsd.core :as statsd]
[config.core :refer [env]] [config.core :refer [env]]
[mount.core :as mount] [mount.core :as mount]
[nrepl.server :refer [start-server]]
[ring.adapter.jetty :refer [run-jetty]] [ring.adapter.jetty :refer [run-jetty]]
[yang.scheduler :as scheduler] [yang.scheduler :as scheduler])
[auto-ap.jobs.insight-outcome-recommendation :as insight-outcome-recommendation]) (:import (org.eclipse.jetty.server.handler StatisticsHandler)
(:import
(org.eclipse.jetty.server.handler StatisticsHandler)
(org.eclipse.jetty.server.handler.gzip GzipHandler))) (org.eclipse.jetty.server.handler.gzip GzipHandler)))
(defn add-shutdown-hook! [^Runnable f]
(.addShutdownHook (Runtime/getRuntime)
(Thread. f)))
(defn gzip-handler [] (defn gzip-handler []
(doto (GzipHandler.) (doto (GzipHandler.)
(.setIncludedMimeTypes (into-array ["text/css" (.setIncludedMimeTypes (into-array ["text/css"
@@ -88,73 +61,3 @@
:start (scheduler/every (* 1000 10) collect-jetty-stats) :start (scheduler/every (* 1000 10) collect-jetty-stats)
:stop (scheduler/stop jetty-stats)) :stop (scheduler/stop jetty-stats))
(defn shutdown-mount []
(mount/stop))
(defn -main [& _]
(let [job (System/getenv "INTEGREAT_JOB")]
(println "JOB is" job)
(cond (= job "square-import-job")
(job-square/-main)
(= job "reconcile-ledger")
(job-reconcile-ledger/-main)
(= job "current-balance-cache")
(job-current-balance-cache/-main)
(= job "yodlee2")
(job-yodlee2/-main)
(= job "yodlee2-accounts")
(job-yodlee2/accounts-only)
(= job "plaid")
(job-plaid/-main)
(= job "intuit")
(job-intuit/-main)
(= job "vendor-usages")
(job-vendor-usages/-main)
(= job "import-uploaded-invoices")
(job-import-uploaded-invoices/-main)
(= job "sysco")
(job-sysco/-main)
(= job "close-auto-invoices")
(job-close-auto-invoices/-main)
(= job "ezcater-upsert")
(job-ezcater-upsert/-main)
(= job "register-invoice-import")
(job-register-invoice-import/-main)
(= job "load-historical-sales")
(job-load-historical-sales/-main)
(= job "bulk-journal-import")
(job-bulk-journal-import/-main)
(= job "restore-from-backup")
(job-restore-from-backup/-main)
(= job "insight-outcome-recommendation")
(insight-outcome-recommendation/-main)
;; (= job "export-backup")
;; (backup/-main)
(= job "ntg")
(job-ntg/-main)
:else
(do
(add-shutdown-hook! shutdown-mount)
(start-server :port 9000 :bind "0.0.0.0" #_#_:handler (cider-nrepl-handler))
(mount/start)
#_(alter-var-root #'nrepl.middleware.print/*print-fn* (constantly clojure.pprint/pprint))))))

View File

@@ -74,6 +74,7 @@
:client/name :client/name
:client/code :client/code
:client/locations :client/locations
:client/groups
:client/matches :client/matches
:client/week-a-credits :client/week-a-credits
:client/week-b-credits :client/week-b-credits
@@ -277,6 +278,9 @@
[:client/locations [:vector {:decode/arbitrary (fn [m] (if (map? m) [:client/locations [:vector {:decode/arbitrary (fn [m] (if (map? m)
(vals m) (vals m)
m))} :string]] m))} :string]]
[:client/groups [:vector {:decode/arbitrary (fn [m] (if (map? m)
(vals m)
m))} :string]]
[:client/emails {:optional true} [:maybe (many-entity {} [:client/emails {:optional true} [:maybe (many-entity {}
[:db/id [:or entity-id temp-id]] [:db/id [:or entity-id temp-id]]
[:email-contact/description :string] [:email-contact/description :string]
@@ -394,6 +398,19 @@
(com/data-grid-cell {:class "align-top"} (com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x)))) (com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x))))
(defn group-row [_]
(com/data-grid-row
{:x-ref "p"
:x-data (hx/json {})}
(com/data-grid-cell
{}
(com/validated-field {}
(com/text-input {:name (fc/field-name)
:value (fc/field-value)
:class "w-24"})))
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "$refs.p.remove()"} svg/x))))
(defn feature-flag-row [_] (defn feature-flag-row [_]
(com/data-grid-row (com/data-grid-row
{:x-ref "p" {:x-ref "p"
@@ -1318,7 +1335,7 @@
(edit-path [_ _] []) (edit-path [_ _] [])
(step-schema [_] (step-schema [_]
(mut/select-keys (mm/form-schema linear-wizard) #{:client/feature-flags})) (mut/select-keys (mm/form-schema linear-wizard) #{:client/feature-flags :client/groups}))
(render-step [this _] (render-step [this _]
(mm/default-render-step (mm/default-render-step
@@ -1335,7 +1352,19 @@
(com/data-grid-new-row {:colspan 2 (com/data-grid-new-row {:colspan 2
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-feature-flag) :hx-get (bidi/path-for ssr-routes/only-routes ::route/new-feature-flag)
:index (count (fc/field-value))} :index (count (fc/field-value))}
"New flag"))))) "New flag"))))
(fc/with-field :client/groups
(com/validated-field
{:errors (fc/field-errors)
:label "Groups"}
(com/data-grid {:headers [(com/data-grid-header {} "Group")
(com/data-grid-header {:class "w-16"})]}
(fc/cursor-map #(group-row %))
(com/data-grid-new-row {:colspan 2
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-group)
:index (count (fc/field-value))}
"New group")))))
:footer :footer
(mm/default-step-footer linear-wizard this :validation-route ::route/navigate) (mm/default-step-footer linear-wizard this :validation-route ::route/navigate)
:validation-route ::route/navigate))) :validation-route ::route/navigate)))
@@ -1387,14 +1416,17 @@
(first step-key))))) (first step-key)))))
(form-schema [_] form-schema-2) (form-schema [_] form-schema-2)
(submit [_ {:keys [multi-form-state request-method identity] :as request}] (submit [_ {:keys [multi-form-state request-method identity] :as request}]
(let [snapshot (mc/decode (let [
snapshot (mc/decode
form-schema-2 form-schema-2
(:snapshot multi-form-state) (:snapshot multi-form-state)
mt/strip-extra-keys-transformer) mt/strip-extra-keys-transformer)
entity (cond-> snapshot entity (cond-> snapshot
(= :post request-method) (assoc :db/id "new") (= :post request-method) (assoc :db/id "new")
(= :put request-method) (dissoc :client/code) (= :put request-method) (dissoc :client/code)
(:client/locked-until snapshot) (update :client/locked-until clj-time.coerce/to-date) (:client/locked-until snapshot) (update :client/locked-until clj-time.coerce/to-date)
(seq (:client/groups snapshot)) (update :client/groups #(mapv str/upper-case %))
(seq (:client/bank-accounts snapshot)) (update :client/bank-accounts (seq (:client/bank-accounts snapshot)) (update :client/bank-accounts
(fn [bank-accounts] (fn [bank-accounts]
(mapv (mapv
@@ -1418,6 +1450,7 @@
"name" (conj (or (:client/matches updated-client) []) "name" (conj (or (:client/matches updated-client) [])
(:client/name updated-client)) (:client/name updated-client))
"code" (:client/code updated-client) "code" (:client/code updated-client)
"exact" (map str/upper-case (conj (or (:client/matches updated-client) []) "exact" (map str/upper-case (conj (or (:client/matches updated-client) [])
(:client/name updated-client)))}])) (:client/name updated-client)))}]))
(html-response (html-response
@@ -1669,6 +1702,9 @@
::route/new-match (add-new-primitive-handler [:step-params :client/matches] ::route/new-match (add-new-primitive-handler [:step-params :client/matches]
"" ""
match-row) match-row)
::route/new-group (add-new-primitive-handler [:step-params :client/groups]
""
group-row)
::route/new-location-match (add-new-entity-handler [:step-params :client/location-matches] ::route/new-location-match (add-new-entity-handler [:step-params :client/location-matches]
(fn [cursor _] (location-match-row cursor))) (fn [cursor _] (location-match-row cursor)))
::route/new-email-contact (add-new-entity-handler [:step-params :client/emails] ::route/new-email-contact (add-new-entity-handler [:step-params :client/emails]

View File

@@ -1,21 +1,33 @@
(ns auto-ap.ssr.company-dropdown (ns auto-ap.ssr.company-dropdown
(:require (:require [auto-ap.datomic :refer [conn pull-attr pull-many]]
[auto-ap.datomic :refer [conn pull-attr pull-many]] [auto-ap.graphql.utils :refer [cleanse-query]]
[auto-ap.graphql.utils :refer [assert-can-see-client cleanse-query]]
[auto-ap.solr :as solr] [auto-ap.solr :as solr]
[auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils :refer [html-response]] [auto-ap.ssr.utils :refer [html-response]]
[bidi.bidi :as bidi] [bidi.bidi :as bidi]
[clojure.string :as str]
[datomic.api :as dc] [datomic.api :as dc]
[hiccup2.core :as hiccup] [hiccup2.core :as hiccup]
[iol-ion.query :refer [can-see-client?]])) [iol-ion.query :refer [can-see-client?]]))
(defn dropdown-search-results* [{:keys [options]}] (defn dropdown-search-results* [{:keys [options]}]
[:ul [:ul
(for [{:keys [id name]} options] (for [{:keys [id name group]} options]
[:li [:li
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"} [:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
(if group
[:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
:hx-put (bidi/path-for ssr-routes/only-routes
:active-client
:request-method :put)
:hx-target "#company-dropdown"
:hx-headers (hx/json {"x-clients" (pr-str [:group group])})
:hx-swap "outerHTML"
:hx-trigger "click"}
name]
[:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300" [:a {:href "#" :class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
:hx-put (bidi/path-for ssr-routes/only-routes :hx-put (bidi/path-for ssr-routes/only-routes
:active-client :active-client
@@ -24,11 +36,16 @@
:hx-headers (format "{\"x-clients\": \"[%d]\"}" id) :hx-headers (format "{\"x-clients\": \"[%d]\"}" id)
:hx-swap "outerHTML" :hx-swap "outerHTML"
:hx-trigger "click"} :hx-trigger "click"}
name]]])]) name])]])])
(defn get-clients [identity query] (defn get-clients [identity query]
(if (str/starts-with? query "g:")
(let [search-query (str "groups:(" (subs query 2) ")")]
[{:group (subs query 2)
:name (str "All clients matching " (subs query 2))}])
(if-let [query (not-empty (cleanse-query query))] (if-let [query (not-empty (cleanse-query query))]
(let [search-query (str "name:(" query ")")] (let [search-query (str "name:(" query ")")]
@@ -40,19 +57,18 @@
client-id))] client-id))]
{:id (:db/id n) {:id (:db/id n)
:name (:client/name n)})) :name (:client/name n)}))
[])) [])))
(defn dropdown-search-results [{:keys [identity] :as request}] (defn dropdown-search-results [{:keys [identity] :as request}]
(html-response (html-response
(dropdown-search-results* {:options (get-clients identity (get (:query-params request) "search-text"))}))) (dropdown-search-results* {:options (get-clients identity (get (:query-params request) "search-text"))})))
(defn dropdown [{:keys [client-selection client identity]}] (defn dropdown [{:keys [client-selection client identity clients]}]
[:div#company-dropdown [:div#company-dropdown
[:script [:script
(hiccup/raw (hiccup/raw
"localStorage.setItem(\"last-client-id\", \"" (:db/id client) "\")" "\n" "localStorage.setItem(\"last-client-id\", \"" (:db/id client) "\")" "\n"
"localStorage.setItem(\"last-selected-clients\", \"" client-selection "\")" "localStorage.setItem(\"last-selected-clients\", " (pr-str (pr-str client-selection)) ")")]
)]
[:div [:div
[:button#company-dropdown-button {:class "text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" [:button#company-dropdown-button {:class "text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
:type "button"} :type "button"}
@@ -61,16 +77,16 @@
"My Companies" "My Companies"
(= :all client-selection) (= :all client-selection)
"All Companies" "All Companies"
(and (sequential? client-selection)
(= 1 (count client-selection))) (and client
(pull-attr (dc/db conn) :client/name (first client-selection)) (= 1 (count clients)))
( :client/name client)
:else :else
(str (count client-selection) " Companies")) (str (count clients) " Companies"))
[:div.w-4.h-4.ml-2 [:div.w-4.h-4.ml-2
svg/drop-down]] svg/drop-down]]
[:div#company-dropdown-list.hidden {"_" (hiccup/raw "init call initCompanyDropdown()") [:div#company-dropdown-list.hidden {"_" (hiccup/raw "init call initCompanyDropdown()")}
}
[:div {:class "z-10 bg-white rounded-lg shadow w-64 dark:bg-gray-700 slide-up duration-500 transition-all"} [:div {:class "z-10 bg-white rounded-lg shadow w-64 dark:bg-gray-700 slide-up duration-500 transition-all"}
[:div {:class "p-3"} [:div {:class "p-3"}
[:label {:for "input-group-search", :class "sr-only"} "Search"] [:label {:for "input-group-search", :class "sr-only"} "Search"]
@@ -114,8 +130,7 @@
:hx-headers "{\"x-clients\": \":all\"}" :hx-headers "{\"x-clients\": \":all\"}"
:hx-swap "outerHTML" :hx-swap "outerHTML"
:hx-trigger "click"} :hx-trigger "click"}
"All"]]] "All"]]]]]
]]
[:script {:lang "text/javascript"} [:script {:lang "text/javascript"}
(hiccup/raw (hiccup/raw
" "
@@ -147,7 +162,9 @@ function initCompanyDropdown() {
(assoc (assoc
(html-response (html-response
(dropdown {:client-selection (:client-selection (:session request)) (dropdown {:client-selection (:client-selection (:session request))
:clients (:clients request)
:client (:client request) :client (:client request)
:identity identity})) :identity identity}))
:headers :headers
{"hx-trigger" "clientSelected"})) {"hx-trigger" "clientSelected"}))

View File

@@ -201,8 +201,7 @@
[:li [:li
(menu-button- {:icon svg/restaurant (menu-button- {:icon svg/restaurant
:href (bidi/path-for ssr-routes/only-routes ::ac-routes/page) :href (bidi/path-for ssr-routes/only-routes ::ac-routes/page) }
:target "_new"}
"Clients")] "Clients")]
[:li [:li
(menu-button- {:icon svg/vendors (menu-button- {:icon svg/vendors

View File

@@ -8,7 +8,7 @@
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[bidi.bidi :as bidi])) [bidi.bidi :as bidi]))
(defn navbar- [{:keys [client-selection client identity]}] (defn navbar- [{:keys [client-selection client identity clients]}]
[:nav {:class "fixed z-30 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700"} [:nav {:class "fixed z-30 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700"}
[:div {:class "px-3 py-3 lg:px-5 lg:pl-3"} [:div {:class "px-3 py-3 lg:px-5 lg:pl-3"}
[:div {:class "flex items-center justify-between"} [:div {:class "flex items-center justify-between"}
@@ -38,6 +38,7 @@
:hx-target "#modal-holder" :hx-target "#modal-holder"
:hx-swap "outerHTML"} :hx-swap "outerHTML"}
svg/search) svg/search)
(cd/dropdown {:client-selection client-selection :client client :identity identity}) (cd/dropdown {:client-selection client-selection :client client :identity identity
:clients clients})
(user-dropdown/dropdown {:identity identity})]]]]) (user-dropdown/dropdown {:identity identity})]]]])

View File

@@ -6,13 +6,14 @@
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[auto-ap.ssr.hx :as hx])) [auto-ap.ssr.hx :as hx]))
(defn page- [{:keys [nav page-specific client client-selection identity app-params] :or {app-params {}}} & children] (defn page- [{:keys [nav page-specific client clients client-selection identity app-params] :or {app-params {}}} & children]
[:div#app {"_" (hiccup/raw " [:div#app {"_" (hiccup/raw "
on notification from body put event.detail.value into #notification-details then add .htmx-added to #notification-holder then remove .hidden from #notification-holder then wait 30ms then remove .htmx-added from #notification-holder on notification from body put event.detail.value into #notification-details then add .htmx-added to #notification-holder then remove .hidden from #notification-holder then wait 30ms then remove .htmx-added from #notification-holder
on htmx:responseError put event.detail.xhr.response into #error-details then add .htmx-added to #error-holder then remove .hidden from #error-holder then wait 30ms then remove .htmx-added from #error-holder" on htmx:responseError put event.detail.xhr.response into #error-details then add .htmx-added to #error-holder then remove .hidden from #error-holder then wait 30ms then remove .htmx-added from #error-holder"
) )
:x-data (hx/json {:leftNavShow true})} :x-data (hx/json {:leftNavShow true})}
(navbar- {:client-selection client-selection (navbar- {:client-selection client-selection
:clients clients
:client client :client client
:identity identity}) :identity identity})
[:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params [:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params

View File

@@ -13,6 +13,7 @@
"/match/new" ::new-match "/match/new" ::new-match
"/location-match/new" ::new-location-match "/location-match/new" ::new-location-match
"/email-contact/new" ::new-email-contact "/email-contact/new" ::new-email-contact
"/group/new" ::new-group
"/feature-flag/new" ::new-feature-flag "/feature-flag/new" ::new-feature-flag
"/new" {:get ::new-dialog} "/new" {:get ::new-dialog}
["/" [#"\d+" :db/id] "/sales-powerquery"] ::biweekly-sales-powerquery ["/" [#"\d+" :db/id] "/sales-powerquery"] ::biweekly-sales-powerquery

View File

@@ -71,6 +71,7 @@
"/bank-account/typeahead" :bank-account-typeahead "/bank-account/typeahead" :bank-account-typeahead
["/" [#"\d+" :db/id] "/bank-account"] {"/search" :bank-account-search} ["/" [#"\d+" :db/id] "/bank-account"] {"/search" :bank-account-search}
"/active" {:put :active-client} "/active" {:put :active-client}
"/active-group" {:put :active-client-group}
"/1099" :company-1099 "/1099" :company-1099
"/1099/table" {:get :company-1099-vendor-table} "/1099/table" {:get :company-1099-vendor-table}
"/1099/vendor-dialog" {["/" [#"\d+" :vendor-id]] {:get :company-1099-vendor-dialog "/1099/vendor-dialog" {["/" [#"\d+" :vendor-id]] {:get :company-1099-vendor-dialog

View File

@@ -19,6 +19,7 @@
(defn maybe-add-x-clients [headers] (defn maybe-add-x-clients [headers]
(if (or (and (sequential? (:selected-clients @re-frame.db/app-db)) (every? int? (:selected-clients @re-frame.db/app-db))) (if (or (and (sequential? (:selected-clients @re-frame.db/app-db)) (every? int? (:selected-clients @re-frame.db/app-db)))
(and (sequential? (:selected-clients @re-frame.db/app-db)) (every? string? (:selected-clients @re-frame.db/app-db))) (and (sequential? (:selected-clients @re-frame.db/app-db)) (every? string? (:selected-clients @re-frame.db/app-db)))
(and (sequential? (:selected-clients @re-frame.db/app-db)) (= :group (first (:selected-clients @re-frame.db/app-db))))
(keyword? (:selected-clients @re-frame.db/app-db))) (keyword? (:selected-clients @re-frame.db/app-db)))
(assoc headers "x-clients" (pr-str (:selected-clients @re-frame.db/app-db))) (assoc headers "x-clients" (pr-str (:selected-clients @re-frame.db/app-db)))
headers)) headers))

View File

@@ -27,7 +27,7 @@
(defn client-query [] (defn client-query []
(cond-> [:id :name :code :email :locations :feature-flags (cond-> [:id :name :code :email :locations :feature-flags :groups
[:emails [:id :email :description]] [:emails [:id :email :description]]
[:bank-accounts [:id :code :bank-name :name :type :visible [:bank-accounts [:id :code :bank-name :name :type :visible
:locations :include-in-reports :current-balance :locations :include-in-reports :current-balance

View File

@@ -46,7 +46,7 @@
(fn [[selected-clients user clients]] (fn [[selected-clients user clients]]
(println "SELECTED" selected-clients (println "SELECTED" selected-clients
"USER" user "USER" user
"CLIENTS" clients) "CLIENTS" (count clients))
(cond (= :mine selected-clients) (cond (= :mine selected-clients)
(sort-by :name (sort-by :name
@@ -58,6 +58,15 @@
(nil? selected-clients)) (nil? selected-clients))
clients clients
(= :group (and (sequential? selected-clients)
(first selected-clients)))
(let [group (second selected-clients)]
(filterv
(fn [c]
(println "GROUP" group (:groups c))
((set (:groups c)) group))
clients))
(sequential? selected-clients) (sequential? selected-clients)
(filter (comp (set (map coerce-string-version selected-clients)) coerce-string-version :id) (filter (comp (set (map coerce-string-version selected-clients)) coerce-string-version :id)
clients) clients)

View File

@@ -86,13 +86,13 @@
clients clients
(if-let [exact-match (first (filter (if-let [exact-match (first (filter
(fn [client] (fn [client]
(= (str/lower-case (:code client)) (str/lower-case client-search))) (= (str/lower-case (or (:code client) "INVALID")) (str/lower-case client-search)))
clients))] clients))]
[exact-match] [exact-match]
(filter (filter
(fn [client] (fn [client]
(or (or
(str/includes? (str/lower-case (:code client)) (str/lower-case client-search)) (str/includes? (str/lower-case (or (:code client) "INVALID")) (str/lower-case client-search))
(str/includes? (str/lower-case (:name client)) (str/lower-case client-search)))) (str/includes? (str/lower-case (:name client)) (str/lower-case client-search))))
clients))))) clients)))))