diff --git a/notes.txt b/notes.txt index af5c7d31..b4e5274e 100644 --- a/notes.txt +++ b/notes.txt @@ -1 +1,16 @@ 4. Maybe make dark mode persist + + + +# Implement multi +# test headers->clients +# Still use single client in subs, but have it only be set if a single on is selected +X Pass X-Clients header as :all :mine [id-1, id-2, id-3] +X Use X-Clients instead of client filter +# Remove the client specific filter from each graphql +# Test with single client user, all client user, admin, etc +# Synchronize with the backend for SSR, set in session, but hydrate to real clients in middleware +# Ensure that client selection still resets everything +# maybe set it up so that changing assignments works automatically without having to log out or in +# figure out how to not make this require a whole login +# bulk-code-transactions diff --git a/src/clj/auto_ap/datomic/checks.clj b/src/clj/auto_ap/datomic/checks.clj index cd61cb3d..4da6eb8d 100644 --- a/src/clj/auto_ap/datomic/checks.clj +++ b/src/clj/auto_ap/datomic/checks.clj @@ -40,15 +40,13 @@ ([db args] (let [check-number-like (try (Long/parseLong (:check-number-like args)) (catch Exception _ nil)) query (if (:exact-match-id args) - (cond-> {:query {:find '[?e] - :in '[$ ?e] - :where '[[?e :payment/client ?c]]} - :args [db - (:exact-match-id args)]} - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] - :where ['[?e :payment/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]})) + {:query {:find '[?e] + :in '[$ ?e [?c ...]] + :where '[[?e :payment/client ?c]]} + :args [db + (:exact-match-id args) + (map :db/id (:clients args))] + } (cond-> {:query {:find [] :in ['$] :where []} @@ -69,10 +67,10 @@ :where []} :args [(:exact-match-id args)]}) - (limited-clients (:id args)) + (seq (:clients args)) (merge-query {:query {:in ['[?xx ...]] :where ['[?e :payment/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]}) + :args [(map :db/id (:clients args))]}) (:client-id args) diff --git a/src/clj/auto_ap/datomic/clients.clj b/src/clj/auto_ap/datomic/clients.clj index 39d02c2c..da73b70f 100644 --- a/src/clj/auto_ap/datomic/clients.clj +++ b/src/clj/auto_ap/datomic/clients.clj @@ -165,18 +165,20 @@ :else nil) - valid-ids (cond + matching-ids (cond (and name-like-ids (limited-clients (:id args))) (set/intersection name-like-ids (limited-clients (:id args))) - (limited-clients (:id args)) - (limited-clients (:id args)) - name-like-ids name-like-ids :else nil) + valid-ids (if matching-ids + (set/intersection (set (map :db/id (:clients args))) + matching-ids) + (set (map :db/id (:clients args)))) + query (cond-> {:query {:find [] :in ['$ ] diff --git a/src/clj/auto_ap/datomic/expected_deposit.clj b/src/clj/auto_ap/datomic/expected_deposit.clj index f96eabb7..46aa0483 100644 --- a/src/clj/auto_ap/datomic/expected_deposit.clj +++ b/src/clj/auto_ap/datomic/expected_deposit.clj @@ -38,10 +38,10 @@ "fee" ['[?e :expected-deposit/fee ?sort-fee]]} args) - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] + (seq (:clients args)) + (merge-query {:query {:in ['[?xx ...]] :where ['[?e :expected-deposit/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]}) + :args [(set (map :db/id (:clients args)))]}) (:exact-match-id args) (merge-query {:query {:in ['?e] diff --git a/src/clj/auto_ap/datomic/invoices.clj b/src/clj/auto_ap/datomic/invoices.clj index 1e94ba90..0a40ea28 100644 --- a/src/clj/auto_ap/datomic/invoices.clj +++ b/src/clj/auto_ap/datomic/invoices.clj @@ -49,24 +49,21 @@ ([db args] (let [query (if (:exact-match-id args) - (cond-> {:query {:find '[?e] - :in '[$ ?e] - :where '[[?e :invoice/client ?c]]} - :args [db - (:exact-match-id args)]} - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] - :where ['[?e :invoice/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]})) + {:query {:find '[?e] + :in '[$ ?e [?c ...]] + :where '[[?e :invoice/client ?c]]} + :args [db + (:exact-match-id args) + (map :db/id (:clients args))]} (cond-> {:query {:find [] :in ['$] :where ['[?e :invoice/client]]} :args [db]} - (limited-clients (:id args)) + (seq (:clients args)) (merge-query {:query {:in ['[?xx ...]] :where ['[?e :invoice/client ?xx]]} - :args [ (set (map :db/id (limited-clients (:id args))))]}) + :args [ (map :db/id (:clients args))]}) (:client-id args) (merge-query {:query {:in ['?client-id] :where ['[?e :invoice/client ?client-id]]} @@ -87,14 +84,14 @@ (string? (:original-id args)) Long/parseLong )]}) (:start (:date-range args)) (merge-query {:query {:in '[?start-date] - :where ['[?e :invoice/date ?date] - '[(>= ?date ?start-date)]]} - :args [(coerce/to-date (:start (:date-range args)))]}) + :where ['[?e :invoice/date ?date] + '[(>= ?date ?start-date)]]} + :args [(coerce/to-date (:start (:date-range args)))]}) (:end (:date-range args)) (merge-query {:query {:in '[?end-date] - :where ['[?e :invoice/date ?date] - '[(<= ?date ?end-date)]]} - :args [(coerce/to-date (:end (:date-range args)))]}) + :where ['[?e :invoice/date ?date] + '[(<= ?date ?end-date)]]} + :args [(coerce/to-date (:end (:date-range args)))]}) (:start (:due-range args)) (merge-query {:query {:in '[?start-due] :where ['[?e :invoice/due ?due] diff --git a/src/clj/auto_ap/datomic/ledger.clj b/src/clj/auto_ap/datomic/ledger.clj index 0ca08b8a..bdad1365 100644 --- a/src/clj/auto_ap/datomic/ledger.clj +++ b/src/clj/auto_ap/datomic/ledger.clj @@ -16,24 +16,21 @@ (defn raw-graphql-ids [db args] (let [query (if (:exact-match-id args) - (cond-> {:query {:find '[?e] - :in '[$ ?e] - :where '[[?e :journal-entry/client ?c]]} - :args [db - (:exact-match-id args)]} - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] - :where ['[?e :journal-entry/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]})) + {:query {:find '[?e] + :in '[$ ?e [?c ...]] + :where '[[?e :journal-entry/client ?c]]} + :args [db + (:exact-match-id args) + (map :db/id (:clients args))]} (cond-> {:query {:find [] :in ['$ ] :where []} :args [db]} - (:client-id args) - (merge-query {:query {:in ['?client-id] - :where ['[?e :journal-entry/client ?client-id]]} - :args [(:client-id args)]}) + (seq (:clients args)) + (merge-query {:query {:in ['[?xx ...]] + :where ['[?e :journal-entry/client ?xx]]} + :args [(set (map :db/id (:clients args)))]}) (:only-external args) (merge-query {:query {:where ['(not [?e :journal-entry/original-entity ])]}}) @@ -86,7 +83,7 @@ '[(>= ?c ?from-numeric-code)] '[(<= ?c ?to-numeric-code)]]} :args [(vec (for [{:keys [from to]} (:numeric-code args)] - [(or from 0) (or to 99999)]))]}) + [(or from 0) (or to 99999)]))]}) (:amount-gte args) @@ -127,10 +124,10 @@ :where ['[?e :journal-entry/client ?xx]]} :args [(set (map :db/id (limited-clients (:id args))))]}) (:sort args) (add-sorter-fields {"client" ['[?e :journal-entry/client ?c] - '[?c :client/name ?sort-client]] + '[?c :client/name ?sort-client]] "date" ['[?e :journal-entry/date ?sort-date]] "vendor" ['[?e :journal-entry/vendor ?v] - '[?v :vendor/name ?sort-vendor]] + '[?v :vendor/name ?sort-vendor]] "amount" ['[?e :journal-entry/amount ?sort-amount]] "external-id" ['[?e :journal-entry/external-id ?sort-external-id]] "source" ['[?e :journal-entry/source ?sort-source]]} diff --git a/src/clj/auto_ap/datomic/reports.clj b/src/clj/auto_ap/datomic/reports.clj index 66ce0cf2..6ee700ee 100644 --- a/src/clj/auto_ap/datomic/reports.clj +++ b/src/clj/auto_ap/datomic/reports.clj @@ -21,10 +21,10 @@ :args [db]} - (:client-id args) - (merge-query {:query {:in ['?client-id] - :where ['[?e :report/client ?client-id]]} - :args [(:client-id args)]}) + (seq (:clients args)) + (merge-query {:query {:in ['[?xx ...]] + :where ['[?e :report/client ?xx]]} + :args [(set (map :db/id (:clients args)))]}) (limited-clients (:id args)) (merge-query {:query {:in ['[?xx ...]] diff --git a/src/clj/auto_ap/datomic/sales_orders.clj b/src/clj/auto_ap/datomic/sales_orders.clj index a7533a8c..f5e383c2 100644 --- a/src/clj/auto_ap/datomic/sales_orders.clj +++ b/src/clj/auto_ap/datomic/sales_orders.clj @@ -57,7 +57,7 @@ {:charge/processor [:db/ident]} {:expected-deposit/_charges [:db/id]}]}]) (defn raw-graphql-ids [db args] - (let [visible-clients (visible-clients (:id args)) + (let [visible-clients (set (map :db/id (:clients args))) selected-clients (->> (cond (:client-id args) (set/intersection #{(:client-id args)} diff --git a/src/clj/auto_ap/datomic/transaction_rules.clj b/src/clj/auto_ap/datomic/transaction_rules.clj index 7521fe0f..72bd9f23 100644 --- a/src/clj/auto_ap/datomic/transaction_rules.clj +++ b/src/clj/auto_ap/datomic/transaction_rules.clj @@ -50,15 +50,10 @@ "amount-gte" ['[?e :transaction-rule/amount-gte ?sort-amount-gte]]} args) - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] + (seq (:clients args)) + (merge-query {:query {:in ['[?xx ...]] :where ['[?e :transaction-rule/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]}) - - (:client-id args) - (merge-query {:query {:in ['?client-id] - :where ['[?e :transaction-rule/client ?client-id]]} - :args [(:client-id args)]}) + :args [(set (map :db/id (:clients args)))]}) (:vendor-id args) (merge-query {:query {:in ['?vendor-id] diff --git a/src/clj/auto_ap/datomic/transactions.clj b/src/clj/auto_ap/datomic/transactions.clj index 949e5c6e..16c8bb43 100644 --- a/src/clj/auto_ap/datomic/transactions.clj +++ b/src/clj/auto_ap/datomic/transactions.clj @@ -45,14 +45,11 @@ query (if (:exact-match-id args) (cond-> {:query {:find '[?e] - :in '[$ ?e] + :in '[$ ?e [?c ...]] :where '[[?e :transaction/client ?c]]} :args [db - (:exact-match-id args)]} - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] - :where ['[?e :transaction/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]})) + (:exact-match-id args) + (map :db/id (:clients args))]}) (cond-> {:query {:find [] :in ['$ ] :where []} @@ -62,10 +59,10 @@ (merge-query {:query {:in '[[?e ...]]} :args [potential-duplicates]}) - (limited-clients (:id args)) + (seq (:clients args)) (merge-query {:query {:in ['[?xx ...]] :where ['[?e :transaction/client ?xx]]} - :args [(set (map :db/id (limited-clients (:id args))))]}) + :args [(set (map :db/id (:clients args)))]}) (:bank-account-id args) (merge-query {:query {:in ['?bank-account-id] diff --git a/src/clj/auto_ap/datomic/yodlee2.clj b/src/clj/auto_ap/datomic/yodlee2.clj index 6aae1b04..17316ade 100644 --- a/src/clj/auto_ap/datomic/yodlee2.clj +++ b/src/clj/auto_ap/datomic/yodlee2.clj @@ -23,10 +23,10 @@ :where ['[?e :yodlee-provider-account/id]]} :args [db]} - (limited-clients (:id args)) - (merge-query {:query {:in ['[?xx ...]] + (seq (:clients args)) + (merge-query {:query {:in ['[?xx ...]] :where ['[?e :yodlee-provider-account/client ?xx]]} - :args [ (set (map :db/id (limited-clients (:id args))))]}) + :args [(set (map :db/id (:clients args)))]}) (:client-id args) (merge-query {:query {:in ['?client-id] diff --git a/src/clj/auto_ap/graphql.clj b/src/clj/auto_ap/graphql.clj index d4c7dd39..db3ae3bd 100644 --- a/src/clj/auto_ap/graphql.clj +++ b/src/clj/auto_ap/graphql.clj @@ -862,7 +862,9 @@ (lc/with-context {:query q} (log/info "executing query name" (query-name q)) (try - (let [[result time] (time-it (simplify (execute schema q v {:id id})))] + (let [[result time] (time-it (simplify (execute schema q (dissoc v + :clients) {:id id + :clients (:clients v)})))] (info-event "Query completed" {:time (:time time) :errors (seq (:errors result))}) diff --git a/src/clj/auto_ap/graphql/checks.clj b/src/clj/auto_ap/graphql/checks.clj index 051118c7..5c0e8a44 100644 --- a/src/clj/auto_ap/graphql/checks.clj +++ b/src/clj/auto_ap/graphql/checks.clj @@ -433,7 +433,7 @@ (let [[payments checks-count] (d-checks/get-graphql (-> args :filters (<-graphql) - (assoc :id (:id context)) + (assoc :clients (:clients context)) (update :payment-type enum->keyword "payment-type") (update :status enum->keyword "payment-status")))] @@ -557,10 +557,10 @@ (defn void-payments [context args _] (assert-admin (:id context)) - (let [args (assoc args :id (:id context)) + (let [args (assoc args :clients (:clients context)) ids (some-> args :filters - (assoc :id (:id context)) + (assoc :clients (:clients context)) (<-graphql) (update :payment-type enum->keyword "payment-type") (update :status enum->keyword "payment-status") diff --git a/src/clj/auto_ap/graphql/clients.clj b/src/clj/auto_ap/graphql/clients.clj index 9b2844b7..d4830fac 100644 --- a/src/clj/auto_ap/graphql/clients.clj +++ b/src/clj/auto_ap/graphql/clients.clj @@ -221,7 +221,7 @@ (assert-admin (:id context)) (let [args (assoc args :id (:id context)) [clients clients-count] (d-clients/get-graphql-page (assoc (<-graphql (:filters args)) - :id (:id context))) + :clients (:clients context))) clients (->> clients (map (fn [c] diff --git a/src/clj/auto_ap/graphql/expected_deposit.clj b/src/clj/auto_ap/graphql/expected_deposit.clj index 90d1b4b5..50ac678a 100644 --- a/src/clj/auto_ap/graphql/expected_deposit.clj +++ b/src/clj/auto_ap/graphql/expected_deposit.clj @@ -15,7 +15,7 @@ (first (d-expected-deposit/get-graphql (assoc (<-graphql args) :count Integer/MAX_VALUE))))) (defn get-expected-deposit-page [context args _] - (let [args (assoc args :id (:id context)) + (let [args (assoc args :clients (:clients context)) [expected-deposits expected-deposit-count] (d-expected-deposit/get-graphql (<-graphql args)) expected-deposits (map status->graphql expected-deposits)] diff --git a/src/clj/auto_ap/graphql/invoices.clj b/src/clj/auto_ap/graphql/invoices.clj index 5f7a53fa..b00bfb0a 100644 --- a/src/clj/auto_ap/graphql/invoices.clj +++ b/src/clj/auto_ap/graphql/invoices.clj @@ -37,7 +37,7 @@ (let [args (assoc args :id (:id context)) [invoices invoice-count outstanding total-amount] (-> args :filters - (assoc :id (:id context)) + (assoc :clients (:clients context)) (<-graphql) (update :status enum->keyword "invoice-status") (d-invoices/get-graphql))] diff --git a/src/clj/auto_ap/graphql/ledger.clj b/src/clj/auto_ap/graphql/ledger.clj index 8bd8540f..c2d0ed04 100644 --- a/src/clj/auto_ap/graphql/ledger.clj +++ b/src/clj/auto_ap/graphql/ledger.clj @@ -36,7 +36,7 @@ (defn get-ledger-page [context args _] (let [args (assoc args :id (:id context)) [journal-entries journal-entries-count] (l/get-graphql (assoc (<-graphql (:filters args)) - :id (:id context))) + :clients (:clients context))) journal-entries (mapv (fn [je] @@ -316,7 +316,7 @@ (defn delete-external-ledger [context args _] (let [_ (assert-admin (:id context)) - args (assoc args :id (:id context)) + args (assoc args :clients (:clients context)) ids (some-> (:filters args) (assoc :only-external true) (<-graphql) diff --git a/src/clj/auto_ap/graphql/reports.clj b/src/clj/auto_ap/graphql/reports.clj index d2c28394..94245dab 100644 --- a/src/clj/auto_ap/graphql/reports.clj +++ b/src/clj/auto_ap/graphql/reports.clj @@ -11,7 +11,7 @@ (defn get-report-page [context args _] (let [args (assoc args :id (:id context)) [reports reports-count] (r/get-graphql (assoc (<-graphql (:filters args)) - :id (:id context)))] + :clients (:clients context)))] (result->page reports reports-count :reports (:filters args))) ) diff --git a/src/clj/auto_ap/graphql/sales_orders.clj b/src/clj/auto_ap/graphql/sales_orders.clj index 4f2a3761..660c30c8 100644 --- a/src/clj/auto_ap/graphql/sales_orders.clj +++ b/src/clj/auto_ap/graphql/sales_orders.clj @@ -5,7 +5,7 @@ [auto-ap.graphql.utils :refer [attach-tracing-resolvers]])) (defn get-sales-orders-page [context args _] - (let [args (assoc args :id (:id context)) + (let [args (assoc args :clients (:clients context)) [sales-orders sales-orders-count {:keys [total tax]}] (d-sales-orders2/get-graphql (<-graphql args))] (assoc (result->page sales-orders sales-orders-count :sales_orders args) :sales_order_total total diff --git a/src/clj/auto_ap/graphql/transaction_rules.clj b/src/clj/auto_ap/graphql/transaction_rules.clj index d21e9216..7e56be6f 100644 --- a/src/clj/auto_ap/graphql/transaction_rules.clj +++ b/src/clj/auto_ap/graphql/transaction_rules.clj @@ -20,7 +20,7 @@ [iol-ion.tx :refer [random-tempid]])) (defn get-transaction-rule-page [context args _] - (let [args (assoc args :id (:id context)) + (let [args (assoc args :clients (:clients context)) [journal-entries journal-entries-count] (tr/get-graphql (<-graphql args))] (result->page (->> journal-entries (map (ident->enum-f :transaction-rule/transaction-approval-status))) diff --git a/src/clj/auto_ap/graphql/transactions.clj b/src/clj/auto_ap/graphql/transactions.clj index 4f1a8882..5883c53e 100644 --- a/src/clj/auto_ap/graphql/transactions.clj +++ b/src/clj/auto_ap/graphql/transactions.clj @@ -52,7 +52,8 @@ {:validation-error "In order to select potential duplicates, you must filter your view more."}))))) (defn get-transaction-page [context args _] - (let [args (assoc (:filters args) :id (:id context)) + (let [args (assoc (:filters args) + :clients (:clients context)) _ (assert-filtered-enough args) [transactions transactions-count] (d-transactions/get-graphql (update (<-graphql args) :approval-status enum->keyword "transaction-approval-status")) transactions (map ->graphql (map approval-status->graphql transactions))] @@ -85,7 +86,7 @@ (map first))) (defn bulk-change-status [context args _] (let [_ (assert-admin (:id context)) - args (assoc args :id (:id context)) + args (assoc args :clients (:clients context)) all-ids (->> (get-ids-matching-filters args) all-ids-not-locked)] @@ -137,10 +138,11 @@ (defn bulk-code-transactions [context args _] (assert-admin (:id context)) - (when-not (:client_id args) + (when-not (seq (:client_id args)) (throw (ex-info "Client is required" {:validation-error "client is required"}))) - (let [args (assoc args :id (:id context)) + ;; TODO FIX THIS TO WORK WITH MULTIPLE + (let [args (assoc args :clients (:clients context)) locations (pull-attr (dc/db conn) :client/locations (:client_id args)) @@ -184,7 +186,7 @@ (defn delete-transactions [context args _] (let [_ (assert-admin (:id context)) - args (assoc args :id (:id context)) + args (assoc args :clients (:clients context)) all-ids (all-ids-not-locked (get-ids-matching-filters args)) db (dc/db conn)] diff --git a/src/clj/auto_ap/graphql/yodlee2.clj b/src/clj/auto_ap/graphql/yodlee2.clj index 9f311f10..933cb45e 100644 --- a/src/clj/auto_ap/graphql/yodlee2.clj +++ b/src/clj/auto_ap/graphql/yodlee2.clj @@ -5,7 +5,7 @@ (defn get-yodlee-provider-account-page [context args _] (let [args (assoc args :id (:id context)) - [yodlee-provider-accounts cnt] (d-yodlee2/get-graphql (<-graphql (assoc args :id (:id context))))] + [yodlee-provider-accounts cnt] (d-yodlee2/get-graphql (<-graphql (assoc args :clients (:clients context))))] {:yodlee_provider_accounts (map ->graphql yodlee-provider-accounts) :total cnt :count (count yodlee-provider-accounts) diff --git a/src/clj/auto_ap/routes/graphql.clj b/src/clj/auto_ap/routes/graphql.clj index dd03dfa1..277a550e 100644 --- a/src/clj/auto_ap/routes/graphql.clj +++ b/src/clj/auto_ap/routes/graphql.clj @@ -1,10 +1,47 @@ (ns auto-ap.routes.graphql - (:require [auto-ap.routes.utils :refer [wrap-secure]] - [auto-ap.graphql :as ql] - [auto-ap.logging :refer [warn-event]] - [buddy.auth :refer [throw-unauthorized]] - [clojure.edn :as edn] - [clojure.tools.logging :as log])) + (:require + [auto-ap.datomic :refer [conn pull-many]] + [auto-ap.datomic.clients :as d-clients] + [auto-ap.graphql :as ql] + [auto-ap.graphql.utils :refer [limited-clients]] + [auto-ap.logging :refer [warn-event]] + [auto-ap.routes.utils :refer [wrap-secure]] + [buddy.auth :refer [throw-unauthorized]] + [clojure.edn :as edn] + [clojure.set :as set] + [clojure.tools.logging :as log] + [datomic.api :as dc])) + +(defn headers->clients [identity headers] + (let [x-clients (clojure.edn/read-string (get headers "x-clients")) + ideal-ids (set (cond + (or (= :all x-clients) + (nil? x-clients)) + (->> (dc/q '[:find ?c + :where [?c :client/code]] + (dc/db conn)) + (map first)) + + (= :mine x-clients) + (map :db/id (:user/clients identity)) + + (seq x-clients) + x-clients)) + _ (println "X-CLIENSTT" x-clients) + _ (println "IDEAL" ideal-ids) + _ (println "LIMITS" (limited-clients identity)) + limited-clients (some->> (limited-clients identity) + (map :db/id ) + set) + + client-ids (if (set? limited-clients) + (set/intersection ideal-ids + limited-clients) + ideal-ids)] + (pull-many (dc/db conn) + d-clients/full-read + client-ids))) + (defn handle-graphql [{:keys [request-method query-params] :as r}] (when (= "none" (:user/role (:identity r))) (throw-unauthorized)) @@ -13,8 +50,11 @@ (let [variables (some-> (query-params "variables") edn/read-string) body (some-> r :body slurp)] + {:status 200 - :body (pr-str (ql/query (:identity r) (if (= request-method :get) (query-params "query") body) variables )) + :body (pr-str (ql/query (:identity r) (if (= request-method :get) (query-params "query") body) (assoc variables + :clients + (headers->clients (:identity r) (:headers r))) )) :headers {"Content-Type" "application/edn"}}) (catch Throwable e (log/info "here we are " (.getCause e)) diff --git a/src/clj/auto_ap/ssr/company_dropdown.clj b/src/clj/auto_ap/ssr/company_dropdown.clj index 5b3a31a7..d8fd19d9 100644 --- a/src/clj/auto_ap/ssr/company_dropdown.clj +++ b/src/clj/auto_ap/ssr/company_dropdown.clj @@ -1,7 +1,8 @@ (ns auto-ap.ssr.company-dropdown (:require [auto-ap.datomic :refer [conn pull-many]] - [auto-ap.graphql.utils :refer [assert-can-see-client cleanse-query]] + [auto-ap.graphql.utils + :refer [assert-can-see-client cleanse-query is-admin?]] [auto-ap.solr :as solr] [auto-ap.ssr-routes :as ssr-routes] [auto-ap.ssr.svg :as svg] @@ -125,18 +126,48 @@ function initCompanyDropdown() { ")]]]) (defn active-client [{:keys [identity params] :as request}] - (let [client-id (some-> (or (:search-client params) (get params "search-client")) not-empty Long/parseLong)] - (println (format "HERE CLIENT ID '%s'" client-id)) + (let [client-search (or (:search-client params) + (get params "search-client")) + client-id (try (some-> client-search + (not-empty ) + Long/parseLong) + (catch Exception _ + nil))] (when client-id (assert-can-see-client identity client-id)) - (let [new-session (assoc (:session request) :client + + (let [new-session (assoc (:session request) + + :client (when client-id - (dc/pull (dc/db conn) [:db/id :client/name :client/code] client-id)))] + (dc/pull (dc/db conn) [:db/id :client/name :client/code] client-id)) + + :clients + (cond (int? client-id) + [(dc/pull (dc/db conn) [:db/id :client/name :client/code] client-id)] + + (= ":mine" client-search) + (->> (dc/q '[:find (pull ?c [:db/id :client/name :client/code]) + :in $ ?u + :where [?u :user/clients ?c]] + (dc/db conn) + (:db/id identity)) + (map first)) + + (and (or (empty? client-search) + (= ":all" client-search)) + (is-admin? identity)) + (->> (dc/q '[:find (pull ?c [:db/id :client/name :client/code]) + :in $ ?u + :where [?c :client/code]] + (dc/db conn) + (:db/id identity)) + (map first))))] (assoc - (html-response - (dropdown {:client (:client new-session) - :identity identity})) - :session - new-session - :headers - {"hx-trigger" "clientSelected"})))) + (html-response + (dropdown {:client (:client new-session) + :identity identity})) + :session + new-session + :headers + {"hx-trigger" "clientSelected"})))) diff --git a/src/cljs/auto_ap/effects.cljs b/src/cljs/auto_ap/effects.cljs index 2e594ea2..fa06af1c 100644 --- a/src/cljs/auto_ap/effects.cljs +++ b/src/cljs/auto_ap/effects.cljs @@ -85,6 +85,7 @@ (let [headers (if token (assoc headers "Authorization" (str "Token " token)) headers) + headers (assoc headers "x-clients" (pr-str (:selected-clients @re-frame.db/app-db))) response (data [token] (js->clj (.parse js/JSON (b64/decodeString (second (str/split token #"\." )))))) @@ -127,15 +128,36 @@ ::swap-client [with-user] (fn [{:keys [db user]} [_ client]] - (.setItem js/localStorage "last-client-id" (:id client)) - {:db (assoc db :client (:id client)) - :http {:token user - :method :put - :uri (str (bidi/path-for ssr-routes/only-routes - :active-client - :request-method :put) - "?" - (url/map->query {:search-client (:id client)}))}})) + (let [client-identifier (or (:id client) client)] + (when (:id client) + (.setItem js/localStorage "last-client-id" (:id client))) + (.setItem js/localStorage "last-selected-clients" + (condp = client-identifier + :all + :all + + :mine + :mine + + (pr-str [(js/parseInt (:id client))]))) + + {:db (assoc db :client (:id client) + :selected-clients + (condp = client-identifier + :all + :all + + :mine + :mine + + [(js/parseInt (:id client))])) + :http {:token user + :method :put + :uri (str (bidi/path-for ssr-routes/only-routes + :active-client + :request-method :put) + "?" + (url/map->query {:search-client client-identifier}))}}))) (re-frame/reg-event-fx ::set-active-route diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index 8a32c7b7..444cf7e3 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -23,6 +23,28 @@ (when (:user db) (sort-by :name (vals (:clients db)))))) +(re-frame/reg-sub + ::selected-clients + (fn [db] + (let [selected-clients (:selected-clients db)] + (cond (= :mine selected-clients) + (sort-by :name + (:user/clients (parse-jwt (:user db)))) + + (or (and (sequential? selected-clients) + (empty? selected-clients)) + (= :all selected-clients) + (nil? selected-clients)) + (sort-by :name + (vals + (:clients db))) + + (sequential? selected-clients) + selected-clients + + :else + nil)))) + (re-frame/reg-sub ::client-refs :<- [::clients] diff --git a/src/cljs/auto_ap/views/components/layouts.cljs b/src/cljs/auto_ap/views/components/layouts.cljs index e342fc32..924def3a 100644 --- a/src/cljs/auto_ap/views/components/layouts.cljs +++ b/src/cljs/auto_ap/views/components/layouts.cljs @@ -93,17 +93,29 @@ (defn client-dropdown [] (let [client (re-frame/subscribe [::subs/client]) - matching-clients @(re-frame/subscribe [::matching-clients])] + clients @(re-frame/subscribe [::subs/selected-clients]) + matching-clients @(re-frame/subscribe [::matching-clients]) + user (re-frame/subscribe [::subs/user])] - [navbar-drop-down {:header (str "Company: " (if @client (:name @client) - "All")) - :id ::select-client} + [navbar-drop-down {:header (str "Company: " (cond @client + (:name @client) + + :else + (str (count (or clients [])) " Clients"))) + :id ::select-client} [:div [:a {:class "navbar-item" :on-click (fn [] (re-frame/dispatch [::events/toggle-menu ::select-client]) (re-frame/dispatch [::forms/form-closing ::client-search]) - (re-frame/dispatch [::events/swap-client nil]))} "All" ] + (re-frame/dispatch [::events/swap-client :all]))} "All" ] + (when (= "admin" (:user/role @user)) + [:a {:class "navbar-item" + :on-click (fn [] + (re-frame/dispatch [::events/toggle-menu ::select-client]) + (re-frame/dispatch [::forms/form-closing ::client-search]) + (re-frame/dispatch [::events/swap-client :mine]))} "Mine" ]) + [:hr {:class "navbar-divider"}] [form-builder/builder {:id ::client-search :submit-event [::client-searched]} diff --git a/src/cljs/auto_ap/views/pages/admin/users/form.cljs b/src/cljs/auto_ap/views/pages/admin/users/form.cljs index 91a3a67f..8516a9b0 100644 --- a/src/cljs/auto_ap/views/pages/admin/users/form.cljs +++ b/src/cljs/auto_ap/views/pages/admin/users/form.cljs @@ -75,17 +75,18 @@ [:admin "Admin"]] :allow-nil? false :keywordize? true}]] - (when (#{:user :manager :power_user} (:role data)) - [form-builder/field-v2 {:field :clients} - "Client" - [com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client} - [com/entity-typeahead - {:entities clients - :entity->text :name - :style {:width "13em"}}]]] - :key-fn :id - :schema [:sequential client-schema] - :new-text "Grant access to client"}]]) + [form-builder/field-v2 {:field :clients} + (if (= :admin (:role data)) + "Client Assignments" + "Client") + [com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :client} + [com/entity-typeahead + {:entities clients + :entity->text :name + :style {:width "13em"}}]]] + :key-fn :id + :schema [:sequential client-schema] + :new-text "Grant access to client"}]] [form-builder/hidden-submit-button]]]))