Makes groups possible
This commit is contained in:
@@ -74,6 +74,7 @@
|
||||
:client/name
|
||||
:client/code
|
||||
:client/locations
|
||||
:client/groups
|
||||
:client/matches
|
||||
:client/week-a-credits
|
||||
:client/week-b-credits
|
||||
@@ -277,6 +278,9 @@
|
||||
[:client/locations [:vector {:decode/arbitrary (fn [m] (if (map? m)
|
||||
(vals m)
|
||||
m))} :string]]
|
||||
[:client/groups [:vector {:decode/arbitrary (fn [m] (if (map? m)
|
||||
(vals m)
|
||||
m))} :string]]
|
||||
[:client/emails {:optional true} [:maybe (many-entity {}
|
||||
[:db/id [:or entity-id temp-id]]
|
||||
[:email-contact/description :string]
|
||||
@@ -394,6 +398,19 @@
|
||||
(com/data-grid-cell {:class "align-top"}
|
||||
(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 [_]
|
||||
(com/data-grid-row
|
||||
{:x-ref "p"
|
||||
@@ -1318,7 +1335,7 @@
|
||||
(edit-path [_ _] [])
|
||||
|
||||
(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 _]
|
||||
(mm/default-render-step
|
||||
@@ -1335,7 +1352,19 @@
|
||||
(com/data-grid-new-row {:colspan 2
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes ::route/new-feature-flag)
|
||||
: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
|
||||
(mm/default-step-footer linear-wizard this :validation-route ::route/navigate)
|
||||
:validation-route ::route/navigate)))
|
||||
@@ -1387,14 +1416,17 @@
|
||||
(first step-key)))))
|
||||
(form-schema [_] form-schema-2)
|
||||
(submit [_ {:keys [multi-form-state request-method identity] :as request}]
|
||||
(let [snapshot (mc/decode
|
||||
(let [
|
||||
snapshot (mc/decode
|
||||
form-schema-2
|
||||
(:snapshot multi-form-state)
|
||||
mt/strip-extra-keys-transformer)
|
||||
entity (cond-> snapshot
|
||||
(= :post request-method) (assoc :db/id "new")
|
||||
(= :put request-method) (dissoc :client/code)
|
||||
|
||||
(: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
|
||||
(fn [bank-accounts]
|
||||
(mapv
|
||||
@@ -1418,6 +1450,7 @@
|
||||
"name" (conj (or (:client/matches updated-client) [])
|
||||
(:client/name updated-client))
|
||||
"code" (:client/code updated-client)
|
||||
|
||||
"exact" (map str/upper-case (conj (or (:client/matches updated-client) [])
|
||||
(:client/name updated-client)))}]))
|
||||
(html-response
|
||||
@@ -1669,6 +1702,9 @@
|
||||
::route/new-match (add-new-primitive-handler [:step-params :client/matches]
|
||||
""
|
||||
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]
|
||||
(fn [cursor _] (location-match-row cursor)))
|
||||
::route/new-email-contact (add-new-entity-handler [:step-params :client/emails]
|
||||
|
||||
@@ -1,76 +1,92 @@
|
||||
(ns auto-ap.ssr.company-dropdown
|
||||
(:require
|
||||
[auto-ap.datomic :refer [conn pull-attr pull-many]]
|
||||
[auto-ap.graphql.utils :refer [assert-can-see-client cleanse-query]]
|
||||
[auto-ap.solr :as solr]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.utils :refer [html-response]]
|
||||
[bidi.bidi :as bidi]
|
||||
[datomic.api :as dc]
|
||||
[hiccup2.core :as hiccup]
|
||||
[iol-ion.query :refer [can-see-client?]]))
|
||||
(:require [auto-ap.datomic :refer [conn pull-attr pull-many]]
|
||||
[auto-ap.graphql.utils :refer [cleanse-query]]
|
||||
[auto-ap.solr :as solr]
|
||||
[auto-ap.ssr-routes :as ssr-routes]
|
||||
[auto-ap.ssr.hx :as hx]
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[auto-ap.ssr.utils :refer [html-response]]
|
||||
[bidi.bidi :as bidi]
|
||||
[clojure.string :as str]
|
||||
[datomic.api :as dc]
|
||||
[hiccup2.core :as hiccup]
|
||||
[iol-ion.query :refer [can-see-client?]]))
|
||||
|
||||
(defn dropdown-search-results* [{:keys [options]}]
|
||||
[:ul
|
||||
(for [{:keys [id name]} options]
|
||||
[:li
|
||||
[:ul
|
||||
(for [{:keys [id name group]} 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"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-headers (format "{\"x-clients\": \"[%d]\"}" id)
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
name]]])])
|
||||
(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"
|
||||
:hx-put (bidi/path-for ssr-routes/only-routes
|
||||
:active-client
|
||||
:request-method :put)
|
||||
:hx-target "#company-dropdown"
|
||||
:hx-headers (format "{\"x-clients\": \"[%d]\"}" id)
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
name])]])])
|
||||
|
||||
|
||||
|
||||
|
||||
(defn get-clients [identity query]
|
||||
(if-let [query (not-empty (cleanse-query query))]
|
||||
(let [search-query (str "name:(" 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))]
|
||||
(let [search-query (str "name:(" query ")")]
|
||||
|
||||
(for [n (pull-many (dc/db conn) [:client/name :db/id]
|
||||
(for [{:keys [id name]} (solr/query solr/impl "clients" {"query" search-query
|
||||
"fields" "id, name"})
|
||||
:let [client-id (Long/parseLong id)]
|
||||
:when (can-see-client? identity client-id)]
|
||||
client-id))]
|
||||
{:id (:db/id n)
|
||||
:name (:client/name n)}))
|
||||
[]))
|
||||
(for [n (pull-many (dc/db conn) [:client/name :db/id]
|
||||
(for [{:keys [id name]} (solr/query solr/impl "clients" {"query" search-query
|
||||
"fields" "id, name"})
|
||||
:let [client-id (Long/parseLong id)]
|
||||
:when (can-see-client? identity client-id)]
|
||||
client-id))]
|
||||
{:id (:db/id n)
|
||||
:name (:client/name n)}))
|
||||
[])))
|
||||
|
||||
(defn dropdown-search-results [{:keys [identity] :as request}]
|
||||
(html-response
|
||||
(dropdown-search-results* {:options (get-clients identity (get (:query-params request) "search-text"))})))
|
||||
(html-response
|
||||
(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
|
||||
[:script
|
||||
(hiccup/raw
|
||||
"localStorage.setItem(\"last-client-id\", \"" (:db/id client) "\")" "\n"
|
||||
"localStorage.setItem(\"last-selected-clients\", \"" client-selection "\")"
|
||||
)]
|
||||
[: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"
|
||||
"localStorage.setItem(\"last-client-id\", \"" (:db/id client) "\")" "\n"
|
||||
"localStorage.setItem(\"last-selected-clients\", " (pr-str (pr-str client-selection)) ")")]
|
||||
[: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"
|
||||
:type "button"}
|
||||
(cond
|
||||
(= :mine client-selection)
|
||||
"My Companies"
|
||||
(= :all client-selection)
|
||||
"All Companies"
|
||||
(and (sequential? client-selection)
|
||||
(= 1 (count client-selection)))
|
||||
(pull-attr (dc/db conn) :client/name (first client-selection))
|
||||
|
||||
(and client
|
||||
(= 1 (count clients)))
|
||||
( :client/name client)
|
||||
|
||||
:else
|
||||
(str (count client-selection) " Companies"))
|
||||
(str (count clients) " Companies"))
|
||||
[:div.w-4.h-4.ml-2
|
||||
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 "p-3"}
|
||||
[:label {:for "input-group-search", :class "sr-only"} "Search"]
|
||||
@@ -83,27 +99,27 @@
|
||||
:class "block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
:autoFocus true
|
||||
:tab-index -1
|
||||
:hx-trigger "keyup changed delay:500ms, search"
|
||||
:hx-trigger "keyup changed delay:500ms, search"
|
||||
:hx-get (bidi/path-for ssr-routes/only-routes
|
||||
:company-dropdown-search-results)
|
||||
:hx-target "#company-search-results"
|
||||
:hx-swap "innerHTML"} ]]
|
||||
:hx-swap "innerHTML"}]]
|
||||
[:input#company-search-value {:type "hidden"
|
||||
:name "x-clients"}]]
|
||||
[: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"}]
|
||||
(when (= "admin" (:user/role identity))
|
||||
[: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"}
|
||||
|
||||
[:button {: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 "{\"x-clients\": \":mine\"}"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
"Mine"]])
|
||||
[:button {: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 "{\"x-clients\": \":mine\"}"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
"Mine"]])
|
||||
[:div {:class "flex items-center pl-2 rounded hover:bg-green-100 dark:hover:bg-green-600"}
|
||||
|
||||
[:button {:class "w-full py-2 ml-2 text-sm font-medium text-gray-900 rounded dark:text-gray-300"
|
||||
@@ -114,11 +130,10 @@
|
||||
:hx-headers "{\"x-clients\": \":all\"}"
|
||||
:hx-swap "outerHTML"
|
||||
:hx-trigger "click"}
|
||||
"All"]]]
|
||||
]]
|
||||
"All"]]]]]
|
||||
[:script {:lang "text/javascript"}
|
||||
(hiccup/raw
|
||||
"
|
||||
"
|
||||
function initCompanyDropdown() {
|
||||
var $dropdownTargetEl = document.getElementById('company-dropdown-list');
|
||||
|
||||
@@ -145,9 +160,11 @@ function initCompanyDropdown() {
|
||||
|
||||
(defn active-client [{:keys [identity params] :as request}]
|
||||
(assoc
|
||||
(html-response
|
||||
(dropdown {:client-selection (:client-selection (:session request))
|
||||
:client (:client request)
|
||||
:identity identity}))
|
||||
:headers
|
||||
{"hx-trigger" "clientSelected"}))
|
||||
(html-response
|
||||
(dropdown {:client-selection (:client-selection (:session request))
|
||||
:clients (:clients request)
|
||||
:client (:client request)
|
||||
:identity identity}))
|
||||
:headers
|
||||
{"hx-trigger" "clientSelected"}))
|
||||
|
||||
|
||||
@@ -201,8 +201,7 @@
|
||||
|
||||
[:li
|
||||
(menu-button- {:icon svg/restaurant
|
||||
:href (bidi/path-for ssr-routes/only-routes ::ac-routes/page)
|
||||
:target "_new"}
|
||||
:href (bidi/path-for ssr-routes/only-routes ::ac-routes/page) }
|
||||
"Clients")]
|
||||
[:li
|
||||
(menu-button- {:icon svg/vendors
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[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"}
|
||||
[:div {:class "px-3 py-3 lg:px-5 lg:pl-3"}
|
||||
[:div {:class "flex items-center justify-between"}
|
||||
@@ -38,6 +38,7 @@
|
||||
:hx-target "#modal-holder"
|
||||
:hx-swap "outerHTML"}
|
||||
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})]]]])
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
[auto-ap.ssr.svg :as svg]
|
||||
[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 "
|
||||
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"
|
||||
)
|
||||
:x-data (hx/json {:leftNavShow true})}
|
||||
(navbar- {:client-selection client-selection
|
||||
:clients clients
|
||||
:client client
|
||||
:identity identity})
|
||||
[:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params
|
||||
|
||||
0
src/clj/auto_ap/ssr/transaction/insights.fiddle
Normal file
0
src/clj/auto_ap/ssr/transaction/insights.fiddle
Normal file
Reference in New Issue
Block a user