rough cut of new dashboard
This commit is contained in:
parent
45ec5f2b0e
commit
8b8765688d
|
@ -1,10 +1,10 @@
|
||||||
(ns commiteth.manage-payouts
|
(ns commiteth.manage-payouts
|
||||||
(:require [re-frame.core :as rf]
|
(:require [reagent.core :as r]
|
||||||
|
[re-frame.core :as rf]
|
||||||
[commiteth.routes :as routes]
|
[commiteth.routes :as routes]
|
||||||
|
[commiteth.model.bounty :as bnt]
|
||||||
[commiteth.common :as common :refer [human-time]]))
|
[commiteth.common :as common :refer [human-time]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn pr-url [{owner :repo_owner
|
(defn pr-url [{owner :repo_owner
|
||||||
pr-number :pr_number
|
pr-number :pr_number
|
||||||
repo :repo_name}]
|
repo :repo_name}]
|
||||||
|
@ -12,17 +12,34 @@
|
||||||
|
|
||||||
(defn balance-badge
|
(defn balance-badge
|
||||||
[tla balance]
|
[tla balance]
|
||||||
|
{:pre [(keyword? tla)]}
|
||||||
(let [color (fn balance-badge-color [tla]
|
(let [color (fn balance-badge-color [tla]
|
||||||
(get {"ETH" "#57a7ed"} tla "#4360df"))
|
(get {"ETH" "#57a7ed"} tla "#4360df"))
|
||||||
tla (if (keyword? tla)
|
tla (name tla)]
|
||||||
(subs (str tla) 1)
|
[:div.dib.ph2.pv1.relative
|
||||||
tla)]
|
|
||||||
[:div.ph2.pv1.relative
|
|
||||||
{:style {:color (color tla)}}
|
{:style {:color (color tla)}}
|
||||||
[:div.absolute.top-0.left-0.right-0.bottom-0.o-10.br2
|
[:div.absolute.top-0.left-0.right-0.bottom-0.o-10.br2
|
||||||
{:style {:background-color (color tla)}}]
|
{:style {:background-color (color tla)}}]
|
||||||
[:span.pg-med (str tla " " balance)]]))
|
[:span.pg-med (str tla " " balance)]]))
|
||||||
|
|
||||||
|
(defn usd-value-label [value-usd]
|
||||||
|
[:span
|
||||||
|
[:span.usd-value-label "Value "]
|
||||||
|
[:span.usd-balance-label (str "$" value-usd)]])
|
||||||
|
|
||||||
|
(defn token-balances [crypto-balances]
|
||||||
|
[:span ; TODO consider non DOM el react wrapping
|
||||||
|
(for [[tla balance] crypto-balances]
|
||||||
|
^{:key tla}
|
||||||
|
[:div.dib.mr2
|
||||||
|
[balance-badge tla balance]])])
|
||||||
|
|
||||||
|
(defn bounty-balance [{:keys [value-usd] :as bounty}]
|
||||||
|
[:div
|
||||||
|
[token-balances (bnt/crypto-balances bounty)]
|
||||||
|
[:div.dib.mr2.pv1
|
||||||
|
[usd-value-label value-usd]]])
|
||||||
|
|
||||||
(defn bounty-card [{owner :repo-owner
|
(defn bounty-card [{owner :repo-owner
|
||||||
repo-name :repo-name
|
repo-name :repo-name
|
||||||
issue-title :issue-title
|
issue-title :issue-title
|
||||||
|
@ -31,78 +48,76 @@
|
||||||
tokens :tokens
|
tokens :tokens
|
||||||
balance-eth :balance-eth
|
balance-eth :balance-eth
|
||||||
value-usd :value-usd
|
value-usd :value-usd
|
||||||
:as bounty}]
|
:as bounty}
|
||||||
|
{:keys [style] :as opts}]
|
||||||
[:div
|
[:div
|
||||||
[:a {:href (common/issue-url owner repo-name issue-number)}
|
[:a {:href (common/issue-url owner repo-name issue-number)}
|
||||||
[:span.db.f4.muted-blue.hover-black issue-title]
|
[:div.cf
|
||||||
[:div.mt2
|
[:div.fl.w-80
|
||||||
[:span.f5.gray.pg-book (str owner "/" repo-name " #" issue-number) " — " (common/human-time updated)]]
|
[:span.db.f4.muted-blue.hover-black issue-title]
|
||||||
[:div.cf.mt2
|
[:div.mt2
|
||||||
[:div.fl.mr2
|
[:span.f5.gray.pg-book (str owner "/" repo-name " #" issue-number)]]]
|
||||||
[balance-badge "ETH" balance-eth]]
|
[:div.fl.w-20.tr
|
||||||
(for [[tla balance] tokens]
|
[:span.f5.gray.pg-book
|
||||||
^{:key tla}
|
{:on-click #(do (.preventDefault %) (prn (dissoc bounty :claims)))}
|
||||||
[:div.fl.mr2
|
(common/human-time updated)]]]]])
|
||||||
[balance-badge tla balance]])
|
|
||||||
[:div.fl.mr2.pv1
|
|
||||||
[:span.usd-value-label "Value "]
|
|
||||||
[:span.usd-balance-label (str "$" value-usd)]]]
|
|
||||||
|
|
||||||
#_[:code (pr-str bounty)]
|
(defn confirm-button [bounty claim]
|
||||||
|
(let [paid? (bnt/paid? claim)
|
||||||
|
merged? (bnt/merged? claim)]
|
||||||
|
(when (and merged? (not paid?))
|
||||||
|
[:button.f5.outline-0.bg-sob-blue.white.pv2.ph3.pg-med.br2.bn.pointer
|
||||||
|
(merge (if (and merged? (not paid?))
|
||||||
|
{}
|
||||||
|
{:disabled true})
|
||||||
|
{:on-click #(rf/dispatch [:confirm-payout claim])}
|
||||||
|
(when (and (or (bnt/confirming? bounty)
|
||||||
|
(bnt/bot-confirm-unmined? bounty))
|
||||||
|
merged?)
|
||||||
|
{:class "busy loading" :disabled true}))
|
||||||
|
(if paid?
|
||||||
|
"Signed off"
|
||||||
|
"Confirm")])))
|
||||||
|
|
||||||
|
(defn confirm-row [bounty claim]
|
||||||
|
[:div.cf
|
||||||
|
[:div.dt.fr
|
||||||
|
[:div.dtc.v-mid.pr3
|
||||||
|
[bounty-balance bounty]]
|
||||||
|
[:div.dtc.v-mid
|
||||||
|
[confirm-button bounty claim]]]])
|
||||||
|
|
||||||
#_(when (> claim-count 0)
|
(defn claim-card [bounty claim {:keys [render-view-claim-button?] :as opts}]
|
||||||
[:span.open-claims-label (str claim-count " open claim"
|
(let [{user-name :user_name
|
||||||
(when (> claim-count 1) "s"))])]])
|
|
||||||
|
|
||||||
(defn claim-card [bounty claim]
|
|
||||||
#_(prn claim)
|
|
||||||
(let [{pr-state :pr_state
|
|
||||||
user-name :user_name
|
|
||||||
user-login :user_login
|
user-login :user_login
|
||||||
avatar-url :user_avatar_url
|
avatar-url :user_avatar_url} claim
|
||||||
issue-id :issue_id
|
winner-login (:winner_login bounty)]
|
||||||
issue-title :issue_title} claim
|
|
||||||
merged? (= 1 (:pr_state claim))
|
|
||||||
paid? (not-empty (:payout_hash claim))
|
|
||||||
winner-login (:winner_login bounty)
|
|
||||||
bot-confirm-unmined? (empty? (:confirm_hash bounty))
|
|
||||||
confirming? (:confirming? bounty)
|
|
||||||
updated (:updated bounty)]
|
|
||||||
[:div.pa2
|
[:div.pa2
|
||||||
[:div.dt
|
[:div.flex.items-center
|
||||||
{:class (when (and paid? (not (= user-login winner-login)))
|
{:class (when (and (bnt/paid? claim) (not (= user-login winner-login)))
|
||||||
"o-50")}
|
"o-50")}
|
||||||
[:div.dtc.v-top
|
[:div
|
||||||
[:img.br-100.w3 {:src avatar-url}]]
|
[:img.br-100.w3 {:src avatar-url}]]
|
||||||
[:div.dtc.v-top.pl3
|
[:div.pl3.flex-auto
|
||||||
[:div
|
[:div
|
||||||
[:span.f4.muted-blue (or user-name user-login) " · "
|
[:span.f4.muted-blue
|
||||||
(if paid?
|
(or user-name user-login) " "
|
||||||
|
[:span.f5.o-60 (when user-name (str "@" user-login "") )]
|
||||||
|
(if (bnt/paid? claim)
|
||||||
(if (= user-login winner-login)
|
(if (= user-login winner-login)
|
||||||
[:span "Received payout"]
|
[:span "Received payout"]
|
||||||
[:span "No payout"])
|
[:span "No payout"]))]
|
||||||
(if merged? "Merged" "Open"))]
|
|
||||||
;; [:span.f5 (human-time updated)]
|
|
||||||
[:div "Submitted a claim via "
|
[:div "Submitted a claim via "
|
||||||
[:a {:href (pr-url claim)}
|
[:a {:href (pr-url claim)}
|
||||||
(str (:repo_owner claim) "/" (:repo_name claim) " PR #" (:pr_number claim))]]
|
(str (:repo_owner claim) "/" (:repo_name claim) " PR #" (:pr_number claim))]]]]
|
||||||
(when (and merged? (not paid?))
|
(when render-view-claim-button?
|
||||||
[:button.mt2.f5.outline-0.bg-sob-blue.white.pv2.ph3.pg-med.br2.bn
|
[:div.dtc.v-mid
|
||||||
(merge (if (and merged? (not paid?))
|
[:div.w-100
|
||||||
{}
|
[:a.f5.outline-0.bg-sob-blue.white.pv2.ph3.pg-med.br2.bn.pointer.hover-white
|
||||||
{:disabled true})
|
{:href (pr-url claim)}
|
||||||
{:on-click #(rf/dispatch [:confirm-payout claim])}
|
"View Claim"]]])]]))
|
||||||
(when (and (or confirming? bot-confirm-unmined?)
|
|
||||||
merged?)
|
|
||||||
{:class "busy loading" :disabled true}))
|
|
||||||
(if paid?
|
|
||||||
"Signed off"
|
|
||||||
"Confirm")])]]]]))
|
|
||||||
|
|
||||||
|
#_(defn claim-list [bounties]
|
||||||
(defn claim-list [bounties]
|
|
||||||
;; TODO: exclude bounties with no claims
|
;; TODO: exclude bounties with no claims
|
||||||
(if (empty? bounties)
|
(if (empty? bounties)
|
||||||
[:div.ui.text "No items"]
|
[:div.ui.text "No items"]
|
||||||
|
@ -119,17 +134,51 @@
|
||||||
[claim-card bounty claim])
|
[claim-card bounty claim])
|
||||||
[:div.f4.muted-blue "No claims yet."])]]))))
|
[:div.f4.muted-blue "No claims yet."])]]))))
|
||||||
|
|
||||||
|
(defn to-confirm-list [bounties]
|
||||||
|
(if (empty? bounties)
|
||||||
|
[:div.ui.text "No items"]
|
||||||
|
(into [:div]
|
||||||
|
(for [bounty bounties
|
||||||
|
:let [winning-claim (first (:claims bounty))]] ; TODO identify winning claim
|
||||||
|
^{:key (:issue_id bounty)}
|
||||||
|
[:div.mb2
|
||||||
|
[:div.pa3.bg-white.bb.b--light-gray
|
||||||
|
[bounty-card bounty]]
|
||||||
|
[:div.pa3.bg-white
|
||||||
|
[claim-card bounty winning-claim]]
|
||||||
|
[:div.pa3.bg-near-white
|
||||||
|
[confirm-row bounty winning-claim]]]))))
|
||||||
|
|
||||||
|
(defn to-merge-list [bounties]
|
||||||
|
(if (empty? bounties)
|
||||||
|
[:div.ui.text "No items"]
|
||||||
|
(into [:div]
|
||||||
|
(for [bounty bounties
|
||||||
|
:let [claims (:claims bounty)]] ; TODO identify winning claim
|
||||||
|
^{:key (:issue_id bounty)}
|
||||||
|
[:div.mb2
|
||||||
|
[:div.pa3.bg-white.bb.b--light-gray
|
||||||
|
[bounty-card bounty]
|
||||||
|
[:div.mt3 [bounty-balance bounty]]]
|
||||||
|
[:div.pa3.bg-white
|
||||||
|
(for [claim (:claims bounty)]
|
||||||
|
^{:key (:pr_id claim)}
|
||||||
|
[claim-card bounty claim {:render-view-claim-button? true}])]]))))
|
||||||
|
|
||||||
(defn bounty-stats [{:keys [paid unpaid]}]
|
(defn bounty-stats [{:keys [paid unpaid]}]
|
||||||
[:div.cf
|
[:div.cf
|
||||||
[:div.fl-ns.w-50-ns.tc.pv4
|
[:div.fl-ns.w-33-ns.tc.pv4
|
||||||
[:div.ttu.tracked "Open"]
|
#_[:div.ttu.tracked "Paid"]
|
||||||
[:div.f2.pa2 (common/usd-string (:combined-usd-value unpaid))]
|
[:div.f3.pa2 (common/usd-string (:combined-usd-value paid))]
|
||||||
[:div (:count unpaid) " bounties"]]
|
[:div.ph4 "Invested so far"]]
|
||||||
|
|
||||||
[:div.fl-ns.w-50-ns.tc.pv4
|
[:div.fl-ns.w-33-ns.tc.pv4
|
||||||
[:div.ttu.tracked "Paid"]
|
[:div.f3.pa2 (:count paid)]
|
||||||
[:div.f2.pa2 (common/usd-string (:combined-usd-value paid))]
|
[:div.ph4 "Bounties solved by contributors"]]
|
||||||
[:div (:count paid) " bounties"]]])
|
|
||||||
|
[:div.fl-ns.w-33-ns.tc.pv4
|
||||||
|
[:div.f3.pa2 (:count unpaid)]
|
||||||
|
[:div.ph4 "Open bounties in total"]]])
|
||||||
|
|
||||||
(def state-mapping
|
(def state-mapping
|
||||||
{:opened :open
|
{:opened :open
|
||||||
|
@ -141,14 +190,55 @@
|
||||||
:pending-maintainer-confirmation :pending-maintainer-confirmation
|
:pending-maintainer-confirmation :pending-maintainer-confirmation
|
||||||
:paid :paid})
|
:paid :paid})
|
||||||
|
|
||||||
|
(defn bounty-title-link [bounty]
|
||||||
|
[:a {:href (common/issue-url (:repo-owner bounty) (:repo-name bounty) (:issue-number bounty))}
|
||||||
|
[:div.w-100.overflow-hidden
|
||||||
|
[:span.db.f5.pg-med.muted-blue.hover-black (:issue-title bounty)]
|
||||||
|
[:span.f6.gray.pg-book
|
||||||
|
{:on-click #(do (.preventDefault %) (prn (dissoc bounty :claims)))}
|
||||||
|
(common/human-time (:updated bounty))]]])
|
||||||
|
|
||||||
|
(defn unclaimed-bounty [bounty]
|
||||||
|
[:div.w-third-ns.fl.pa2
|
||||||
|
[:div.bg-white.br2.br--top.pa2.h4
|
||||||
|
[bounty-title-link bounty]]
|
||||||
|
[:div.bg-white.pa2.f7.br2.br--bottom
|
||||||
|
[bounty-balance bounty]]])
|
||||||
|
|
||||||
|
(defn paid-bounty [bounty]
|
||||||
|
[:div.w-third-ns.fl.pa2
|
||||||
|
[:div.bg-white.br2.br--top.pa2.h4
|
||||||
|
[bounty-title-link bounty]]
|
||||||
|
[:div.bg-white.ph2.f6
|
||||||
|
"Paid out to @" (:winner_login bounty)]
|
||||||
|
[:div.bg-white.pa2.f7.br2.br--bottom
|
||||||
|
[bounty-balance bounty]]])
|
||||||
|
|
||||||
|
(defn expandable-bounty-list [bounty-component bounties]
|
||||||
|
(let [expanded? (r/atom false)]
|
||||||
|
(fn expandable-bounty-list-render [bounty-component bounties]
|
||||||
|
[:div
|
||||||
|
[:div.cf.nl2.nr2
|
||||||
|
(for [bounty (cond->> bounties
|
||||||
|
(not @expanded?) (take 3))]
|
||||||
|
[bounty-component bounty])]
|
||||||
|
[:div.tr
|
||||||
|
[:span.f5.sob-blue.pointer
|
||||||
|
{:role "button"
|
||||||
|
:on-click #(reset! expanded? (not @expanded?))}
|
||||||
|
(if @expanded?
|
||||||
|
"Collapse ↑"
|
||||||
|
"See all ↓")]]])))
|
||||||
|
|
||||||
(defn manage-payouts-page []
|
(defn manage-payouts-page []
|
||||||
(let [owner-bounties (rf/subscribe [:owner-bounties])
|
(let [page (rf/subscribe [:page]) ; TODO fix this to subscribe to route subscription
|
||||||
|
owner-bounties (rf/subscribe [:owner-bounties])
|
||||||
bounty-stats-data (rf/subscribe [:owner-bounties-stats])
|
bounty-stats-data (rf/subscribe [:owner-bounties-stats])
|
||||||
owner-bounties-loading? (rf/subscribe [:get-in [:owner-bounties-loading?]])]
|
owner-bounties-loading? (rf/subscribe [:get-in [:owner-bounties-loading?]])]
|
||||||
(fn []
|
(fn []
|
||||||
(if @owner-bounties-loading?
|
(if @owner-bounties-loading?
|
||||||
[:container
|
[:div.pa5
|
||||||
[:div.ui.active.inverted.dimmer
|
[:div.ui.active.inverted.dimmer.bg-none
|
||||||
[:div.ui.text.loader "Loading"]]]
|
[:div.ui.text.loader "Loading"]]]
|
||||||
(let [bounties (vals @owner-bounties)
|
(let [bounties (vals @owner-bounties)
|
||||||
grouped (group-by (comp state-mapping :state) bounties)]
|
grouped (group-by (comp state-mapping :state) bounties)]
|
||||||
|
@ -158,12 +248,51 @@
|
||||||
[:i.warning.icon]
|
[:i.warning.icon]
|
||||||
"To sign off claims, please view Status Open Bounty in Status, Mist or Metamask"])
|
"To sign off claims, please view Status Open Bounty in Status, Mist or Metamask"])
|
||||||
[bounty-stats @bounty-stats-data]
|
[bounty-stats @bounty-stats-data]
|
||||||
[:div.cf
|
[:div.cf.ba.b--white.mb2
|
||||||
|
[:div.f4.fl.w-50-ns.pa4.tc
|
||||||
|
{:role "button"
|
||||||
|
:class (if (= @page :issuer-dashboard/to-confirm) "bg-white" "bg-near-white pointer")
|
||||||
|
:on-click #(routes/nav! :issuer-dashboard/to-confirm)}
|
||||||
|
"To confirm payment (" (count (get grouped :pending-maintainer-confirmation)) ")"]
|
||||||
|
[:div.f4.fl.w-50-ns.pa4.tc.pointer.bl.b--white
|
||||||
|
{:role "button"
|
||||||
|
:class (if (= @page :issuer-dashboard/to-merge) "bg-white" "bg-near-white pointer")
|
||||||
|
:on-click #(routes/nav! :issuer-dashboard/to-merge)}
|
||||||
|
"To merge (" (count (get grouped :claimed)) ")"]]
|
||||||
|
[:div
|
||||||
|
(case @page
|
||||||
|
:issuer-dashboard/to-confirm (to-confirm-list (get grouped :pending-maintainer-confirmation))
|
||||||
|
:issuer-dashboard/to-merge (to-merge-list (get grouped :claimed))
|
||||||
|
(cond
|
||||||
|
(seq (get grouped :pending-maintainer-confirmation))
|
||||||
|
(routes/nav! :issuer-dashboard/to-confirm)
|
||||||
|
|
||||||
|
(seq (get grouped :claimed))
|
||||||
|
(routes/nav! :issuer-dashboard/to-merge)
|
||||||
|
|
||||||
|
:else (routes/nav! :issuer-dashboard/to-confirm)))]
|
||||||
|
[:div.mt4
|
||||||
|
[:h4.f3.sob-muted-blue "Bounties not claimed yet (" (count (get grouped :funded)) ")"]
|
||||||
|
[expandable-bounty-list
|
||||||
|
unclaimed-bounty
|
||||||
|
(reverse (sort-by :updated (get grouped :funded)))]]
|
||||||
|
|
||||||
|
[:div.mt4
|
||||||
|
[:h4.f3.sob-muted-blue "Paid out bounties (" (count (get grouped :paid)) ")"]
|
||||||
|
[expandable-bounty-list paid-bounty (get grouped :paid)]]
|
||||||
|
|
||||||
|
|
||||||
|
#_[:div.mt4
|
||||||
|
[:h4.f3 "Revoked bounties (" (count (get grouped :paid)) ")"]
|
||||||
|
[expandable-bounty-list unclaimed-bounty (get grouped :paid)]]
|
||||||
|
|
||||||
|
[:div.mb5]
|
||||||
|
#_[:div.cf
|
||||||
[:button.pa2.tl.bn.bg-white.muted-blue
|
[:button.pa2.tl.bn.bg-white.muted-blue
|
||||||
{:on-click #(routes/nav! :issuer-dashboard/paid)}
|
{:on-click #(routes/nav! :issuer-dashboard/paid)}
|
||||||
[:span.f4 "Paid"] [:br]
|
[:span.f4 "Paid"] [:br]
|
||||||
(count (get grouped :paid)) " bounties"]]
|
(count (get grouped :paid)) " bounties"]]
|
||||||
(for [[k v] grouped]
|
#_(for [[k v] grouped]
|
||||||
[:div
|
[:div
|
||||||
{:key (name k)}
|
{:key (name k)}
|
||||||
[:h3 (name k) " — " (count v)]
|
[:h3 (name k) " — " (count v)]
|
||||||
|
|
Loading…
Reference in New Issue