Compare commits
4 Commits
d52159637e
...
integreat-
| Author | SHA1 | Date | |
|---|---|---|---|
| 3759258ebe | |||
| 55650c2dab | |||
| 19186097d5 | |||
| 1f6395382d |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -51,3 +51,6 @@ sysco-poller/**/*.csv
|
|||||||
.tmp/**
|
.tmp/**
|
||||||
playwright-report/**
|
playwright-report/**
|
||||||
test-results/**
|
test-results/**
|
||||||
|
# Scratch dir for temp files (screenshots, logs, etc.); keep the dir, ignore contents
|
||||||
|
/tmp/*
|
||||||
|
!/tmp/.gitkeep
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Integreat Development Guide
|
# Integreat Development Guide
|
||||||
|
|
||||||
|
## Temporary Files
|
||||||
|
|
||||||
|
Write any temporary files (screenshots, scratch logs, generated artifacts, etc.) to the `./tmp/` directory at the repo root. Its contents are gitignored (only `.gitkeep` is tracked), so nothing there will be accidentally committed. Do not scatter temp files elsewhere in the repo or in the system `/tmp`.
|
||||||
|
|
||||||
## Build & Run Commands
|
## Build & Run Commands
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|||||||
@@ -10,8 +10,7 @@
|
|||||||
[bidi.bidi :as bidi]
|
[bidi.bidi :as bidi]
|
||||||
[clj-time.coerce :as coerce]
|
[clj-time.coerce :as coerce]
|
||||||
[clj-time.core :as time]
|
[clj-time.core :as time]
|
||||||
[datomic.api :as dc]
|
[datomic.api :as dc]))
|
||||||
[hiccup2.core :as hiccup]))
|
|
||||||
|
|
||||||
(defn hourly-changes []
|
(defn hourly-changes []
|
||||||
(let [tx-instant-attr (:db/id (dc/pull (dc/db conn) '[:db/id] :db/txInstant))
|
(let [tx-instant-attr (:db/id (dc/pull (dc/db conn) '[:db/id] :db/txInstant))
|
||||||
@@ -56,34 +55,68 @@
|
|||||||
[:div
|
[:div
|
||||||
[:h1.text-2xl.mb-3.font-bold "Growth in clients"]
|
[:h1.text-2xl.mb-3.font-bold "Growth in clients"]
|
||||||
[:div
|
[:div
|
||||||
[:div {:class "w-full h-64"
|
[:div.w-full.h-64
|
||||||
:id "client-chart"
|
[:canvas.w-full.h-full {:x-data (hx/json {:chart nil
|
||||||
:data-chart (hx/json {:labels ["2 years ago" "1 year ago" "today"],
|
:labels ["2 years ago" "1 year ago" "today"]
|
||||||
:series [(for [n [2 1 0]
|
:data (for [n [2 1 0]
|
||||||
:let [start (time/plus (time/now) (time/years (- n)))]]
|
:let [start (time/plus (time/now) (time/years (- n)))]]
|
||||||
(->> (dc/q '[:find (count ?c)
|
(->> (dc/q '[:find (count ?c)
|
||||||
:in $
|
:in $
|
||||||
:where [?c :client/code]]
|
:where [?c :client/code]]
|
||||||
(dc/as-of (dc/db conn) (coerce/to-date start)))
|
(dc/as-of (dc/db conn) (coerce/to-date start)))
|
||||||
first
|
first
|
||||||
first))]})}]
|
first))})
|
||||||
[:script {:lang "javascript"}
|
:x-init "new Chart($el, {
|
||||||
(hiccup/raw
|
type: 'bar',
|
||||||
"new Chartist.Bar('#client-chart', JSON.parse(document.getElementById('client-chart').getAttribute('data-chart')))")]]]])
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Clients',
|
||||||
|
data: data,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});"}]]]]])
|
||||||
|
|
||||||
(com/content-card {:class "w-1/2"}
|
(com/content-card {:class "w-1/2"}
|
||||||
[:div {:class "flex flex-col px-4 py-3 space-y-3"}
|
[:div {:class "flex flex-col px-4 py-3 space-y-3"}
|
||||||
[:div
|
[:div
|
||||||
[:h1.text-2xl.mb-3.font-bold "Changes by hour"]
|
[:h1.text-2xl.mb-3.font-bold "Changes by hour"]
|
||||||
[:div
|
[:div
|
||||||
[:div {:class "w-full h-64"
|
[:div.w-full.h-64
|
||||||
:id "changes"
|
[:canvas.w-full.h-full {:x-data (hx/json {:chart nil
|
||||||
:data-chart (hx/json {:labels (for [n (range -24 0)]
|
:labels (for [n (range -24 0)]
|
||||||
(format "%d" n)),
|
(format "%d" n))
|
||||||
:series [(hourly-changes)]})}]
|
:data (hourly-changes)})
|
||||||
[:script {:lang "javascript"}
|
:x-init "new Chart($el, {
|
||||||
(hiccup/raw
|
type: 'line',
|
||||||
"new Chartist.Line('#changes', JSON.parse(document.getElementById('changes').getAttribute('data-chart')))")]]]])])
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Changes',
|
||||||
|
data: data,
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});"}]]]]])])
|
||||||
"Admin"))
|
"Admin"))
|
||||||
|
|
||||||
(def key->handler
|
(def key->handler
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
::route/table)
|
::route/table)
|
||||||
"hx-target" "#entity-table"
|
"hx-target" "#entity-table"
|
||||||
|
|||||||
@@ -14,5 +14,5 @@
|
|||||||
[:section (merge params {:class (hh/add-class " py-3 sm:py-5" (:class params))})
|
[:section (merge params {:class (hh/add-class " py-3 sm:py-5" (:class params))})
|
||||||
[:div {:class (:max-w params "max-w-screen-2xl")}
|
[:div {:class (:max-w params "max-w-screen-2xl")}
|
||||||
(into
|
(into
|
||||||
[:div {:class "relative overflow-scroll shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white"}]
|
[:div {:class "relative overflow-auto shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white"}]
|
||||||
children)]])
|
children)]])
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
[clj-time.core :as t]
|
[clj-time.core :as t]
|
||||||
[clj-time.periodic :as per]))
|
[clj-time.periodic :as per]))
|
||||||
|
|
||||||
(defn date-range-field [{:keys [value id apply-button?]}]
|
(defn date-range-field [{:keys [value id]}]
|
||||||
[:div {:id id}
|
[:div {:id id}
|
||||||
(com/field {:label "Date Range"}
|
(com/field {:label "Date Range"}
|
||||||
[:div.space-y-4
|
[:div.space-y-4
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
|
(com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
|
||||||
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
|
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
|
||||||
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))]
|
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))]
|
||||||
[:div.flex.space-x-1.items-baseline.w-full.justify-start
|
[:div.flex.space-x-1.items-baseline.w-full.justify-start {"@change.stop" ""}
|
||||||
(com/date-input {:name "start-date"
|
(com/date-input {:name "start-date"
|
||||||
:value (some-> (:start value)
|
:value (some-> (:start value)
|
||||||
(atime/unparse-local atime/normal-date))
|
(atime/unparse-local atime/normal-date))
|
||||||
@@ -31,9 +31,8 @@
|
|||||||
:placeholder "Date"
|
:placeholder "Date"
|
||||||
:size :small
|
:size :small
|
||||||
:class "shrink date-filter-input"})
|
:class "shrink date-filter-input"})
|
||||||
(when apply-button?
|
(but/button- {:color :secondary
|
||||||
(but/button- {:color :secondary
|
:size :small
|
||||||
:size :small
|
:type "button"
|
||||||
:type "button"
|
"x-on:click" "$dispatch('datesApplied')"}
|
||||||
"x-on:click" "$dispatch('datesApplied')"}
|
"Apply")]])])
|
||||||
"Apply"))]])])
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
[:div {:id "exact-match-id-tag"}]))
|
[:div {:id "exact-match-id-tag"}]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form#invoice-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form#invoice-filters {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
::route/import-table)
|
::route/import-table)
|
||||||
"hx-target" "#entity-table"
|
"hx-target" "#entity-table"
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
[:div {:id "exact-match-id-tag"}]))
|
[:div {:id "exact-match-id-tag"}]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form#payment-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form#payment-filters {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
::route/table)
|
::route/table)
|
||||||
"hx-target" "#entity-table"
|
"hx-target" "#entity-table"
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
|
|
||||||
(defn filters [params]
|
(defn filters [params]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:pos-cash-drawer-shift-table)
|
:pos-cash-drawer-shift-table)
|
||||||
"hx-target" "#cash-drawer-shift-table"
|
"hx-target" "#cash-drawer-shift-table"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:pos-expected-deposit-table)
|
:pos-expected-deposit-table)
|
||||||
"hx-target" "#expected-deposit-table"
|
"hx-target" "#expected-deposit-table"
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
[:client {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :client/name]}]]]]
|
[:client {:optional true :default nil} [:maybe [:entity-map {:pull [:db/id :client/name]}]]]]
|
||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:pos-refund-table)
|
:pos-refund-table)
|
||||||
"hx-target" "#refund-table"
|
"hx-target" "#refund-table"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:pos-sales-table)
|
:pos-sales-table)
|
||||||
"hx-target" "#sales-table"
|
"hx-target" "#sales-table"
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
default-grid-fields-schema)]))
|
default-grid-fields-schema)]))
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
::route/table)
|
::route/table)
|
||||||
"hx-target" "#entity-table"
|
"hx-target" "#entity-table"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
;; always should be fast
|
;; always should be fast
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
:pos-tender-table)
|
:pos-tender-table)
|
||||||
"hx-target" "#tender-table"
|
"hx-target" "#tender-table"
|
||||||
|
|||||||
@@ -316,7 +316,7 @@
|
|||||||
:content (:bank-account/name ba)}))}))))])
|
:content (:bank-account/name ba)}))}))))])
|
||||||
|
|
||||||
(defn filters [request]
|
(defn filters [request]
|
||||||
[:form#transaction-filters {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
[:form#transaction-filters {"hx-trigger" "datesApplied, change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
|
||||||
"hx-get" (bidi/path-for ssr-routes/only-routes
|
"hx-get" (bidi/path-for ssr-routes/only-routes
|
||||||
::route/table)
|
::route/table)
|
||||||
"hx-target" "#entity-table"
|
"hx-target" "#entity-table"
|
||||||
|
|||||||
@@ -23,8 +23,6 @@
|
|||||||
[:title (str "Integreat | " page-name)]
|
[:title (str "Integreat | " page-name)]
|
||||||
[:link {:href "/css/font.min.css", :rel "stylesheet"}]
|
[:link {:href "/css/font.min.css", :rel "stylesheet"}]
|
||||||
[:link {:rel "icon" :type "image/png" :href "/favicon.png"}]
|
[:link {:rel "icon" :type "image/png" :href "/favicon.png"}]
|
||||||
[:link {:rel "stylesheet" :href "//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css"}]
|
|
||||||
[:script {:src "//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"}]
|
|
||||||
[:link {:rel "stylesheet", :href "/output.css"}]
|
[:link {:rel "stylesheet", :href "/output.css"}]
|
||||||
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
|
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
|
||||||
[:script {:src "https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" :defer true}]
|
[:script {:src "https://cdn.jsdelivr.net/npm/@ryangjchandler/alpine-tooltip@1.x.x/dist/cdn.min.js" :defer true}]
|
||||||
|
|||||||
0
tmp/.gitkeep
Normal file
0
tmp/.gitkeep
Normal file
Reference in New Issue
Block a user