瀏覽代碼

refactor(ui): use pagination component for All pages

Andelf 2 年之前
父節點
當前提交
f5789bd4f9
共有 2 個文件被更改,包括 181 次插入187 次删除
  1. 181 166
      src/main/frontend/components/page.cljs
  2. 0 21
      src/main/frontend/components/page.css

+ 181 - 166
src/main/frontend/components/page.cljs

@@ -818,6 +818,36 @@
                     (notification/show! (str (t :tips/all-done) "!") :success)
                     (js/setTimeout #(refresh-fn) 200)))]]))
 
+(rum/defc pagination
+  "Pagination component, like `<< <Prev 1/10 Next> >>`.
+
+- current: current page number
+- total: total number of items
+- per-page: number of items per page
+- on-change: callback function when page number changes"
+  [& {:keys [current total per-page on-change]
+      :or {current 1 per-page 40}}]
+  (let [total-pages (int (Math/ceil (/ total per-page)))
+        has-prev? (> current 1)
+        has-next? (< current total-pages)
+        prev-page (if (= 1 current) 1 (dec current))
+        next-page (if (= total-pages current) total-pages (inc current))]
+    [:div.flex.items-center.noselect
+     (when has-prev?
+       [[:a.fade-link.flex
+         {:on-click #(on-change 1)}
+         (ui/icon "chevrons-left")]
+        [:a.fade-link.flex.items-center {:on-click #(on-change prev-page)}
+         (ui/icon "caret-left") (t :paginates/prev)]])
+     [:div.px-2
+      [:span (str current "/" total-pages)]]
+     (when has-next?
+       [[:a.fade-link.flex.items-center {:on-click #(on-change next-page)}
+         (t :paginates/next) (ui/icon "caret-right")]
+        [:a.fade-link.flex
+         {:on-click #(on-change total-pages)}
+         (ui/icon "chevrons-right")]])]))
+
 (rum/defcs ^:large-vars/cleanup-todo all-pages < rum/reactive
   (rum/local nil ::pages)
   (rum/local nil ::search-key)
@@ -847,15 +877,17 @@
         *search-input (rum/create-ref)
 
         *indeterminate (rum/derived-atom
-                           [*checks] ::indeterminate
-                         (fn [checks]
-                           (when-let [checks (vals checks)]
-                             (if (every? true? checks)
-                               1 (if (some true? checks) -1 0)))))
+                        [*checks] ::indeterminate
+                        (fn [checks]
+                          (when-let [checks (vals checks)]
+                            (if (every? true? checks)
+                              1 (if (some true? checks) -1 0)))))
 
         mobile? (util/mobile?)
+        total-items (count @*results-all)
+        ;; FIXME: "pages" is ambiguous here, it can be either "Logseq pages" or "result pages"
         total-pages (if-not @*results-all 0
-                            (js/Math.ceil (/ (count @*results-all) per-page-num)))
+                            (js/Math.ceil (/ total-items per-page-num)))
         to-page (fn [page]
                   (when (> total-pages 1)
                     (if (and (> page 0)
@@ -878,7 +910,7 @@
     [:div.flex-1.cp__all_pages
      [:h1.title (t :all-pages)]
 
-     [:div.text-sm.ml-1.opacity-70.mb-4 (t :paginates/pages (count @*results-all))]
+     [:div.text-sm.ml-1.opacity-70.mb-4 (t :paginates/pages total-items)]
 
      (when current-repo
 
@@ -918,168 +950,151 @@
                                       [idx (boolean (get @*checks idx))])))
            (reset! *results pages)))
 
-       (let [has-prev? (> @*current-page 1)
-             has-next? (not= @*current-page total-pages)]
-         [:div
-         [:div.actions
-          {:class (util/classnames [{:has-selected (or (nil? @*indeterminate)
-                                                       (not= 0 @*indeterminate))}])}
-          [:div.l.flex.items-center
-           [:div.actions-wrap
-            (ui/button
-              [(ui/icon "trash" {:style {:font-size 15}}) (t :delete)]
-              :on-click (fn []
-                          (let [selected (filter (fn [[_ v]] v) @*checks)
-                                selected (and (seq selected)
-                                              (into #{} (for [[k _] selected] k)))]
-                            (when-let [pages (and selected (filter #(contains? selected (:block/idx %)) @*results))]
-                              (state/set-modal! (batch-delete-dialog pages false #(do
-                                                                                    (reset! *checks nil)
-                                                                                    (refresh-pages)))))))
-              :class "fade-link"
-              :small? true)]
-
-           [:div.search-wrap.flex.items-center.pl-2
-            (let [search-fn (fn []
-                              (let [^js input (rum/deref *search-input)]
-                                (search-key (.-value input))
-                                (reset! *current-page 1)))
-                  reset-fn (fn []
+       [:div
+        [:div.actions
+         {:class (util/classnames [{:has-selected (or (nil? @*indeterminate)
+                                                      (not= 0 @*indeterminate))}])}
+         [:div.l.flex.items-center
+          [:div.actions-wrap
+           (ui/button
+            [(ui/icon "trash" {:style {:font-size 15}}) (t :delete)]
+            :on-click (fn []
+                        (let [selected (filter (fn [[_ v]] v) @*checks)
+                              selected (and (seq selected)
+                                            (into #{} (for [[k _] selected] k)))]
+                          (when-let [pages (and selected (filter #(contains? selected (:block/idx %)) @*results))]
+                            (state/set-modal! (batch-delete-dialog pages false #(do
+                                                                                  (reset! *checks nil)
+                                                                                  (refresh-pages)))))))
+            :class "fade-link"
+            :small? true)]
+
+          [:div.search-wrap.flex.items-center.pl-2
+           (let [search-fn (fn []
                              (let [^js input (rum/deref *search-input)]
-                               (set! (.-value input) "")
-                               (reset! *search-key nil)))]
-
-              [(ui/button (ui/icon "search")
-                 :on-click search-fn
-                 :small? true)
-               [:input.form-input {:placeholder   (t :search/page-names)
-                                   :on-key-up     (fn [^js e]
-                                                    (let [^js target (.-target e)]
-                                                      (if (string/blank? (.-value target))
-                                                        (reset! *search-key nil)
-                                                        (cond
-                                                          (= 13 (.-keyCode e)) (search-fn)
-                                                          (= 27 (.-keyCode e)) (reset-fn)))))
-                                   :ref           *search-input
-                                   :default-value ""}]
-
-               (when (not (string/blank? @*search-key))
-                 [:a.cancel {:on-click reset-fn}
-                  (ui/icon "x")])])]]
-
-          [:div.r.flex.items-center.justify-between
-           [:div
-            (ui/tippy
-             {:html  [:small (str (t :page/show-whiteboards) " ?")]
-              :arrow true}
-             [:a.button.whiteboard
-              {:class    (util/classnames [{:active (boolean @*whiteboard?)}])
-               :on-click #(reset! *whiteboard? (not @*whiteboard?))}
-              (ui/icon "whiteboard" {:extension? true :style {:fontSize ui/icon-size}})])]
-           [:div
-            (ui/tippy
-             {:html  [:small (str (t :page/show-journals) " ?")]
-              :arrow true}
-             [:a.button.journal
-              {:class    (util/classnames [{:active (boolean @*journal?)}])
-               :on-click #(reset! *journal? (not @*journal?))}
-              (ui/icon "calendar" {:size ui/icon-size})])]
-
-           [:div.paginates
-            [:span.flex.items-center
-             {:class (util/classnames [{:is-first (= 1 @*current-page)
-                                        :is-last  (= @*current-page total-pages)}])}
-             (when has-prev?
-               [:a.py-4.pr-2.fade-link.flex.items-center
-                {:on-click #(to-page (dec @*current-page))}
-                (ui/icon "caret-left") (str " " (t :paginates/prev))])
-             [:span.opacity-60 (str @*current-page "/" total-pages)]
-             (when has-next?
-               [:a.py-4.pl-2.fade-link.flex.items-center
-                {:on-click #(to-page (inc @*current-page))} (str (t :paginates/next) " ")
-                (ui/icon "caret-right")])]]
-
-           (ui/dropdown-with-links
-            (fn [{:keys [toggle-fn]}]
-              [:a.button.fade-link
-               {:on-click toggle-fn}
-               (ui/icon "dots" {:size ui/icon-size})])
-            [{:title (t :remove-orphaned-pages)
-              :options {:on-click (fn []
-                                    (let [orphaned-pages (model/get-orphaned-pages {})
-                                          orphaned-pages? (seq orphaned-pages)]
-                                      (if orphaned-pages?
-                                        (state/set-modal!
-                                         (batch-delete-dialog
-                                          orphaned-pages  true
-                                          #(do
-                                             (reset! *checks nil)
-                                             (refresh-pages))))
-                                        (notification/show! "Congratulations, no orphaned pages in your graph!" :success))))}
-              :icon (ui/icon "file-x")}
-             {:title (t :all-files)
-              :options {:href (rfe/href :all-files)}
-              :icon (ui/icon "files")}]
-            {})]]
-
-         [:table.table-auto.cp__all_pages_table
-          [:thead
-           [:tr
-            [:th.selector
-             (checkbox-opt "all-pages-select-all"
-                           (= 1 @*indeterminate)
-                           {:on-change     (fn []
-                                             (let [indeterminate? (= -1 @*indeterminate)
-                                                   all? (= 1 @*indeterminate)]
-                                               (doseq [{:block/keys [idx]} @*results]
-                                                 (swap! *checks assoc idx (or indeterminate? (not all?))))))
-                            :indeterminate (= -1 @*indeterminate)})]
-
-            (sortable-title (t :block/name) :block/name *sort-by-item *desc?)
-            (when-not mobile?
-              [(sortable-title (t :page/backlinks) :block/backlinks *sort-by-item *desc?)
-               (sortable-title (t :page/created-at) :block/created-at *sort-by-item *desc?)
-               (sortable-title (t :page/updated-at) :block/updated-at *sort-by-item *desc?)])]]
-
-          [:tbody
-           (for [{:block/keys [idx name created-at updated-at backlinks] :as page} @*results]
-             (when-not (string/blank? name)
-               [:tr {:key name}
-                [:td.selector
-                 (checkbox-opt (str "label-" idx)
-                               (get @*checks idx)
-                               {:on-change (fn []
-                                             (swap! *checks update idx not))})]
-
-                [:td.name [:a {:on-click (fn [e]
+                               (search-key (.-value input))
+                               (reset! *current-page 1)))
+                 reset-fn (fn []
+                            (let [^js input (rum/deref *search-input)]
+                              (set! (.-value input) "")
+                              (reset! *search-key nil)))]
+
+             [(ui/button (ui/icon "search")
+                         :on-click search-fn
+                         :small? true)
+              [:input.form-input {:placeholder   (t :search/page-names)
+                                  :on-key-up     (fn [^js e]
+                                                   (let [^js target (.-target e)]
+                                                     (if (string/blank? (.-value target))
+                                                       (reset! *search-key nil)
+                                                       (cond
+                                                         (= 13 (.-keyCode e)) (search-fn)
+                                                         (= 27 (.-keyCode e)) (reset-fn)))))
+                                  :ref           *search-input
+                                  :default-value ""}]
+
+              (when (not (string/blank? @*search-key))
+                [:a.cancel {:on-click reset-fn}
+                 (ui/icon "x")])])]]
+
+         [:div.r.flex.items-center.justify-between
+          [:div
+           (ui/tippy
+            {:html  [:small (str (t :page/show-whiteboards) " ?")]
+             :arrow true}
+            [:a.button.whiteboard
+             {:class    (util/classnames [{:active (boolean @*whiteboard?)}])
+              :on-click #(reset! *whiteboard? (not @*whiteboard?))}
+             (ui/icon "whiteboard" {:extension? true :style {:fontSize ui/icon-size}})])]
+          [:div
+           (ui/tippy
+            {:html  [:small (str (t :page/show-journals) " ?")]
+             :arrow true}
+            [:a.button.journal
+             {:class    (util/classnames [{:active (boolean @*journal?)}])
+              :on-click #(reset! *journal? (not @*journal?))}
+             (ui/icon "calendar" {:size ui/icon-size})])]
+
+          [:div.paginates
+           (pagination :current @*current-page
+                       :total total-items
+                       :per-page per-page-num
+                       :on-change #(to-page %))]
+
+          (ui/dropdown-with-links
+           (fn [{:keys [toggle-fn]}]
+             [:a.button.fade-link
+              {:on-click toggle-fn}
+              (ui/icon "dots" {:size ui/icon-size})])
+           [{:title (t :remove-orphaned-pages)
+             :options {:on-click (fn []
+                                   (let [orphaned-pages (model/get-orphaned-pages {})
+                                         orphaned-pages? (seq orphaned-pages)]
+                                     (if orphaned-pages?
+                                       (state/set-modal!
+                                        (batch-delete-dialog
+                                         orphaned-pages  true
+                                         #(do
+                                            (reset! *checks nil)
+                                            (refresh-pages))))
+                                       (notification/show! "Congratulations, no orphaned pages in your graph!" :success))))}
+             :icon (ui/icon "file-x")}
+            {:title (t :all-files)
+             :options {:href (rfe/href :all-files)}
+             :icon (ui/icon "files")}]
+           {})]]
+
+        [:table.table-auto.cp__all_pages_table
+         [:thead
+          [:tr
+           [:th.selector
+            (checkbox-opt "all-pages-select-all"
+                          (= 1 @*indeterminate)
+                          {:on-change     (fn []
+                                            (let [indeterminate? (= -1 @*indeterminate)
+                                                  all? (= 1 @*indeterminate)]
+                                              (doseq [{:block/keys [idx]} @*results]
+                                                (swap! *checks assoc idx (or indeterminate? (not all?))))))
+                           :indeterminate (= -1 @*indeterminate)})]
+
+           (sortable-title (t :block/name) :block/name *sort-by-item *desc?)
+           (when-not mobile?
+             [(sortable-title (t :page/backlinks) :block/backlinks *sort-by-item *desc?)
+              (sortable-title (t :page/created-at) :block/created-at *sort-by-item *desc?)
+              (sortable-title (t :page/updated-at) :block/updated-at *sort-by-item *desc?)])]]
+
+         [:tbody
+          (for [{:block/keys [idx name created-at updated-at backlinks] :as page} @*results]
+            (when-not (string/blank? name)
+              [:tr {:key name}
+               [:td.selector
+                (checkbox-opt (str "label-" idx)
+                              (get @*checks idx)
+                              {:on-change (fn []
+                                            (swap! *checks update idx not))})]
+
+               [:td.name [:a {:on-click (fn [e]
                                           (.preventDefault e)
-                                           (let [repo (state/get-current-repo)]
-                                             (when (gobj/get e "shiftKey")
-                                               (state/sidebar-add-block!
-                                                repo
-                                                (:db/id page)
-                                                :page))))
-                               :href     (rfe/href :page {:name (:block/name page)})}
-                           (component-block/page-cp {} page)]]
-
-                (when-not mobile?
-                  [:td.backlinks [:span backlinks]])
-
-                (when-not mobile?
+                                          (let [repo (state/get-current-repo)]
+                                            (when (gobj/get e "shiftKey")
+                                              (state/sidebar-add-block!
+                                               repo
+                                               (:db/id page)
+                                               :page))))
+                              :href     (rfe/href :page {:name (:block/name page)})}
+                          (component-block/page-cp {} page)]]
+
+               (when-not mobile?
+                 [[:td.backlinks [:span backlinks]]
                   [:td.created-at [:span (if created-at
                                            (date/int->local-time-2 created-at)
-                                           "Unknown")]])
-                (when-not mobile?
+                                           "Unknown")]]
                   [:td.updated-at [:span (if updated-at
                                            (date/int->local-time-2 updated-at)
-                                           "Unknown")]])]))]]
-
-         [:div.paginates
-          [:span]
-          [:span.flex.items-center
-           (when has-prev?
-             [:a.py-4.text-sm.fade-link.flex.items-center {:on-click #(to-page (dec @*current-page))}
-              (ui/icon "caret-left") (str " " (t :paginates/prev))])
-           (when has-next?
-             [:a.py-4.pl-2.text-sm.fade-link.flex.items-center {:on-click #(to-page (inc @*current-page))} (str (t :paginates/next) " ")
-              (ui/icon "caret-right")])]]]))]))
+                                           "Unknown")]]])]))]]
+
+        [:div.flex.justify-end.py-4
+         (pagination :current @*current-page
+                     :total total-items
+                     :per-page per-page-num
+                     :on-change #(to-page %))]])]))

+ 0 - 21
src/main/frontend/components/page.css

@@ -195,27 +195,6 @@
       }
     }
   }
-
-  .paginates {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 0 4px;
-
-    > span {
-      color: var(--ls-primary-text-color);
-
-      &:last-child {
-        a {
-          user-select: none;
-
-          &:active {
-            opacity: .6;
-          }
-        }
-      }
-    }
-  }
 }
 
 .cp__vertical-menu-button {