From 91d9ea346dc798b7c52a64cb287a0c8a3e18e19b Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Tue, 19 Feb 2019 22:03:26 -0800 Subject: [PATCH] dropdown fixed. --- resources/public/css/main.css | 4 + src/clj/auto_ap/yodlee/core.clj | 1 + src/cljs/auto_ap/subs.cljs | 5 + .../auto_ap/views/components/dropdown.cljs | 30 ++++++ .../views/components/invoice_table.cljs | 68 +++++++------- .../auto_ap/views/components/layouts.cljs | 88 ++++++++++-------- .../auto_ap/views/pages/unpaid_invoices.cljs | 92 +++++++++---------- 7 files changed, 164 insertions(+), 124 deletions(-) create mode 100644 src/cljs/auto_ap/views/components/dropdown.cljs diff --git a/resources/public/css/main.css b/resources/public/css/main.css index 98d8d44d..95cff5c7 100644 --- a/resources/public/css/main.css +++ b/resources/public/css/main.css @@ -294,6 +294,10 @@ nav.navbar .navbar-item.is-active { padding: 0 20px; color: #5D5D5D; } +.icon.padded { + margin-right: 0.25em !important; + +} .message-preview .avatar { display: inline-block; } diff --git a/src/clj/auto_ap/yodlee/core.clj b/src/clj/auto_ap/yodlee/core.clj index 6c147577..e7c04a43 100644 --- a/src/clj/auto_ap/yodlee/core.clj +++ b/src/clj/auto_ap/yodlee/core.clj @@ -187,6 +187,7 @@ :as :json}) :body))) + #_(defn get-users [] (let [cob-session (login-cobrand)] (-> "https://developer.api.yodlee.com/ysl/user" diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index d8de61b2..3e0d6512 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -34,6 +34,11 @@ (when (:user db) (:clients db)))) +(re-frame/reg-sub + ::menu-active? + (fn [db [_ id]] + (-> db :menu (get id) :active?))) + (re-frame/reg-sub ::menu (fn [db] diff --git a/src/cljs/auto_ap/views/components/dropdown.cljs b/src/cljs/auto_ap/views/components/dropdown.cljs new file mode 100644 index 00000000..50e94118 --- /dev/null +++ b/src/cljs/auto_ap/views/components/dropdown.cljs @@ -0,0 +1,30 @@ +(ns auto-ap.views.components.dropdown + (:require [reagent.core :as r] + [auto-ap.events :as events] + [re-frame.core :as re-frame] + [auto-ap.subs :as subs])) + +(defn drop-down-contents [{:keys [id]} children ] + (let [toggle-fn (fn [] (re-frame/dispatch [::events/toggle-menu id]))] + (r/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 drop-down [{:keys [ header id]} child] + (let [menu-active? (re-frame/subscribe [::subs/menu-active? id])] + (r/create-class + {:reagent-render (fn [{:keys [header id]} child] + (let [menu-active? @(re-frame/subscribe [::subs/menu-active? id])] + [:div.dropdown.is-right {:class (if menu-active? + "is-active" + "")} + [:div.dropdown-trigger header] + + [:div.dropdown-menu {:role "menu"} + [:div.dropdown-content + (when menu-active? + [drop-down-contents {:id id} + child])]]]))}))) + diff --git a/src/cljs/auto_ap/views/components/invoice_table.cljs b/src/cljs/auto_ap/views/components/invoice_table.cljs index af4d4b9f..32363317 100644 --- a/src/cljs/auto_ap/views/components/invoice_table.cljs +++ b/src/cljs/auto_ap/views/components/invoice_table.cljs @@ -4,6 +4,8 @@ [auto-ap.views.utils :refer [date->str dispatch-event delayed-dispatch]] [auto-ap.views.components.paginator :refer [paginator]] [auto-ap.views.components.sorter :refer [sorted-column]] + [auto-ap.views.components.dropdown :refer [drop-down drop-down-contents]] + [auto-ap.events :as events] [reagent.core :as reagent] [clojure.string :as str] [cljs-time.format :as format] @@ -167,21 +169,15 @@ [:div.buttons (when (seq expense-accounts) - - [:div.dropdown.is-right {:class (if (= id visible-expense-accounts) - "is-active" - "") - :on-blur (dispatch-event [::toggle-expense-accounts id]) - :on-focus (dispatch-event [::toggle-expense-accounts id])} - [:div.dropdown-trigger - [:a.button.badge {:data-badge (str (clojure.core/count expense-accounts)) - :aria-haspopup true - :tab-index "0" - - - } "Accounts"]] - [:div.dropdown-menu {:role "menu"} - [:div.dropdown-content + [drop-down {:id [::expense-accounts id ] + :header [:a.button.badge {:data-badge (str (clojure.core/count expense-accounts)) + :aria-haspopup true + :on-click (dispatch-event [::events/toggle-menu [::expense-accounts id]]) + :tab-index "0" + + } "Accounts"]} + [drop-down-contents + [:div (for [e expense-accounts] ^{:key (:id e)} [:span.dropdown-item (:name (:expense-account e)) " " (gstring/format "$%.2f" (:amount e) ) ]) @@ -189,7 +185,7 @@ [:hr.dropdown-divider] (when expense-event - [:a.dropdown-item.is-primary {:on-click (fn [x] (println "here"))#_(dispatch-event (conj expense-event i))} "Change"])]]]) + [:a.dropdown-item.is-primary {:on-click (dispatch-event (conj expense-event i))} "Change"])]]]) [:span {:style {:margin-left "1em"}}] (when (and on-edit-invoice (not= ":voided" (:status i))) [:a.button {:on-click (fn [] (on-edit-invoice i))} [:span.icon [:i.fa.fa-pencil]]]) @@ -198,30 +194,32 @@ (when (and on-unvoid-invoice (= ":voided" (:status i))) [:a {:on-click (fn [] (on-unvoid-invoice i))} [:span [:span.icon [:i.fa.fa-undo]]]]) (when (seq payments) + [drop-down {:id [::payments id] + :header [:button.button.badge {:data-badge (str (clojure.core/count payments)) + :aria-haspopup true + :tab-index "0" + :on-click (dispatch-event [::events/toggle-menu [::payments id]]) + } "Payments"]} + [:div + (for [payment payments] + (if (:s3-url (:payment payment)) + ^{:key (:id payment)} + [:a.dropdown-item {:href (:s3-url (:payment payment)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ")")] - [:div.dropdown.is-right {:class (if (= id visible-checks) + ^{:key (:id payment)} + [:span.dropdown-item [:span.icon {:class [(when (= :cleared (:status (:payment payment))) + "has-text-success")]} + [:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ") " + (when (= :cleared (:status (:payment payment))) + (str " - " (:post-date (:transaction (:payment payment))))))]))]] + + #_[:div.dropdown.is-right {:class (if (= id visible-checks) "is-active" "")} [:div.dropdown-trigger - [:a.button.badge {:data-badge (str (clojure.core/count payments)) - :aria-haspopup true - :tab-index "0" - - :on-blur (delayed-dispatch [::toggle-checks id]) - :on-focus (dispatch-event [::toggle-checks id]) - } "Checks"]] + ] [:div.dropdown-menu {:role "menu"} [:div.dropdown-content - (for [payment payments] - (if (:s3-url (:payment payment)) - ^{:key (:id payment)} - [:a.dropdown-item {:href (:s3-url (:payment payment)) :target "_new"} [:i.fa.fa-money-check] [:span.icon [:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ")")] - - ^{:key (:id payment)} - [:span.dropdown-item [:span.icon {:class [(when (= :cleared (:status (:payment payment))) - "has-text-success")]} - [:i.fa.fa-money]] (str " " (:check-number (:payment payment)) " (" (gstring/format "$%.2f" (:amount payment) ) ") " - (when (= :cleared (:status (:payment payment))) - (str " - " (:post-date (:transaction (:payment payment))))))]))]]])] + ]]])] ]]))]]])))) diff --git a/src/cljs/auto_ap/views/components/layouts.cljs b/src/cljs/auto_ap/views/components/layouts.cljs index 68c5f03d..175dd91f 100644 --- a/src/cljs/auto_ap/views/components/layouts.cljs +++ b/src/cljs/auto_ap/views/components/layouts.cljs @@ -12,39 +12,46 @@ [auto-ap.views.components.vendor-dialog :refer [vendor-dialog]])) (def css-transition-group (reagent/adapt-react-class js/ReactTransitionGroup.CSSTransition)) -(defn login-dropdown [] - (let [user (re-frame/subscribe [::subs/user]) - menu (re-frame/subscribe [::subs/menu])] - (if @user - [:div {:class (str "navbar-item has-dropdown " (when (get-in @menu [:account :active?]) "is-active"))} - [:a {:class "navbar-link login" :on-click (fn [e] (re-frame/dispatch [::events/toggle-menu :account]))} (:user/name @user)] - [:div {:class "navbar-dropdown"} - [:a {:class "navbar-item"} "My profile"] - (when (= "admin" (:user/role @user)) - [:a {:class "navbar-item" :href (bidi/path-for routes/routes :admin) - :on-click (fn [e] (re-frame/dispatch [::events/toggle-menu :account]))} "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"]))) -(defn navbar-drop-down-contents [children] - (let [toggle-fn (fn [] (re-frame/dispatch [::events/toggle-menu :client]))] +(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 [active? header]} & children] - (reagent/create-class - {:reagent-render (fn [{:keys [active? header]} & children] - [:div { :class (str "navbar-item has-dropdown " (when active? "is-active"))} - [:a {:class "navbar-link login" :on-click (fn [] (re-frame/dispatch [::events/toggle-menu :client]))} header] - [:div {:class "navbar-dropdown"} - (when active? - [navbar-drop-down-contents - [:div - children]])]])})) +(defn navbar-drop-down [{:keys [ header id]} 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"))} + [:a {:class "navbar-link login" :on-click (fn [e] + (.preventDefault e) + (.stopPropagation e) + (re-frame/dispatch [::events/toggle-menu id]) + true)} header] + [:div {:class "navbar-dropdown"} + (when menu-active? + [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"]))) + + (defn navbar [ap] (let [client (re-frame/subscribe [::subs/client]) clients (re-frame/subscribe [::subs/clients]) @@ -74,20 +81,21 @@ [:span]] [:div.navbar-end (when (> (count @clients) 1) - [navbar-drop-down {:active? (get-in @menu [:client :active?]) - :header (str "Client: " (if @client (:name @client) - "All"))} - [:a {:class "navbar-item" - :on-click (fn [] - (re-frame/dispatch [::events/swap-client nil])) - } "All"] - [:hr {:class "navbar-divider"}] - (for [{:keys [name id] :as client} @clients] - ^{:key id } - [:a {:class "navbar-item" - :on-click (fn [] - (re-frame/dispatch [::events/swap-client client])) - } name])])]] + [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"}] + (for [{:keys [name id] :as client} @clients] + ^{:key id } + [:a {:class "navbar-item" + :on-click (fn [] + (re-frame/dispatch [::events/swap-client client])) + } name])]])]] [login-dropdown]]])) (defn footer [] diff --git a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs index 117ea63a..9e7c07aa 100644 --- a/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs +++ b/src/cljs/auto_ap/views/pages/unpaid_invoices.cljs @@ -12,6 +12,7 @@ [auto-ap.forms :as forms] [auto-ap.views.components.layouts :refer [side-bar-layout appearing-side-bar]] [auto-ap.routes :as routes] + [auto-ap.views.components.dropdown :refer [drop-down drop-down-contents]] [auto-ap.views.components.expense-accounts-dialog :as expense-accounts-dialog] [auto-ap.views.components.vendor-dialog :refer [vendor-dialog]] [auto-ap.views.components.vendor-filter :refer [vendor-filter]] @@ -102,10 +103,7 @@ (dissoc x id) (assoc x id invoice)))))))) -(re-frame/reg-event-db - ::print-checks-clicked - (fn [db _] - (update-in db [::invoice-page :print-checks-shown?] #(not %) ))) + (re-frame/reg-event-db ::advanced-print-checks @@ -757,53 +755,49 @@ [:div.buttons [:button.button.is-success {:on-click (dispatch-event [::new-invoice-clicked])} "New Invoice"] (when current-client - [:div.dropdown.is-right {:class (if print-checks-shown? - "is-active" - "")} - [:div.dropdown-trigger - [:button.button.is-success {:aria-haspopup true - :on-click (dispatch-event [::print-checks-clicked ]) - :disabled (if (and (seq checked-invoices) - (->> checked-invoices - vals - (group-by #(get-in % [:vendor :id])) - (reduce-kv (fn [negative? _ invoices] - (or negative? (< (reduce + 0 (map (fn [x] (-> x :outstanding-balance js/parseFloat)) invoices) ) 0))) - false) - not)) - "" - "disabled") + [drop-down {:header [:button.button.is-success {:aria-haspopup true + :on-click (dispatch-event [::events/toggle-menu ::print-checks ]) + :disabled (if (and (seq checked-invoices) + (->> checked-invoices + vals + (group-by #(get-in % [:vendor :id])) + (reduce-kv (fn [negative? _ invoices] + (or negative? (< (reduce + 0 (map (fn [x] (-> x :outstanding-balance js/parseFloat)) invoices) ) 0))) + false) + not)) + "" + "disabled") - :class (if print-checks-loading? - "is-loading" - "")} - "Pay " - (when (> (count checked-invoices )) - (str - (count checked-invoices) - " invoices " - "(" (->> checked-invoices - vals - (map (comp js/parseFloat :outstanding-balance)) - (reduce + 0) - (gstring/format "$%.2f" )) - ")")) - [:span " "] - [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]]] - [:div.dropdown-menu {:role "menu"} - [:div.dropdown-content - (list - (for [{:keys [id number name type]} (->> (:bank-accounts current-client) (filter :visible) (sort-by :sort-order))] - (if (= :cash type) - ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"] - (list - ^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :check])} "Print checks from " name] - ^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :debit])} "Debit from " name]))) - ^{:key "advanced-divider"} [:hr.dropdown-divider] + :class (if print-checks-loading? + "is-loading" + "")} + "Pay " + (when (> (count checked-invoices )) + (str + (count checked-invoices) + " invoices " + "(" (->> checked-invoices + vals + (map (comp js/parseFloat :outstanding-balance)) + (reduce + 0) + (gstring/format "$%.2f" )) + ")")) + [:span " "] + [:span.icon.is-small [:i.fa.fa-angle-down {:aria-hidden "true"}]]] + :id ::print-checks} + [:div + (list + (for [{:keys [id number name type]} (->> (:bank-accounts current-client) (filter :visible) (sort-by :sort-order))] + (if (= :cash type) + ^{:key id} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :cash])} "With cash"] + (list + ^{:key (str id "-check")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :check])} "Print checks from " name] + ^{:key (str id "-debit")} [:a.dropdown-item {:on-click (dispatch-event [::print-checks id :debit])} "Debit from " name]))) + ^{:key "advanced-divider"} [:hr.dropdown-divider] - (when (= 1 (count checked-invoices)) - ^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."]) - ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]]])]] + (when (= 1 (count checked-invoices)) + ^{:key "handwritten"} [:a.dropdown-item {:on-click (dispatch-event [::handwrite-checks])} "Handwritten Check..."]) + ^{:key "advanced"} [:a.dropdown-item {:on-click (dispatch-event [::advanced-print-checks])} "Advanced..."])]])]] [:div.is-pulled-right (into [:div.tags {:style {:margin-right ".5 rem;"}}] (map (fn [[id invoice]] [:span.tag.is-medium (:invoice-number invoice) [:button.delete.is-small {:on-click (dispatch-event [::toggle-check id invoice])}]]) checked-invoices))]] ))