diff --git a/src/clj/auto_ap/graphql/import_batch.clj b/src/clj/auto_ap/graphql/import_batch.clj new file mode 100644 index 00000000..15f9a0a9 --- /dev/null +++ b/src/clj/auto_ap/graphql/import_batch.clj @@ -0,0 +1,63 @@ +(ns auto-ap.graphql.import-batch + (:require + [clojure.tools.logging :as log] + + [datomic.api :as d] + [auto-ap.datomic + :refer [add-sorter-fields apply-pagination apply-sort-3 merge-query conn]] + [auto-ap.graphql.utils :refer [<-graphql assert-admin ident->enum-f result->page]])) + +(def default-read '[:db/id + :import-batch/external-id + :import-batch/date + :import-batch/imported + :import-batch/suppressed + :import-batch/extant + :import-batch/user-name + {:import-batch/source [:db/ident]} + {:import-batch/status [:db/ident]}]) + +(defn raw-graphql-ids [db args] + (let [query (cond-> {:query {:find [] + :in ['$] + :where []} + :args [db]} + + (:sort args) (add-sorter-fields {"date" ['[?e :import-batch/date ?sort-date]]} + args) + + true + (merge-query {:query {:find ['?e] + :where ['[?e :import-batch/date]]}}))] + + + (cond->> query + true (d/query) + true (apply-sort-3 args) + true (apply-pagination args)))) + +(defn graphql-results [ids db args] + (let [results (->> (d/pull-many db default-read ids) + (group-by :db/id))] + (->> ids + (map results) + (map first)))) + +(defn get-graphql [args] + (let [db (d/db conn) + {ids-to-retrieve :ids matching-count :count} (raw-graphql-ids db args)] + [(graphql-results ids-to-retrieve db args) + matching-count])) + +(defn get-import-batch-page [context args value] + (let [_ (assert-admin (:id context)) + args (assoc (:filters args) :id (:id context)) + [values matching-count] (get-graphql (<-graphql args))] + (result->page (->> values + (map (ident->enum-f :import-batch/source)) + (map (ident->enum-f :import-batch/status)) + (map #(update % :import-batch/date clj-time.coerce/to-date-time))) + matching-count :data args))) + + + diff --git a/src/cljs/auto_ap/views/pages/admin/import_batches.cljs b/src/cljs/auto_ap/views/pages/admin/import_batches.cljs new file mode 100644 index 00000000..681efb3b --- /dev/null +++ b/src/cljs/auto_ap/views/pages/admin/import_batches.cljs @@ -0,0 +1,73 @@ +(ns auto-ap.views.pages.admin.import-batches + (:require [auto-ap.forms :as forms] + [auto-ap.subs :as subs] + [auto-ap.views.components.admin.side-bar :refer [admin-side-bar]] + [auto-ap.views.components.layouts :refer [appearing-side-bar side-bar-layout]] + [auto-ap.views.pages.admin.import-batches.table :as table] + [auto-ap.views.utils :refer [dispatch-event with-user]] + [vimsical.re-frame.cofx.inject :as inject] + [vimsical.re-frame.fx.track :as track] + [auto-ap.events :as events] + [auto-ap.utils :refer [replace-by merge-by]] + [re-frame.core :as re-frame] + [auto-ap.status :as status] + [auto-ap.effects.forward :as forward] + [auto-ap.views.pages.data-page :as data-page] + [clojure.set :as set] + [auto-ap.views.components.buttons :as buttons])) + + +(def default-read [:user-name :date :source :status :id :imported :suppressed :extant]) + +(re-frame/reg-event-fx + ::params-change + [with-user ] + (fn [{:keys [db user] :as cofx} [_ params]] + {:graphql {:token user + :owns-state {:single [::data-page/page ::page]} + :query-obj {:venia/queries [{:query/data [:import_batch_page + {:filters {:sort (:sort params) + :start (:start params 0) + :per-page (:per-page params)}} + [[:data default-read] + :total + :start + :end]] + :query/alias :result}]} + :on-success (fn [result] + [::data-page/received ::page + (set/rename-keys (:result result) + {:import-batches :data})])}})) + + +(re-frame/reg-event-fx + ::mounted + (fn [{:keys [db]}] + {::track/register {:id ::params + :subscription [::data-page/params ::page] + :event-fn (fn [params] + [::params-change params])}})) + +(re-frame/reg-event-fx + ::unmounted + (fn [{:keys [db]}] + {:dispatch [::data-page/dispose ::page] + ::track/dispose {:id ::params}})) + +;; VIEWS +(def import-batch-content + (with-meta + (fn [] + (let [user @(re-frame/subscribe [::subs/user])] + [:div + [:h1.title "Import Batches"] + (when (= "admin" (:user/role user)) + [table/table {:id :import-batches + :data-page ::page}])])) + {:component-did-mount (dispatch-event [::mounted ]) + :component-will-unmount #(re-frame/dispatch-sync [::unmounted])})) + +(defn import-batches-page [] + [side-bar-layout {:side-bar [admin-side-bar {}] + :main [import-batch-content]}]) + diff --git a/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs b/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs new file mode 100644 index 00000000..6d725c82 --- /dev/null +++ b/src/cljs/auto_ap/views/pages/admin/import_batches/table.cljs @@ -0,0 +1,87 @@ +(ns auto-ap.views.pages.admin.import-batches.table + (:require + [auto-ap.status :as status] + [auto-ap.subs :as subs] + [auto-ap.views.components.buttons :as buttons] + [auto-ap.views.components.grid :as grid] + [auto-ap.views.pages.data-page :as data-page] + [auto-ap.views.utils :refer [date->str dispatch-event action-cell-width]] + [re-frame.core :as re-frame] + [reagent.core :as r] + [bidi.bidi :as bidi] + [auto-ap.routes :as routes] + [cemerick.url :as url])) + +(re-frame/reg-sub + ::specific-table-params + (fn [db] + (::table-params db))) + + +(re-frame/reg-event-db + ::unmounted + (fn [db] + (status/reset-multi db ::run))) + +(re-frame/reg-sub + ::table-params + :<- [::specific-table-params] + :<- [::subs/query-params] + (fn [[specific-table-params query-params]] + (merge (select-keys query-params #{:start :sort}) specific-table-params ))) + +(re-frame/reg-event-fx + ::params-changed + [(re-frame/path [::table-params])] + (fn [{table-params :db} [_ params :as z]] + {:db (merge table-params params)})) + +(defn table* [{:keys [id data-page]}] + (let [{:keys [data]} @(re-frame/subscribe [::data-page/page data-page])] + [grid/grid {:data-page data-page + :column-count 6} + [grid/controls data] + [grid/table {:fullwidth true } + [grid/header + [grid/row {} + [grid/sortable-header-cell {:sort-key "date" + :sort-name "Date"} + "Date"] + + [grid/sortable-header-cell {:sort-key "source" + :sort-name "Source"} + "Source"] + + [grid/sortable-header-cell {:sort-key "status" + :sort-name "Status"} + "Status"] + + [grid/sortable-header-cell {:sort-key "user" + :sort-name "User"} + "User"] + [grid/header-cell {:style {:width "7em"}} "Imported"] + [grid/header-cell {:style {:width "7em"}} "Preexisting"] + [grid/header-cell {:style {:width "7em"}} "Suppressed"] + [grid/header-cell {:style {:width (action-cell-width 3)}}]]] + [grid/body + (for [{:keys [date source status user-name id imported extant suppressed] :as r} (:data data)] + ^{:key id} + [grid/row {:class (:class r) :id id} + [grid/cell {} (date->str date)] + [grid/cell {} source] + [grid/cell {} status] + [grid/cell {} user-name] + [grid/cell {} imported] + [grid/cell {} extant] + [grid/cell {} suppressed] + [grid/button-cell {} + [buttons/fa-icon {:href (str (bidi/path-for routes/routes :transactions) + "?" + (url/map->query {:import-batch-id id})) + :icon "fa-external-link"}]] + ])]]])) + +(defn table [params] + (r/create-class {:component-will-unmount (dispatch-event [::unmounted]) + :reagent-render (fn [params] + [table* params])}))