enhance: add table action bar

feat/asset-sync
Tienson Qin 2024-07-08 16:12:57 +08:00
parent b273df3e76
commit 374f43e0c4
7 changed files with 96 additions and 132 deletions

View File

@ -236,13 +236,6 @@
prop) prop)
children])) children]))
(rum/defc table-head < rum/static
[& prop-and-children]
(let [[prop children] (get-prop-and-children prop-and-children)]
[:div (merge {:class "cursor-pointer transition-colors hover:bg-muted/50 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:px-0"}
prop)
children]))
(rum/defc table-cell < rum/static (rum/defc table-cell < rum/static
[& prop-and-children] [& prop-and-children]
(let [[prop children] (get-prop-and-children prop-and-children)] (let [[prop children] (get-prop-and-children prop-and-children)]
@ -256,3 +249,15 @@
:else :else
" border-r px-2"))} " border-r px-2"))}
children]])) children]]))
(rum/defc table-actions < rum/static
[& prop-and-children]
(let [[prop children] (get-prop-and-children prop-and-children)
el-ref (rum/use-ref nil)
;; _ (use-sticky-element2! (get-main-scroll-container) el-ref)
]
[:div.ls-table-actions.flex.flex-row.items-center.gap-1.bg-gray-01
(merge {:ref el-ref
:style {:z-index 101}}
prop)
children]))

View File

@ -134,4 +134,5 @@
(def table-footer table-core/table-footer) (def table-footer table-core/table-footer)
(def table-row table-core/table-row) (def table-row table-core/table-row)
(def table-cell table-core/table-cell) (def table-cell table-core/table-cell)
(def table-actions table-core/table-actions)
(def table-get-selection-rows table-core/get-selection-rows) (def table-get-selection-rows table-core/get-selection-rows)

View File

@ -2,13 +2,15 @@
"All pages" "All pages"
(:require [clojure.string :as string] (:require [clojure.string :as string]
[frontend.components.block :as component-block] [frontend.components.block :as component-block]
[frontend.components.page :as component-page]
[frontend.components.views :as views] [frontend.components.views :as views]
[frontend.handler.page :as page-handler] [frontend.handler.page :as page-handler]
[frontend.state :as state] [frontend.state :as state]
[logseq.db :as ldb] [logseq.db :as ldb]
[frontend.db :as db] [frontend.db :as db]
[promesa.core :as p] [promesa.core :as p]
[rum.core :as rum])) [rum.core :as rum]
[logseq.shui.ui :as shui]))
(defn- columns (defn- columns
[db] [db]
@ -56,79 +58,12 @@
[:div.ls-all-pages.w-full [:div.ls-all-pages.w-full
(views/view view-entity {:data data (views/view view-entity {:data data
:set-data! set-data! :set-data! set-data!
:columns columns})]))
(comment
(rum/defc all-pages < rum/static
[]
(let [[input set-input!] (rum/use-state "")
[sorting set-sorting!] (rum/use-state [{:id :block/updated-at, :asc? false}])
[row-filter set-row-filter!] (rum/use-state nil)
[visible-columns set-visible-columns!] (rum/use-state {:block/type false})
[row-selection set-row-selection!] (rum/use-state {})
[data set-data!] (rum/use-state (get-all-pages))
_ (rum/use-effect!
(fn []
(when-let [^js worker @state/*db-worker]
(p/let [result-str (.get-page-refs-count worker (state/get-current-repo))
result (ldb/read-transit-str result-str)
data (map (fn [row] (assoc row :block.temp/refs-count (get result (:db/id row) 0))) data)]
(set-data! data))))
[])
table (shui/table-option {:data data
:columns columns :columns columns
:state {:sorting sorting :on-delete-rows (fn [table selected-rows]
:row-filter row-filter (shui/dialog-open!
:row-selection row-selection (component-page/batch-delete-dialog
:visible-columns visible-columns} selected-rows false
:data-fns {:set-sorting! set-sorting! (fn []
:set-visible-columns! set-visible-columns! (when-let [f (get-in table [:data-fns :set-row-selection!])]
:set-row-selection! set-row-selection!}}) (f {}))
selected-rows (shui/table-get-selection-rows row-selection (:rows table)) (set-data! (get-all-pages))))))})]))
selected-rows-count (count selected-rows)
selected? (pos? selected-rows-count)]
[:div.w-full
[:div.flex.items-center.pb-4.justify-between
[:div.ml-1
(when selected?
(shui/button {:variant :destructive
:class "text-red-500"
:size :sm
:on-click #(shui/dialog-open!
(component-page/batch-delete-dialog selected-rows false (fn [] (set-data! (get-all-pages)))))}
(ui/icon "trash-x")))]
[:div.flex.items-center.gap-2
(shui/input
{:placeholder "Search pages"
:value input
:onChange (fn [e]
(let [value (util/evalue e)]
(set-input! value)
(set-row-filter! (fn []
;; Returns a fn here.
;; https://stackoverflow.com/questions/55621212/is-it-possible-to-react-usestate-in-react
(fn [row]
(if (string/blank? value)
true
(when row
(pos? (fuzzy-search/score (string/lower-case value) (:block/name row))))))))))
:class "max-w-sm !h-7 !py-0"})
(columns-select columns table)]]
(let [columns' (:columns table)
rows (:rows table)]
[:div.rounded-md.border
(ui/virtualized-table
{:custom-scroll-parent (gdom/getElement "main-content-container")
:total-count (count rows)
:fixedHeaderContent (fn [] (table-header table columns'))
:components {:Table (fn [props]
(shui/table {}
(.-children props)))
:TableRow (fn [props] (table-row table rows columns' props))}})])
(let [rows-count (count (:rows table))]
[:div.flex.items-center.justify-end.space-x-2.py-4
[:div.flex-1.text-sm.text-muted-foreground
(if (pos? selected-rows-count)
(str selected-rows-count " of " rows-count " row(s) selected.")
(str "Total: " rows-count))]])])))

View File

@ -11,7 +11,9 @@
[frontend.state :as state] [frontend.state :as state]
[logseq.outliner.property :as outliner-property] [logseq.outliner.property :as outliner-property]
[promesa.core :as p] [promesa.core :as p]
[rum.core :as rum])) [rum.core :as rum]
[frontend.modules.outliner.ui :as ui-outliner-tx]
[frontend.modules.outliner.op :as outliner-op]))
(defn- get-all-objects (defn- get-all-objects
[class] [class]
@ -69,7 +71,22 @@
:add-property! (fn [] :add-property! (fn []
(state/pub-event! [:editor/new-property {:block class (state/pub-event! [:editor/new-property {:block class
:page-configure? true :page-configure? true
:class-schema? true}]))})))) :class-schema? true}]))
:on-delete-rows (fn [table selected-rows]
(let [pages (filter ldb/page? selected-rows)
blocks (remove ldb/page? selected-rows)]
(p/do!
(ui-outliner-tx/transact!
{:outliner-op :delete-blocks}
(when (seq blocks)
(outliner-op/delete-blocks! blocks nil))
(let [page-ids (map :db/id pages)
tx-data (map (fn [pid] [:db/retract pid :block/tags (:db/id class)]) page-ids)]
(when (seq tx-data)
(outliner-op/transact! tx-data {:outliner-op :save-block}))))
(set-data! (get-all-objects class))
(when-let [f (get-in table [:data-fns :set-row-selection!])]
(f {})))))}))))
(rum/defcs objects < rum/reactive db-mixins/query mixins/container-id (rum/defcs objects < rum/reactive db-mixins/query mixins/container-id
[state class] [state class]

View File

@ -1031,27 +1031,13 @@
(t :remove-orphaned-pages) (t :remove-orphaned-pages)
(t :page/delete-confirmation))]]] (t :page/delete-confirmation))]]]
[:div.cp__all_pages_table-wrap [:ol.p-2.pt-4
[:table.w-full.cp__all_pages_table.mt-4 (for [page pages]
[:thead [:li
[:tr.opacity-70 [:a {:href (rfe/href :page {:name (:block/uuid page)})}
[:th [:span "#"]] (component-block/page-cp {} page)]])]
[:th [:span (t :block/name)]]
[:th [:span (t :page/backlinks)]]
(when-not orphaned-pages? [:th [:span (t :page/created-at)]])
(when-not orphaned-pages? [:th [:span (t :page/updated-at)]])]]
[:tbody [:p.px-2.opacity-50 [:small (str "Total: " (count pages))]]
(for [[n {:block/keys [name created-at updated-at backlinks] :as page}] (medley/indexed pages)]
[:tr {:key name}
[:td.n.w-12 [:span.opacity-70 (str (inc n) ".")]]
[:td.name [:a {:href (rfe/href :page {:name (:block/uuid page)})}
(component-block/page-cp {} page)]]
[:td.backlinks [:span (or backlinks "0")]]
(when-not orphaned-pages? [:td.created-at [:span (if created-at (date/int->local-time-2 created-at) "Unknown")]])
(when-not orphaned-pages? [:td.updated-at [:span (if updated-at (date/int->local-time-2 updated-at) "Unknown")]])])]]]
[:p.px-1.opacity-50 [:small (str "Total: " (count pages))]]
[:div.pt-6.flex.justify-end.gap-4 [:div.pt-6.flex.justify-end.gap-4
(ui/button (ui/button

View File

@ -215,8 +215,25 @@
(ui/icon "plus") (ui/icon "plus")
"New property")]) "New property")])
(rum/defc action-bar < rum/static
[table selected-rows {:keys [on-delete-rows]}]
(shui/table-actions
{}
(shui/button
{:variant "ghost"
:class "h-8 !pl-4 !px-2 !py-0 hover:text-foreground w-full justify-start"
:disabled true}
(str (count selected-rows) " selected"))
(when (fn? on-delete-rows)
(shui/button
{:variant "ghost"
:class "h-8 !pl-4 !px-2 !py-0 hover:text-foreground w-full justify-start"
:on-click (fn []
(on-delete-rows table selected-rows))}
(ui/icon "trash")))))
(defn- table-header (defn- table-header
[table columns {:keys [show-add-property? add-property!]}] [table columns {:keys [show-add-property? add-property!] :as option} selected-rows]
(let [set-ordered-columns! (get-in table [:data-fns :set-ordered-columns!]) (let [set-ordered-columns! (get-in table [:data-fns :set-ordered-columns!])
items (mapv (fn [column] items (mapv (fn [column]
{:id (:name column) {:id (:name column)
@ -241,11 +258,15 @@
:value :add-new-property :value :add-new-property
:content (add-property-button) :content (add-property-button)
:disabled? true}) :disabled? true})
items)] items)
selection-rows-count (count selected-rows)]
(shui/table-header (shui/table-header
(dnd/items items {:vertical? false (dnd/items items {:vertical? false
:on-drag-end (fn [ordered-columns _m] :on-drag-end (fn [ordered-columns _m]
(set-ordered-columns! ordered-columns))})))) (set-ordered-columns! ordered-columns))})
(when (pos? selection-rows-count)
[:div.absolute.top-0.left-8
(action-bar table selected-rows option)]))))
(rum/defc table-row < rum/reactive (rum/defc table-row < rum/reactive
[{:keys [row-selected?] :as table} row columns props {:keys [show-add-property?]}] [{:keys [row-selected?] :as table} row columns props {:keys [show-add-property?]}]
@ -887,9 +908,7 @@
:set-ordered-columns! set-ordered-columns! :set-ordered-columns! set-ordered-columns!
:set-row-selection! set-row-selection! :set-row-selection! set-row-selection!
:add-new-object! add-new-object!}}) :add-new-object! add-new-object!}})
;; selected-rows (shui/table-get-selection-rows row-selection (:rows table)) selected-rows (shui/table-get-selection-rows row-selection (:rows table))]
;; selected-rows-count (count selected-rows)
]
(rum/use-effect! (rum/use-effect!
(fn [] (debounced-set-row-filter! (fn [] (debounced-set-row-filter!
@ -921,7 +940,7 @@
rows (:rows table)] rows (:rows table)]
[:div.ls-table-rows.content.overflow-x-auto.force-visible-scrollbar [:div.ls-table-rows.content.overflow-x-auto.force-visible-scrollbar
[:div.relative [:div.relative
(table-header table columns' option) (table-header table columns' option selected-rows)
(ui/virtualized-list (ui/virtualized-list
{:custom-scroll-parent (gdom/getElement "main-content-container") {:custom-scroll-parent (gdom/getElement "main-content-container")

View File

@ -31,7 +31,8 @@
[blocks opts] [blocks opts]
(op-transact! (op-transact!
(let [ids (map :db/id blocks)] (let [ids (map :db/id blocks)]
[:delete-blocks [ids opts]]))) (when (seq ids)
[:delete-blocks [ids opts]]))))
(defn move-blocks! (defn move-blocks!
[blocks target-block sibling?] [blocks target-block sibling?]