diff --git a/env/test/resources/config.edn b/env/test/resources/config.edn index 6e65a3d..4c40fb3 100644 --- a/env/test/resources/config.edn +++ b/env/test/resources/config.edn @@ -1,4 +1,4 @@ { :test true - :jdbc-database-url "jdbc:postgresql://localhost/commiteth_test?user=commiteth&password=commiteth" + :jdbc-database-url "jdbc:postgresql://localhost/commiteth?user=commiteth&password=commiteth" } diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 5d31eaf..48a7b9b 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -9,6 +9,7 @@ [commiteth.db.repositories :as repositories] [commiteth.db.bounties :as bounties-db] [commiteth.bounties :as bounties] + [commiteth.eth.core :as eth] [commiteth.github.core :as github] [clojure.tools.logging :as log] [commiteth.eth.core :as eth] @@ -97,11 +98,9 @@ :description "commitETH API"}}}} (context "/api" [] - (context "/bounties" [] (GET "/all" [] (ok (bounties-db/list-all-bounties)))) - (context "/user" [] (GET "/" [] :auth-rules authenticated? @@ -111,10 +110,15 @@ :auth-rules authenticated? :body-params [user-id :- Long, address :- String] :summary "Update user address" - (let [result (users/update-user-address user-id address)] - (if (= 1 result) - (ok) - (internal-server-error)))) + (if-not (eth/valid-address? address) + {:status 400 + :body "Invalid Ethereum address"} + (let [result (users/update-user-address + user-id + address)] + (if (= 1 result) + (ok) + (internal-server-error))))) (GET "/repositories" [] :auth-rules authenticated? :current-user user @@ -138,8 +142,7 @@ :auth-rules authenticated? :current-user user (ok (map #(conj % (let [balance (:balance %)] - {:balance-eth (eth/hex->eth balance 6) - :balance-wei (eth/hex->big-integer balance)})) + {:balance-eth (eth/hex->eth balance 6)})) (bounties-db/list-owner-bounties (:id user))))) (POST "/repository/toggle" {:keys [params]} :auth-rules authenticated? diff --git a/src/cljs/commiteth/common.cljs b/src/cljs/commiteth/common.cljs index 39c6d1a..08d5792 100644 --- a/src/cljs/commiteth/common.cljs +++ b/src/cljs/commiteth/common.cljs @@ -9,12 +9,13 @@ :value @val-ratom :on-change #(reset! val-ratom (-> % .-target .-value))})])) -(defn dropdown [title val-ratom items] +(defn dropdown [props title val-ratom items] (fn [] (if (= 1 (count items)) (reset! val-ratom (first items))) [:select.ui.basic.selection.dropdown - {:on-change #(reset! val-ratom (-> % .-target .-value))} + (merge props {:on-change + #(reset! val-ratom (-> % .-target .-value))}) (doall (for [item items] ^{:key item} [:option {:value item} diff --git a/src/cljs/commiteth/core.cljs b/src/cljs/commiteth/core.cljs index 7407dc2..5afffc6 100644 --- a/src/cljs/commiteth/core.cljs +++ b/src/cljs/commiteth/core.cljs @@ -22,6 +22,16 @@ [re-frisk.core :refer [enable-re-frisk!]]) (:import goog.History)) + +(defn flash-message-pane [] + (let [flash-message (rf/subscribe [:flash-message])] + (fn [] + (when-let [[type message] @flash-message] + [:div.flash-message {:class (name type)} + [:i.close.icon {:on-click #(rf/dispatch [:clear-flash-message])}] + [:p message]])) + )) + (def user-dropdown-open? (r/atom false)) (defn user-dropdown [user items] @@ -38,12 +48,13 @@ [:div.item [:span.dropdown.icon]] (into menu - (for [[target caption] items] + (for [[target caption props] items] ^{:key target} [:div.item [:a - (if (keyword? target) - {:on-click #(rf/dispatch [target])} - {:href target}) + (merge props + (if (keyword? target) + {:on-click #(rf/dispatch [target])} + {:href target})) caption]]))])) @@ -53,8 +64,8 @@ (if @user [:div.ui.text.menu.user-component [:div.item - [user-dropdown @user [[:update-address "Update address"] - ["/logout" "Sign out"]]]]] + [user-dropdown @user [[:update-address "Update address" {}] + ["/logout" "Sign out" {:class "logout-link"}]]]]] [:a.ui.button.small {:href js/authorizeUrl} "Sign in"])))) (defn tabs [] @@ -74,7 +85,8 @@ (defn page-header [] - (let [user (rf/subscribe [:user])] + (let [user (rf/subscribe [:user]) + flash-message (rf/subscribe [:flash-message])] (fn [] [:div.vertical.segment.commiteth-header [:div.ui.grid.container @@ -82,7 +94,9 @@ [:div.ui.image [:img.left.aligned {:src "/img/logo.svg"}]]] [:div.four.wide.column - [user-component @user]] + (if @flash-message + [flash-message-pane] + [user-component @user])] (when-not @user [:div.ui.text.content [:div.ui.divider.hidden] @@ -117,7 +131,6 @@ (fn [] [:div.ui.pusher [page-header] - ;; [error-pane] [:div.ui.vertical.segment [:div.ui.container [:div.ui.grid.stackable diff --git a/src/cljs/commiteth/handlers.cljs b/src/cljs/commiteth/handlers.cljs index c5ceeda..e10d89d 100644 --- a/src/cljs/commiteth/handlers.cljs +++ b/src/cljs/commiteth/handlers.cljs @@ -25,14 +25,14 @@ (assoc-in db path value))) (reg-event-db - :set-error - (fn [db [_ text]] - (assoc db :error text))) + :set-flash-message + (fn [db [_ type text]] + (assoc db :flash-message [type text]))) (reg-event-db - :clear-error + :clear-flash-message (fn [db _] - (dissoc db :error))) + (dissoc db :flash-message))) (reg-event-db :set-active-page @@ -181,9 +181,21 @@ :save-user-address (fn [{:keys [db]} [_ user-id address]] (prn "save-user-address" user-id address) - {:db db + {:db (assoc db :updating-address true) :http {:method POST :url "/api/user/address" - :on-success #(println "on-success" %) - :on-error #(println "on-error" %) + :on-success #(do + (dispatch [:assoc-in [:user [:address] address]]) + (dispatch [:set-flash-message + :success + "Address saved"])) + :on-error #(dispatch [:set-flash-message + :error + (:response %)]) + :finally #(dispatch [:clear-updating-address]) :params {:user-id user-id :address address}}})) + +(reg-event-db + :clear-updating-address + (fn [db _] + (dissoc db :updating-address))) diff --git a/src/cljs/commiteth/subscriptions.cljs b/src/cljs/commiteth/subscriptions.cljs index 53f006d..eb10d9b 100644 --- a/src/cljs/commiteth/subscriptions.cljs +++ b/src/cljs/commiteth/subscriptions.cljs @@ -22,9 +22,9 @@ (:repos db))) (reg-sub - :error + :flash-message (fn [db _] - (:error db))) + (:flash-message db))) (reg-sub :all-bounties diff --git a/src/cljs/commiteth/update_address.cljs b/src/cljs/commiteth/update_address.cljs index 5b4b100..a6183ad 100644 --- a/src/cljs/commiteth/update_address.cljs +++ b/src/cljs/commiteth/update_address.cljs @@ -7,6 +7,7 @@ (defn update-address-page [] (let [user (rf/subscribe [:user]) + updating-address (rf/subscribe [:get-in [:updating-address]]) web3 (.-web3 js/window) web3-accounts (into [] (when-not (nil? web3) (-> web3 .-eth @@ -21,7 +22,7 @@ [:p "Placeholder text for explaining what an Ethereum address is."] [:div.field (if-not (empty? web3-accounts) - [dropdown "Select address" + [dropdown {:class "address-input"} "Select address" address (into [] (for [acc web3-accounts] @@ -29,9 +30,13 @@ [:div.ui.input.address-input [input address {:placeholder "0x0000000000000000000000000000000000000000" :auto-complete "off" + :auto-correct "off" + :spell-check "false" :max-length 42}]])] - [:button.ui.button {:on-click - #(rf/dispatch [:save-user-address - (:id @user) - @address])} + [:button.ui.button (merge {:on-click + #(rf/dispatch [:save-user-address + (:id @user) + @address])} + (when @updating-address + {:class "busy loading"})) "Update"]]]))) diff --git a/src/less/style.less b/src/less/style.less index 670d4f5..e33d866 100644 --- a/src/less/style.less +++ b/src/less/style.less @@ -13,9 +13,16 @@ .ui.button { + color: #2f3f44; background-color: #b0f1ee; white-space: nowrap; padding: 0.9em 1.2em 0.9em; + &:hover { + background-color: #bdf8f5; + } + &:active,&:focus { + background-color: #97ebe7; + } } .ui.small.button { font-size: 15px!important; @@ -87,7 +94,6 @@ span.dropdown.icon { .ui.dropdown .item { color: #fff!important; opacity: 0.98; - } .ui.menu .ui.dropdown .menu>.item:hover, .ui.menu .ui.dropdown .menu>.selected.item { @@ -95,30 +101,33 @@ span.dropdown.icon { } .ui.input.address-input { + color: #e7e7e7!important; font-size: .8em; width: 360px!important; } - +.ui.selection.dropdown.address-input option { + color: #e7e7e7; + background-color: yellow!important; +} .ui.menu.transition.visible { font-family: 'postgrotesk'; font-size: 1em; border-radius: 8px; border: none; padding: .5em; - .item { - :hover { - color: #e96868; - } - a { - &:hover { - color: #e96868; - } - color: #474951; + .item>a { + &:hover { + color:#1bb5c1; } + color: #474951; } } +.logout-link { + color: #e96868!important; +} + .ui.attached.tabular { background-color: #2f3f44; border-bottom: none; @@ -189,9 +198,6 @@ span.dropdown.icon { padding: 0.8em 1em 1.1em!important; flex-direction: row!important; - // .ui.mini.circular.image { - // margin: 0; - // } } .ui.cards>.card { @@ -229,6 +235,28 @@ span.dropdown.icon { color: #a8aab1; } +.flash-message { + &.success { + background-color: #61deb0; + } + &.error { + background-color: #e96868; + } + + color: #fff; + border-radius: 8px; + z-index: 100; + padding: 1.4em 1em 1.4em; + i { + position: absolute; + margin: 0; + right: 1.5em; + top: 1.5em; + cursor: pointer; + } +} + + .ui { font-family: 'postgrotesk'!important; } diff --git a/test/clj/commiteth/test/db/core.clj b/test/clj/commiteth/test/db/core.clj index 4775e95..a356d1b 100644 --- a/test/clj/commiteth/test/db/core.clj +++ b/test/clj/commiteth/test/db/core.clj @@ -24,6 +24,7 @@ {:id 1 :login "torvalds" :name "Linus Torvalds" + :avatar_url "" :email nil :token "not null" :address "address" @@ -32,6 +33,7 @@ :login "torvalds" :name "Linus Torvalds" :email nil + :avatar_url "" :token "not null" :address "address" :created nil}