fix: load all pages initially

There're still some issues when loading partial pages initially,
let's improve the performance during the test.
experiment/tanstack-table
Tienson Qin 2024-06-26 17:46:52 +08:00
parent 119b519e2a
commit 5c965e5235
7 changed files with 81 additions and 258 deletions

View File

@ -36,14 +36,15 @@
"logseq/custom.js"]]
(map #(d/pull db '[*] [:file/path %]) files))))
(defn get-all-pages
[db exclude-page-ids]
(->> (d/datoms db :avet :block/name)
(keep (fn [e]
(when-not (contains? exclude-page-ids (:e e))
(d/pull db '[:db/id :db/ident :block/uuid :block/name :block/original-name :block/alias :block/type :block/journal-day
:block/created-at :block/updated-at]
(:e e)))))))
(comment
(defn get-all-pages
[db exclude-page-ids]
(->> (d/datoms db :avet :block/name)
(keep (fn [e]
(when-not (contains? exclude-page-ids (:e e))
(d/pull db '[:db/id :db/ident :block/uuid :block/name :block/original-name :block/alias :block/type :block/journal-day
:block/created-at :block/updated-at]
(:e e))))))))
(defn get-all-files
[db]
@ -205,13 +206,30 @@
(mapcat (fn [p]
(d/datoms db :eavt (:db/id p)))))))
(defn get-all-pages
[db]
(let [datoms (d/datoms db :avet :block/name)]
(mapcat (fn [d] (d/datoms db :eavt (:e d))) datoms)))
(defn get-page->refs-count
[db]
(let [datoms (d/datoms db :avet :block/name)]
(->>
(map (fn [d]
[(:e d)
(count (:block/_refs (d/entity db (:e d))))]) datoms)
(into {}))))
(defn get-structured-datoms
[db]
(mapcat (fn [type]
(->> (d/datoms db :avet :block/type type)
(mapcat (fn [d]
(d/datoms db :eavt (:e d))))))
["property" "class" "closed value"]))
[
;; property and class pages are pulled from `get-all-pages` already
;; "property" "class"
"closed value"]))
(defn get-favorites
"Favorites page and its blocks"
@ -242,9 +260,11 @@
favorites (when db-graph? (get-favorites db))
latest-journals (get-latest-journals db 1)
all-files (get-all-files db)
all-pages (get-all-pages db)
structured-datoms (when db-graph?
(get-structured-datoms db))
data (concat idents
all-pages
structured-datoms
favorites
latest-journals

View File

@ -1,14 +0,0 @@
(ns logseq.shui.tanstack-table.core
(:require [rum.core :as rum]
[logseq.shui.util :as util]))
(def table (util/lsui-wrap "Table"))
(def table-header (util/lsui-wrap "TableHeader"))
(def table-body (util/lsui-wrap "TableBody"))
(def table-footer (util/lsui-wrap "TableFooter"))
(def table-head (util/lsui-wrap "TableHead"))
(def table-row (util/lsui-wrap "TableRow"))
(def table-cell (util/lsui-wrap "TableCell"))
(def table-caption (util/lsui-wrap "TableCaption"))
(def ^js tanStackReact (util/lsui-get "tanStackReact"))

View File

@ -4,12 +4,12 @@
[logseq.shui.shortcut.v1 :as shui.shortcut.v1]
[logseq.shui.toaster.core :as toaster-core]
[logseq.shui.select.core :as select-core]
[logseq.shui.tanstack-table.core :as tanstack-table-core]
[logseq.shui.select.multi :as select-multi]
[logseq.shui.dialog.core :as dialog-core]
[logseq.shui.popup.core :as popup-core]
[logseq.shui.base.core :as base-core]
[logseq.shui.form.core :as form-core]))
[logseq.shui.form.core :as form-core]
[logseq.shui.table.core :as table-core]))
(def button base-core/button)
(def link base-core/link)
@ -52,15 +52,6 @@
(def card-content (util/lsui-wrap "CardContent"))
(def card-footer (util/lsui-wrap "CardFooter"))
(def table tanstack-table-core/table)
(def table-header tanstack-table-core/table-header)
(def table-body tanstack-table-core/table-body)
(def table-footer tanstack-table-core/table-footer)
(def table-head tanstack-table-core/table-head)
(def table-row tanstack-table-core/table-row)
(def table-cell tanstack-table-core/table-cell)
(def table-caption tanstack-table-core/table-caption)
(def ^js tanStackReact tanstack-table-core/tanStackReact)
(def form-provider form-core/form-provider)
(def form-item form-core/form-item)
@ -137,3 +128,12 @@
(def popup-hide-all! popup-core/hide-all!)
(def multi-select-content select-multi/x-select-content)
(def table-option table-core/table-option)
(def table table-core/table)
(def table-header table-core/table-header)
(def table-head table-core/table-head)
(def table-body table-core/table-body)
(def table-row table-core/table-row)
(def table-cell table-core/table-cell)
(def table-get-selection-rows-count table-core/get-selection-rows-count)

View File

@ -84,15 +84,15 @@
[visible-columns set-visible-columns!] (rum/use-state {})
[row-selection set-row-selection!] (rum/use-state {})
{:keys [column-visible? column-toggle-visiblity row-selected?]
:as table} (table/table-option {:data data
:columns columns
:state {:sorting sorting
:row-filter row-filter
:row-selection row-selection
:visible-columns visible-columns}
:data-fns {:set-sorting! set-sorting!
:set-visible-columns! set-visible-columns!
:set-row-selection! set-row-selection!}})]
:as table} (shui/table-option {:data data
:columns columns
:state {:sorting sorting
:row-filter row-filter
:row-selection row-selection
:visible-columns visible-columns}
:data-fns {:set-sorting! set-sorting!
:set-visible-columns! set-visible-columns!
:set-row-selection! set-row-selection!}})]
[:div.w-full
[:div.flex.items-center.py-4
(shui/input
@ -127,35 +127,35 @@
(:name column)))))]
(let [columns' (:columns table)]
[:div.rounded-md.border
(table/table
(table/table-header
(table/table-row
(shui/table
(shui/table-header
(shui/table-row
(for [column columns']
(table/table-head
(shui/table-head
{:key (:id column)}
(let [header-fn (:header column)]
(if (fn? header-fn)
(header-fn table column)
header-fn))))))
(table/table-body
(shui/table-body
(let [rows (:rows table)]
(if (pos? (count rows))
(for [row rows]
(table/table-row
(shui/table-row
{:key (str (:id row))
:data-state (when (row-selected? row) "selected")}
(for [column columns']
(let [id (str (:id row) "-" (:id column))
render (get column :cell)]
(table/table-cell
(shui/table-cell
{:key id}
(render table row column))))))
(table/table-row
(table/table-cell
(shui/table-row
(shui/table-cell
{:colSpan (count columns)
:className "h-24 text-center"}
"No results."))))))])
(let [selected-rows-count (table/get-selection-rows-count row-selection (:rows table))
(let [selected-rows-count (shui/table-get-selection-rows-count row-selection (:rows table))
rows-count (count (:rows table))]
[:div.flex.items-center.justify-end.space-x-2.py-4
[:div.flex-1.text-sm.text-muted-foreground

View File

@ -1,188 +0,0 @@
(ns frontend.components.all-pages2
"All pages"
(:require [logseq.shui.ui :as shui]
[rum.core :as rum]
[cljs-bean.core :refer [->js ->clj]]
[frontend.util :as util]
[goog.object :as gobj]
[frontend.ui :as ui]))
(def useReactTable (gobj/get shui/tanStackReact "useReactTable"))
(def getCoreRowModel (gobj/get shui/tanStackReact "getCoreRowModel"))
(def getSortedRowModel (gobj/get shui/tanStackReact "getSortedRowModel"))
(def getFilteredRowModel (gobj/get shui/tanStackReact "getFilteredRowModel"))
(def getPaginationRowModel (gobj/get shui/tanStackReact "getPaginationRowModel"))
(def flexRender (gobj/get shui/tanStackReact "flexRender"))
(def data
[{:id "m5gr84i9" :amount 316 :status "success" :email "ken99@yahoo.com"}
{:id "3u1reuv4" :amount 242 :status "success" :email "Abe45@gmail.com"}
{:id "derv1ws0" :amount 837 :status "processing" :email "Monserrat44@gmail.com"}
{:id "5kma53ae" :amount 874 :status "success" :email "Silas22@gmail.com"}
{:id "bhqecj4p" :amount 721 :status "failed" :email "carmella@hotmail.com"}])
(def rows data)
(defn header-checkbox [^js table]
(shui/checkbox
{:checked (or (.getIsAllPageRowsSelected table)
(and (.getIsSomePageRowsSelected table) "indeterminate"))
:on-checked-change #(.toggleAllPageRowsSelected table %)
:aria-label "Select all"}))
(defn row-checkbox [^js row]
(shui/checkbox
{:checked (.getIsSelected row)
:on-checked-change (fn [v] (.toggleSelected row v))
:aria-label "Select row"}))
(def columns
[{:id "select"
:header (fn [opts] (header-checkbox (.-table opts)))
:cell (fn [opts] (row-checkbox (.-row opts)))
:enableSorting false
:enableHiding false}
{:accessorKey "status"
:header "Status"
:cell (fn [^js opts]
(.getValue (.-row opts) "status"))}
{:accessorKey "email"
:header (fn [^js opts]
(shui/button
{:variant "ghost"
:onClick #(.toggleSorting ^js (.-column opts) (= "asc" (.getIsSorted ^js (.-column opts))))}
"Email"
(ui/icon "arrows-up-down")))
:cell (fn [opts] (.getValue (.-row opts) "email"))}
{:accessorKey "amount"
:header (fn [_opts] "Amount")
:cell (fn [opts]
(let [amount (.getValue (.-row opts) "amount")
formatted (.format (js/Intl.NumberFormat. "en-US" #js {:style "currency" :currency "USD"}) amount)]
formatted))}
{:id "actions"
:enableHiding false
:cell (fn [opts]
(let [payment (.-original (.-row opts))]
(shui/dropdown-menu
(shui/dropdown-menu-trigger
{:asChild true}
(shui/button
{:variant "ghost" :className "h-8 w-8 p-0"}
[:span.sr-only "Open menu"]
(ui/icon "dots")))
(shui/dropdown-menu-content
(shui/dropdown-menu-label
"Actions")
(shui/dropdown-menu-item
{:onClick #(js/navigator.clipboard.writeText (.-id payment))}
"Copy payment ID")
(shui/dropdown-menu-separator)
(shui/dropdown-menu-item
"View customer")
(shui/dropdown-menu-item
"View payment details")))))}])
(rum/defc all-pages < rum/static
[]
(let [[sorting set-sorting!] (rum/use-state #js [])
[column-filters set-column-filters!] (rum/use-state #js [])
[column-visibility set-column-visibility!] (rum/use-state #js {})
[row-selection set-row-selection!] (rum/use-state #js {})
_ (prn :debug row-selection)
^js table (useReactTable #js {:columns (->js columns)
:data (->js data)
:state (->js
{:sorting sorting
:columnFilters column-filters
:columnVisibility column-visibility
:rowSelection row-selection})
:getCoreRowModel (getCoreRowModel)
:getSortedRowModel (getSortedRowModel)
:getFilteredRowModel (getFilteredRowModel)
:getPaginationRowModel (getPaginationRowModel)
:onSortingChange set-sorting!
:onColumnFiltersChange set-column-filters!
:onColumnVisibilityChange set-column-visibility!
:onRowSelectionChange set-row-selection!})]
[:div.w-full
[:div.flex.items-center.py-4
(shui/input
{:placeholder "Filter emails..."
:value (or
(when-let [^js column (.getColumn table "email")]
(try
(str (.getFilterValue column))
(catch :default _
nil)))
"")
:onChange (fn [e]
(when-let [^js column (.getColumn table "email")]
(.setFilterValue column (util/evalue e))))
:className "max-w-sm"})
(shui/dropdown-menu
(shui/dropdown-menu-trigger
{:asChild true}
(shui/button
{:variant "outline" :className "ml-auto"}
"Columns"
(ui/icon "chevron-down")))
(shui/dropdown-menu-content
{:align "end"}
(for [^js column (.getAllColumns table)]
(shui/dropdown-menu-checkbox-item
{:key (.-id column)
:className "capitalize"
:checked (.getIsVisible column)
:onCheckedChange #(.toggleVisibility column %)}
(.-id column)))))]
[:div.rounded-md.border
(shui/table
(shui/table-header
(for [^js headerGroup (.getHeaderGroups table)]
(shui/table-row
{:key (.-id headerGroup)}
(for [^js header (.-headers headerGroup)]
(shui/table-head
{:key (.-id header)}
(when-not (.-isPlaceholder header)
(flexRender
(-> header .-column .-columnDef .-header)
(.getContext header))))))))
(shui/table-body
(let [^js rows (.-rows (.getRowModel table))]
(if (pos? (count rows))
(for [^js row rows]
(shui/table-row
{:key (.-id row)
:data-state (when (.getIsSelected row) "selected")}
(for [^js cell (.getVisibleCells row)]
(shui/table-cell
{:key (.-id cell)}
(flexRender
(-> cell .-column .-columnDef .-cell)
(.getContext cell))))))
(shui/table-row
(shui/table-cell
{:colSpan (count columns)
:className "h-24 text-center"}
"No results."))))))]
[:div.flex.items-center.justify-end.space-x-2.py-4
[:div.flex-1.text-sm.text-muted-foreground
(let [selected-rows (.-rows ^js (.getFilteredSelectedRowModel table))
filter-rows (.-rows ^js (.getFilteredRowModel table))]
(str (count selected-rows)
" of "
(count filter-rows) " row(s) selected."))]
[:div.space-x-2
(shui/button {:variant "outline"
:size "sm"
:onClick #(.previousPage table)
:disabled (not (.getCanPreviousPage table))}
"Previous")
(shui/button {:variant "outline"
:size "sm"
:onClick #(.nextPage table)
:disabled (not (.getCanNextPage table))}
"Next")]]]))

View File

@ -7,9 +7,7 @@
[promesa.core :as p]
[cljs-time.core :as t]
[logseq.db.sqlite.common-db :as sqlite-common-db]
[datascript.transit :as dt]
[frontend.db.async :as db-async]
[clojure.core.async :as async]))
[datascript.transit :as dt]))
(defn restore-graph!
"Restore db from SQLite"
@ -33,6 +31,7 @@
(state/set-state! :graph/loading? false)
(react/clear-query-state!)
(state/pub-event! [:ui/re-render-root])
(async/go
(async/<! (async/timeout 100))
(db-async/<fetch-all-pages repo))))
;; (async/go
;; (async/<! (async/timeout 100))
;; (db-async/<fetch-all-pages repo))
))

View File

@ -421,19 +421,25 @@
(when-let [conn (worker-state/get-datascript-conn repo)]
(ldb/write-transit-str (sqlite-common-db/get-initial-data @conn))))
(get-page-refs-count
[_this repo]
(when-let [conn (worker-state/get-datascript-conn repo)]
(ldb/write-transit-str (sqlite-common-db/get-page->refs-count @conn))))
(fetch-all-pages
[_this repo exclude-page-ids-str]
(when-let [conn (worker-state/get-datascript-conn repo)]
(async/go
(let [all-pages (sqlite-common-db/get-all-pages @conn (ldb/read-transit-str exclude-page-ids-str))
partitioned-data (map-indexed (fn [idx p] [idx p]) (partition-all 2000 all-pages))]
(doseq [[idx tx-data] partitioned-data]
(worker-util/post-message :sync-db-changes {:repo repo
:tx-data tx-data
:tx-meta {:initial-pages? true
:end? (= idx (dec (count partitioned-data)))}})
(async/<! (async/timeout 100)))))
nil))
;; (when-let [conn (worker-state/get-datascript-conn repo)]
;; (async/go
;; (let [all-pages (sqlite-common-db/get-all-pages @conn (ldb/read-transit-str exclude-page-ids-str))
;; partitioned-data (map-indexed (fn [idx p] [idx p]) (partition-all 2000 all-pages))]
;; (doseq [[idx tx-data] partitioned-data]
;; (worker-util/post-message :sync-db-changes {:repo repo
;; :tx-data tx-data
;; :tx-meta {:initial-pages? true
;; :end? (= idx (dec (count partitioned-data)))}})
;; (async/<! (async/timeout 100)))))
;; nil)
)
(closeDB
[_this repo]