217 lines
9.6 KiB
Clojure
217 lines
9.6 KiB
Clojure
(ns auto-ap.views.components.layouts
|
|
(:require
|
|
[cljsjs.react-transition-group]
|
|
[reagent.core :as reagent]
|
|
[re-frame.core :as re-frame]
|
|
[bidi.bidi :as bidi]
|
|
[auto-ap.routes :as routes]
|
|
[auto-ap.subs :as subs]
|
|
[auto-ap.events :as events]
|
|
[auto-ap.views.utils :refer [active-when active-when= login-url dispatch-event appearing css-transition-group bind-field]]
|
|
[auto-ap.views.components.vendor-dialog :refer [vendor-dialog]]
|
|
|
|
[auto-ap.views.components.vendor-dialog :refer [vendor-dialog]]
|
|
[auto-ap.views.components.modal :as modal]
|
|
[auto-ap.entities.vendors :as vendor]
|
|
[auto-ap.views.components.vendor-dialog :as vendor-dialog]
|
|
[clojure.string :as str]))
|
|
|
|
|
|
(defn navbar-drop-down-contents [{:keys [id]} children ]
|
|
(let [toggle-fn (fn [] (re-frame/dispatch [::events/toggle-menu id]))]
|
|
(reagent/create-class {:component-did-mount (fn [] (.addEventListener js/document "click" toggle-fn))
|
|
:component-will-unmount (fn [] (.removeEventListener js/document "click" toggle-fn))
|
|
:reagent-render
|
|
(fn [children]
|
|
children)})))
|
|
|
|
(defn navbar-drop-down [{:keys [ header id class]} child]
|
|
(let [menu-active? (re-frame/subscribe [::subs/menu-active? id])]
|
|
(reagent/create-class
|
|
{:reagent-render (fn [{:keys [header id]} child]
|
|
(let [menu-active? @(re-frame/subscribe [::subs/menu-active? id])]
|
|
[:div { :class (str "navbar-item has-dropdown " (when menu-active? "is-active " ) " " class)}
|
|
[:a {:class "navbar-link login" :on-click (fn [e]
|
|
(.preventDefault e)
|
|
(.stopPropagation e)
|
|
(re-frame/dispatch [::events/toggle-menu id])
|
|
true)} header]
|
|
[appearing {:visible? menu-active? :enter-class "appear" :exit-class "disappear" :timeout 200}
|
|
[:div {:class "navbar-dropdown"}
|
|
[navbar-drop-down-contents {:id id}
|
|
[:div child]]]]]))})))
|
|
|
|
(defn login-dropdown []
|
|
(let [user (re-frame/subscribe [::subs/user])
|
|
menu (re-frame/subscribe [::subs/menu])]
|
|
(if @user
|
|
[navbar-drop-down {:header [:span [:span.icon [:i.fa.fa-user] ]
|
|
[:span (:user/name @user)]] :id ::account}
|
|
[:div
|
|
[:a {:class "navbar-item"} "My profile"]
|
|
(when (= "admin" (:user/role @user))
|
|
[:a {:class "navbar-item" :href (bidi/path-for routes/routes :admin)} "Administration"])
|
|
[:hr {:class "navbar-divider"}]
|
|
[:a.navbar-item {:on-click (fn [e] (.preventDefault e) (re-frame/dispatch [::events/logout]))} "Logout"]]]
|
|
[:a.navbar-item {:href login-url} "Login"])))
|
|
|
|
(re-frame/reg-sub
|
|
::client-search
|
|
(fn [db]
|
|
(::client-search db)))
|
|
|
|
(re-frame/reg-sub
|
|
::matching-clients
|
|
:<- [::subs/clients]
|
|
:<- [::client-search]
|
|
(fn [[clients {client-search :value}]]
|
|
(if (empty? client-search)
|
|
clients
|
|
(if-let [exact-match (first (filter
|
|
(fn [client]
|
|
(= (str/lower-case (:code client)) (str/lower-case client-search)))
|
|
clients))]
|
|
[exact-match]
|
|
(filter
|
|
(fn [client]
|
|
(or
|
|
(str/includes? (str/lower-case (:code client)) (str/lower-case client-search))
|
|
(str/includes? (str/lower-case (:name client)) (str/lower-case client-search))))
|
|
clients)))))
|
|
|
|
(re-frame/reg-event-db
|
|
::client-search-changed
|
|
[(re-frame/path [::client-search])]
|
|
(fn [client-search [_ path value]]
|
|
(assoc-in client-search path value)))
|
|
|
|
(defn navbar [ap]
|
|
(let [user (re-frame/subscribe [::subs/user])
|
|
client (re-frame/subscribe [::subs/client])
|
|
clients (re-frame/subscribe [::subs/clients])
|
|
matching-clients @(re-frame/subscribe [::matching-clients])
|
|
menu (re-frame/subscribe [::subs/menu])
|
|
client-search @(re-frame/subscribe [::client-search])
|
|
is-initial-loading @(re-frame/subscribe [::subs/is-initial-loading?])]
|
|
[:nav {:class "navbar has-shadow is-fixed-top"}
|
|
[:div {:class "container"}
|
|
[:div {:class "navbar-brand"}
|
|
[:a {:class "navbar-item", :href "../"}
|
|
[:img {:src "/img/logo.png"}]]]
|
|
[:div.navbar-menu
|
|
(when-not is-initial-loading
|
|
[:div.navbar-start
|
|
[:a.navbar-item {:class [(active-when ap = :index)]
|
|
:href (bidi/path-for routes/routes :index)}
|
|
"Home" ]
|
|
[:a.navbar-item {:class [(active-when ap #{:unpaid-invoices :paid-invoices})]
|
|
:href (bidi/path-for routes/routes :unpaid-invoices)}
|
|
"Invoices" ]
|
|
[:a.navbar-item {:class [(active-when ap = :payments)]
|
|
:href (bidi/path-for routes/routes :payments)}
|
|
"Payments" ]
|
|
[:a.navbar-item {:class [(active-when ap = :transactions)]
|
|
:href (bidi/path-for routes/routes :transactions)}
|
|
"Transactions" ]
|
|
|
|
(when (not= "manager" (:user/role @user))
|
|
[:a.navbar-item {:class [(active-when ap = :ledger)]
|
|
:href (bidi/path-for routes/routes :ledger)}
|
|
"Ledger" ])])
|
|
[:div {:class "navbar-burger burger", :data-target "navMenu"}
|
|
[:span]
|
|
[:span]
|
|
[:span]]
|
|
(when-not is-initial-loading
|
|
[:div.navbar-end
|
|
[:div.navbar-item
|
|
[:a.button.is-primary.is-outlined
|
|
{:on-click (dispatch-event [::vendor-dialog/started {}])}
|
|
[:span.icon [:i.fa.fa-plus] ] [:span "Vendor"]]]
|
|
|
|
|
|
(when (> (count @clients) 1)
|
|
[navbar-drop-down {:header (str "Client: " (if @client (:name @client)
|
|
"All"))
|
|
:id ::select-client}
|
|
[:div
|
|
[:a {:class "navbar-item"
|
|
:on-click (fn []
|
|
(re-frame/dispatch [::events/swap-client nil]))} "All" ]
|
|
[:hr {:class "navbar-divider"}]
|
|
[bind-field
|
|
[:input.input.navbar-item {:placeholder "Client name"
|
|
:auto-focus true
|
|
:field [:value]
|
|
:on-key-up (fn [k]
|
|
(when (= 13 (.-which k))
|
|
(do
|
|
(re-frame/dispatch [::events/swap-client (first matching-clients)])
|
|
(re-frame/dispatch [::events/toggle-menu ::select-client])
|
|
(re-frame/dispatch [::client-search-changed [:value] nil])))
|
|
)
|
|
:event [::client-search-changed]
|
|
:subscription client-search}]]
|
|
(for [{:keys [name id] :as client} matching-clients]
|
|
^{:key id }
|
|
[:a {:class "navbar-item"
|
|
:on-click (fn []
|
|
(re-frame/dispatch [::events/swap-client client]))
|
|
} name])]])])]
|
|
(when-not is-initial-loading
|
|
[login-dropdown])]]))
|
|
|
|
|
|
(defn footer []
|
|
[:footer {:style {:padding "1em"}}
|
|
[:div {:class "content has-text-centered"}
|
|
[:p
|
|
[:strong "Integreat"] ]]])
|
|
|
|
(defn appearing-side-bar [{:keys [visible?]} & children ]
|
|
[appearing {:visible? visible? :enter-class "slide-in-right" :exit-class "slide-out-right" :timeout 500}
|
|
[:aside {:class "column is-4 aside menu" :style {:height "calc(100vh - 46px)" :overflow "auto"}}
|
|
(into [:div.sub-main {} ] children )]])
|
|
|
|
(defn side-bar-layout [{:keys [side-bar main ap bottom right-side-bar]}]
|
|
(let [ap @(re-frame/subscribe [::subs/active-page])
|
|
client @(re-frame/subscribe [::subs/client])
|
|
is-initial-loading @(re-frame/subscribe [::subs/is-initial-loading?])]
|
|
[:div
|
|
[modal/global-modal]
|
|
[navbar ap]
|
|
[:div {:class "columns has-shadow", :style {:margin-bottom "0px" :height "calc(100vh - 46px)" } :id "mail-app" }
|
|
[:aside {:class "column aside menu is-2 " }
|
|
[:div.main.left-nav
|
|
[:div side-bar
|
|
]]]
|
|
[:div {:class "column messages hero " :style { :overflow "auto" }, :id "message-feed"}
|
|
^{:key (str "active-page-" (:name client))}
|
|
[:div.inbox-messages
|
|
(when-let [error @(re-frame/subscribe [::subs/page-failure])]
|
|
[:div.notification.is-warning.animated.fadeInUp
|
|
error])
|
|
main]]
|
|
(when right-side-bar
|
|
right-side-bar)
|
|
]
|
|
#_[footer]
|
|
[:div
|
|
(when-not is-initial-loading
|
|
[vendor-dialog {}])
|
|
bottom]
|
|
[:div#dz-hidden]]))
|
|
|
|
|
|
(defn side-bar [{:keys [on-close]} children]
|
|
[:div [:a.delete.is-pulled-right {:on-click on-close}] [:div children]])
|
|
|
|
(defn loading-layout []
|
|
[side-bar-layout
|
|
{:main [:div.has-text-centered.hero.is-fullheight.is-vertically-centered.is-centered
|
|
[:div.hero-body
|
|
[:div.container
|
|
[:div.column.is-4.is-offset-4.has-text-centered
|
|
[:div.loader.is-loading.is-active.big.is-centered]]]]]}])
|
|
|