Adds new default admin page
This commit is contained in:
@@ -210,3 +210,13 @@
|
|||||||
.arrow {
|
.arrow {
|
||||||
bottom: -4px;
|
bottom: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Use this selector to override the line style on a given series */
|
||||||
|
.ct-series-a .ct-bar {
|
||||||
|
/* Set the colour of this series line */
|
||||||
|
stroke: #79b52e;
|
||||||
|
fill: #79b52e;
|
||||||
|
/* Control the thikness of your lines */
|
||||||
|
stroke-width: 20px;
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
98
src/clj/auto_ap/ssr/admin.clj
Normal file
98
src/clj/auto_ap/ssr/admin.clj
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
(ns auto-ap.ssr.admin
|
||||||
|
(:require
|
||||||
|
[auto-ap.datomic :refer [conn]]
|
||||||
|
[auto-ap.routes.utils
|
||||||
|
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
|
||||||
|
[auto-ap.ssr-routes :as ssr-routes]
|
||||||
|
[auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.hx :as hx]
|
||||||
|
[auto-ap.ssr.ui :refer [base-page]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
|
[clj-time.coerce :as coerce]
|
||||||
|
[clj-time.core :as time]
|
||||||
|
[datomic.api :as dc]
|
||||||
|
[hiccup2.core :as hiccup]))
|
||||||
|
|
||||||
|
(defn hourly-changes []
|
||||||
|
(let [tx-instant-attr (:db/id (dc/pull (dc/db conn) '[:db/id] :db/txInstant))
|
||||||
|
tx-lookup (->>
|
||||||
|
(dc/tx-range
|
||||||
|
(dc/log conn)
|
||||||
|
(coerce/to-date (time/plus (time/now) (time/hours -24)))
|
||||||
|
(coerce/to-date (time/now)))
|
||||||
|
(map (fn extract-tx-instant [tx]
|
||||||
|
(let [tx-id (->> (:data tx)
|
||||||
|
(map (fn [d]
|
||||||
|
(:tx d)))
|
||||||
|
first)
|
||||||
|
tx-instant (->> tx
|
||||||
|
:data
|
||||||
|
(filter (fn [d]
|
||||||
|
(and (= (:e d) tx-id)
|
||||||
|
(= tx-instant-attr (:a d)))))
|
||||||
|
(map :v)
|
||||||
|
first)]
|
||||||
|
|
||||||
|
tx-instant)))
|
||||||
|
(group-by (fn hours-ago [d]
|
||||||
|
(time/in-hours (time/interval (coerce/to-date-time d) (time/now)))
|
||||||
|
))
|
||||||
|
)]
|
||||||
|
(for [h (range 24)]
|
||||||
|
(count (tx-lookup h [])))))
|
||||||
|
|
||||||
|
(defn page [request]
|
||||||
|
(base-page
|
||||||
|
request
|
||||||
|
(com/page {:nav (com/admin-aside-nav)
|
||||||
|
:client-selection (:client-selection (:session request))
|
||||||
|
:clients (:clients request)
|
||||||
|
:client (:client request)
|
||||||
|
:identity (:identity request)}
|
||||||
|
(com/breadcrumbs {} [:a {:href (bidi/path-for ssr-routes/only-routes :auto-ap.routes.admin/page)}
|
||||||
|
"Admin"])
|
||||||
|
[:div.flex.space-x-4
|
||||||
|
(com/content-card {:class "w-1/4"}
|
||||||
|
[:div {:class "flex flex-col px-4 py-3 space-y-3"}
|
||||||
|
[:div
|
||||||
|
[:h1.text-2xl.mb-3.font-bold "Growth in clients"]
|
||||||
|
[:div
|
||||||
|
[:div {:class "w-full h-64"
|
||||||
|
:id "client-chart"
|
||||||
|
:data-chart (hx/json {
|
||||||
|
:labels ["2 years ago" "1 year ago" "today"],
|
||||||
|
:series [(for [n [2 1 0]
|
||||||
|
:let [start (time/plus (time/now) (time/years (- n)))]]
|
||||||
|
(->> (dc/q '[:find (count ?c)
|
||||||
|
:in $
|
||||||
|
:where [?c :client/code]]
|
||||||
|
(dc/as-of (dc/db conn) (coerce/to-date start)))
|
||||||
|
first
|
||||||
|
first))]})}]
|
||||||
|
[:script {:lang "javascript"}
|
||||||
|
(hiccup/raw
|
||||||
|
"new Chartist.Bar('#client-chart', JSON.parse(document.getElementById('client-chart').getAttribute('data-chart')))")]]]])
|
||||||
|
|
||||||
|
(com/content-card {:class "w-1/2"}
|
||||||
|
[:div {:class "flex flex-col px-4 py-3 space-y-3"}
|
||||||
|
[:div
|
||||||
|
[:h1.text-2xl.mb-3.font-bold "Changes by hour"]
|
||||||
|
[:div
|
||||||
|
[:div {:class "w-full h-64"
|
||||||
|
:id "changes"
|
||||||
|
:data-chart (hx/json {
|
||||||
|
:labels (for [n (range -24 0)]
|
||||||
|
(format "%d" n)),
|
||||||
|
:series [(hourly-changes)]})}]
|
||||||
|
[:script {:lang "javascript"}
|
||||||
|
(hiccup/raw
|
||||||
|
"new Chartist.Line('#changes', JSON.parse(document.getElementById('changes').getAttribute('data-chart')))")]]]])]
|
||||||
|
)
|
||||||
|
"Admin")
|
||||||
|
)
|
||||||
|
|
||||||
|
(def key->handler
|
||||||
|
{
|
||||||
|
:auto-ap.routes.admin/page (wrap-client-redirect-unauthenticated (wrap-admin page))
|
||||||
|
})
|
||||||
|
|
||||||
@@ -192,8 +192,7 @@
|
|||||||
[:ul {:class "space-y-2"}
|
[:ul {:class "space-y-2"}
|
||||||
[:li
|
[:li
|
||||||
(menu-button- {:icon svg/dashboard
|
(menu-button- {:icon svg/dashboard
|
||||||
:href (bidi/path-for client-routes/routes
|
:href (bidi/path-for ssr-routes/only-routes :auto-ap.routes.admin/page)}
|
||||||
:admin)}
|
|
||||||
"Dashboard")]
|
"Dashboard")]
|
||||||
|
|
||||||
[:li
|
[:li
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
(ns auto-ap.ssr.components.card)
|
(ns auto-ap.ssr.components.card
|
||||||
|
(:require [auto-ap.ssr.hiccup-helper :as hh]
|
||||||
|
[auto-ap.ssr.hx :as hx]))
|
||||||
|
|
||||||
(defn card- [params & children]
|
(defn card- [params & children]
|
||||||
(into [:div (update params :class str " shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white overflow-hidden")]
|
(into [:div (update params :class str " shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white overflow-hidden")]
|
||||||
children))
|
children))
|
||||||
|
|
||||||
(defn content-card- [params & children]
|
(defn content-card- [params & children]
|
||||||
[:section {:class " py-3 sm:py-5"}
|
[:section {:class (hh/add-class " py-3 sm:py-5" (:class params))}
|
||||||
[:div {:class "max-w-screen-2xl"}
|
[:div {:class "max-w-screen-2xl"}
|
||||||
(into
|
(into
|
||||||
[:div {:class "relative overflow-hidden shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white"}]
|
[:div {:class "relative overflow-hidden shadow-md dark:bg-gray-800 sm:rounded-lg border-2 border-gray-200 dark:border-gray-900 bg-white"}]
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
[auto-ap.ssr.admin.history :as history]
|
[auto-ap.ssr.admin.history :as history]
|
||||||
[auto-ap.ssr.admin.background-jobs :as admin-jobs]
|
[auto-ap.ssr.admin.background-jobs :as admin-jobs]
|
||||||
[auto-ap.ssr.auth :as auth]
|
[auto-ap.ssr.auth :as auth]
|
||||||
|
[auto-ap.ssr.admin :as admin]
|
||||||
[auto-ap.ssr.company :as company]
|
[auto-ap.ssr.company :as company]
|
||||||
[auto-ap.ssr.company-dropdown :as company-dropdown]
|
[auto-ap.ssr.company-dropdown :as company-dropdown]
|
||||||
[auto-ap.ssr.company.company-1099 :as company-1099]
|
[auto-ap.ssr.company.company-1099 :as company-1099]
|
||||||
@@ -82,6 +83,7 @@
|
|||||||
(into pos-refunds/key->handler)
|
(into pos-refunds/key->handler)
|
||||||
(into users/key->handler)
|
(into users/key->handler)
|
||||||
(into admin-accounts/key->handler)
|
(into admin-accounts/key->handler)
|
||||||
|
(into admin/key->handler)
|
||||||
(into admin-jobs/key->handler)
|
(into admin-jobs/key->handler)
|
||||||
(into admin-rules/key->handler)))
|
(into admin-rules/key->handler)))
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
(ns auto-ap.ssr.pos.common
|
(ns auto-ap.ssr.pos.common
|
||||||
(:require [auto-ap.ssr.components :as com]
|
(:require [auto-ap.ssr.components :as com]
|
||||||
|
[auto-ap.ssr.components.date-range :as dr]
|
||||||
[auto-ap.time :as atime]
|
[auto-ap.time :as atime]
|
||||||
[auto-ap.ssr.svg :as svg]))
|
[auto-ap.ssr.svg :as svg]))
|
||||||
|
(defn date-range-field* [request]
|
||||||
|
(dr/date-range-field {:value {:start (:start-date (:parsed-query-params request))
|
||||||
|
:end (:end-date (:parsed-query-params request))}
|
||||||
|
:id "date-range"}))
|
||||||
|
|
||||||
(defn processor-field* [request]
|
(defn processor-field* [request]
|
||||||
(com/field {:label "Processor"}
|
(com/field {:label "Processor"}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
[: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://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
|
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
|
||||||
@@ -55,6 +57,7 @@
|
|||||||
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
|
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
|
||||||
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.x.x/dist/cdn.min.js"}]
|
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.x.x/dist/cdn.min.js"}]
|
||||||
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"}]
|
[:script {:defer true :src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"}]
|
||||||
|
|
||||||
[:style
|
[:style
|
||||||
"
|
"
|
||||||
input::-webkit-outer-spin-button,
|
input::-webkit-outer-spin-button,
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
"needs-activation/" :needs-activation
|
"needs-activation/" :needs-activation
|
||||||
"needs-activation" :needs-activation
|
"needs-activation" :needs-activation
|
||||||
"payments/" :payments
|
"payments/" :payments
|
||||||
"admin/" {"" :admin
|
"admin/" {"clients/" {"" :admin-clients
|
||||||
"clients/" {"" :admin-clients
|
|
||||||
[:id] {"" :admin-specific-client
|
[:id] {"" :admin-specific-client
|
||||||
"/bank-accounts/" {[:bank-account] :admin-specific-bank-account}}}
|
"/bank-accounts/" {[:bank-account] :admin-specific-bank-account}}}
|
||||||
"rules" :admin-rules
|
|
||||||
"vendors" :admin-vendors
|
"vendors" :admin-vendors
|
||||||
"excel-import" :admin-excel-import
|
"excel-import" :admin-excel-import
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"/create" {:post :invoice-glimpse-create-invoice}
|
"/create" {:post :invoice-glimpse-create-invoice}
|
||||||
"/update" {:patch :invoice-glimpse-update-textract-invoice}}}}}
|
"/update" {:patch :invoice-glimpse-update-textract-invoice}}}}}
|
||||||
"account" {"/search" {:get :account-search}}
|
"account" {"/search" {:get :account-search}}
|
||||||
"admin" {"/history" {"" :admin-history
|
"admin" {"" :auto-ap.routes.admin/page
|
||||||
|
"/history" {"" :admin-history
|
||||||
"/" :admin-history
|
"/" :admin-history
|
||||||
#"/search/?" :admin-history-search
|
#"/search/?" :admin-history-search
|
||||||
["/" [#"\d+" :entity-id] #"/?"] :admin-history
|
["/" [#"\d+" :entity-id] #"/?"] :admin-history
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
[:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/started {}])} "New Vendor"]
|
[:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/started {}])} "New Vendor"]
|
||||||
[:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/edit {}])} "Edit Vendor"]
|
[:a.dropdown-item {:on-click (dispatch-event-with-propagation [::vendor-dialog/edit {}])} "Edit Vendor"]
|
||||||
(when (= "admin" (:user/role @user))
|
(when (= "admin" (:user/role @user))
|
||||||
[:a {:class "navbar-item" :href (bidi/path-for routes/routes :admin)} "Administration"])
|
[:a {:class "navbar-item" :href (bidi/path-for ssr-routes/only-routes :auto-ap.routes.admin/page)} "Administration"])
|
||||||
[:hr {:class "navbar-divider"}]
|
[:hr {:class "navbar-divider"}]
|
||||||
[:a.navbar-item {:on-click (fn []
|
[:a.navbar-item {:on-click (fn []
|
||||||
(.removeItem js/localStorage "last-client-id" nil)
|
(.removeItem js/localStorage "last-client-id" nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user