[FIX #156] Add pagination to Bounties and Activities views

This commit is contained in:
Vitaliy Vlasov 2018-01-12 19:47:17 +02:00
parent cd3bbbdda0
commit fea0db845a
8 changed files with 241 additions and 18 deletions

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="#57A7ED" fill-rule="evenodd" d="M7.223 11.293l7.068-7.067a.999.999 0 1 1 1.414 1.414l-6.377 6.377 6.377 6.376a.999.999 0 1 1-1.414 1.415L7.223 12.74a1.001 1.001 0 0 1-.288-.827 1 1 0 0 1 .288-.62z"/>
</svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@ -2,6 +2,7 @@
(:require [re-frame.core :as rf]
[reagent.core :as r]
[commiteth.common :refer [moment-timestamp
display-data-page
issue-url]]))
@ -56,21 +57,19 @@
(defn activity-list [activity-items]
(defn activity-list [activity-page-data]
[:div.ui.container.activity-container
(if (empty? activity-items)
(if (empty? (:items activity-page-data))
[:div.view-no-data-container
[:p "No recent activity yet"]]
(into [:div.ui.items]
(for [item activity-items]
^{:key item} [activity-item item])))] )
(display-data-page activity-page-data activity-item :set-activity-page-number))])
(defn activity-page []
(let [activity-items (rf/subscribe [:activity-feed])
(let [activity-page-data (rf/subscribe [:activities-page])
activity-feed-loading? (rf/subscribe [:get-in [:activity-feed-loading?]])]
(fn []
(if @activity-feed-loading?
[:div.view-loading-container
[:div.ui.active.inverted.dimmer
[:div.ui.text.loader.view-loading-label "Loading"]]]
[activity-list @activity-items]))))
[activity-list @activity-page-data]))))

View File

@ -1,6 +1,7 @@
(ns commiteth.bounties
(:require [re-frame.core :as rf]
[commiteth.common :refer [moment-timestamp
display-data-page
issue-url]]))
@ -42,23 +43,22 @@
[:div.ui.tiny.circular.image
[:img {:src avatar-url}]]]]))
(defn bounties-list [open-bounties]
(defn bounties-list [{:keys [items item-count total-count] :as bounty-page-data}]
[:div.ui.container.open-bounties-container
[:div.open-bounties-header "Bounties"]
(if (empty? open-bounties)
(if (empty? items)
[:div.view-no-data-container
[:p "No recent activity yet"]]
(into [:div.ui.items]
(for [bounty open-bounties]
[bounty-item bounty])))])
[:div [:div.item-counts-label
[:span (str "Showing " item-count " of " total-count)]]
(display-data-page bounty-page-data bounty-item :set-bounty-page-number)])])
(defn bounties-page []
(let [open-bounties (rf/subscribe [:open-bounties])
(let [bounty-page-data (rf/subscribe [:open-bounties-page])
open-bounties-loading? (rf/subscribe [:get-in [:open-bounties-loading?]])]
(fn []
(if @open-bounties-loading?
[:div.view-loading-container
[:div.ui.active.inverted.dimmer
[:div.ui.text.loader.view-loading-label "Loading"]]]
[bounties-list @open-bounties]))))
[bounties-list @bounty-page-data]))))

View File

@ -29,3 +29,87 @@
(defn issue-url [owner repo number]
(str "https://github.com/" owner "/" repo "/issues/" number))
(def items-per-page 20)
(defn draw-page-numbers [page-number page-count set-page-kw]
"Draw page numbers for the pagination component.
Inserts ellipsis when list is too long, by default
max 6 items are allowed"
(let [draw-page-num-fn (fn [current? i]
^{:key i}
[:div.rectangle-rounded
(cond-> {}
(not current?)
(assoc :class "grayed-out"
:on-click #(rf/dispatch [set-page-kw i])))
i])
max-page-nums 6]
[:div.page-nums-container
(cond (<= page-count max-page-nums)
(for [i (map inc (range page-count))]
(draw-page-num-fn (= i page-number) i))
(<= page-number (- max-page-nums 3))
(concat
(for [i (map inc (range (- max-page-nums 2)))]
(draw-page-num-fn (= i page-number) i))
[^{:key (dec max-page-nums)}
[:div.page-nav-text [:span "..."]]]
[(draw-page-num-fn false page-count)])
(>= page-number (- page-count (- max-page-nums 4)))
(concat
[(draw-page-num-fn false 1)
^{:key 2}
[:div.page-nav-text [:span "..."]]]
(for [i (map inc (range (- page-count 4) page-count))]
(draw-page-num-fn (= i page-number) i))
)
:else
(concat
[(draw-page-num-fn false 1)
^{:key 2} [:div.page-nav-text [:span "..."]]]
(for [i [(dec page-number) page-number (inc page-number)]]
(draw-page-num-fn (= i page-number) i))
[^{:key (dec page-count)} [:div.page-nav-text [:span "..."]]
(draw-page-num-fn false page-count)]))]))
(defn display-data-page [{:keys [items
item-count
total-count
page-number
page-count]}
draw-item-fn
set-page-kw]
"Draw data items along with pagination controls"
(let [draw-items (fn []
(into [:div.ui.items]
(for [item items]
^{:key item} [draw-item-fn item])))
on-direction-click (fn [forward?]
#(when (or (and (< page-number page-count)
forward?)
(and (< 1 page-number)
(not forward?)))
(rf/dispatch [set-page-kw
(if forward?
(inc page-number)
(dec page-number))])))
draw-rect (fn [direction]
(let [forward? (= direction :forward)]
[:div.rectangle-rounded
{:on-click (on-direction-click forward?)}
[:img.icon-forward-gray
(cond-> {:src "icon-forward-gray.svg"}
forward? (assoc :class "flip-horizontal"))]]))]
(cond (<= total-count items-per-page)
[draw-items]
:else
[:div
[draw-items]
[:div.page-nav-container
[draw-rect :backward]
[draw-rect :forward]
[:div.page-nav-text [:span (str "Page " page-number " of " page-count)]]
[draw-page-numbers page-number page-count set-page-kw]]])))

View File

@ -8,6 +8,8 @@
:activity-feed-loading? false
:open-bounties-loading? false
:open-bounties []
:bounty-page-number 1
:activity-page-number 1
:owner-bounties {}
:top-hunters []
:activity-feed []})

View File

@ -68,6 +68,16 @@
(fn [db [_ page]]
(assoc db :page page)))
(reg-event-db
:set-bounty-page-number
(fn [db [_ page]]
(assoc db :bounty-page-number page)))
(reg-event-db
:set-activity-page-number
(fn [db [_ page]]
(assoc db :activity-page-number page)))
(reg-event-fx
:set-flash-message
(fn [{:keys [db]} [_ type text]]

View File

@ -1,5 +1,6 @@
(ns commiteth.subscriptions
(:require [re-frame.core :refer [reg-sub]]))
(:require [re-frame.core :refer [reg-sub]]
[commiteth.common :refer [items-per-page]]))
(reg-sub
:db
@ -33,7 +34,28 @@
(reg-sub
:open-bounties
(fn [db _]
(:open-bounties db)))
(vec (:open-bounties db))))
(reg-sub
:bounty-page-number
(fn [db _]
(:bounty-page-number db)))
(reg-sub
:open-bounties-page
:<- [:open-bounties]
:<- [:bounty-page-number]
(fn [[open-bounties page-number] _]
(let [total-count (count open-bounties)
start (* (dec page-number) items-per-page)
end (min total-count (+ items-per-page start))
items (subvec open-bounties start end)]
{:items items
:item-count (count items)
:total-count total-count
:page-number page-number
:page-count (Math/ceil (/ total-count items-per-page))})))
(reg-sub
:owner-bounties
@ -53,7 +75,28 @@
(reg-sub
:activity-feed
(fn [db _]
(:activity-feed db)))
(vec (:activity-feed db))))
(reg-sub
:activity-page-number
(fn [db _]
(:activity-page-number db)))
(reg-sub
:activities-page
:<- [:activity-feed]
:<- [:activity-page-number]
(fn [[activities page-number] _]
(let [total-count (count activities)
start (* (dec page-number) items-per-page)
end (min total-count (+ items-per-page start))
items (subvec activities start end)]
{:items items
:item-count (count items)
:total-count total-count
:page-number page-number
:page-count (Math/ceil (/ total-count items-per-page))})))
(reg-sub
:gh-admin-token

View File

@ -870,3 +870,85 @@ body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
.rectangle-rounded {
width: 45px;
height: 45px;
color: #57a7ed;
/*opacity: 0.2;*/
border-radius: 22.5px;
/*background-color: #57a7ed;*/
background-color: rgba(87,167,237,.2);
font-family: "PostGrotesk-Medium";
font-weight: 500;
font-size: 13px;
display: flex;
margin: 0 6px;
flex: none;
align-items: center;
justify-content: center;
}
.grayed-out {
color: #8d99a4;
background-color: #f2f5f8;
opacity: 1.0;
}
.flip-horizontal {
-moz-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
-o-transform: scaleX(-1);
transform: scaleX(-1);
-ms-filter: fliph; /*IE*/
filter: fliph;
}
.pagination-text {
width: 83px;
height: 15px;
font-family: PostGrotesk;
font-size: 15px;
text-align: center;
color: #8d99a4;
}
.icon-forward-gray {
width: 24px;
height: 24px;
object-fit: contain;
}
.page-nav-container {
display: flex;
margin: 0 -6px;
}
.page-nums-container {
display: flex;
margin-left: auto;
justify-content: space-between;
}
.page-nav-text {
font-family: PostGrotesk-Book;
font-size: 15px;
color: #8d99a4;
display: flex;
margin: 0 6px;
flex: none;
align-items: center;
justify-content: center;
}
.item-counts-label {
margin: auto;
font-family: "PostGrotesk-Book";
font-size: 15px;
color: #8d99a4;
padding-top: 8px;
padding-bottom: 8px;
}