mirror of https://github.com/logseq/logseq
enhance: add table action bar
parent
b273df3e76
commit
374f43e0c4
|
@ -236,13 +236,6 @@
|
|||
prop)
|
||||
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
|
||||
[& prop-and-children]
|
||||
(let [[prop children] (get-prop-and-children prop-and-children)]
|
||||
|
@ -256,3 +249,15 @@
|
|||
:else
|
||||
" border-r px-2"))}
|
||||
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]))
|
||||
|
|
|
@ -134,4 +134,5 @@
|
|||
(def table-footer table-core/table-footer)
|
||||
(def table-row table-core/table-row)
|
||||
(def table-cell table-core/table-cell)
|
||||
(def table-actions table-core/table-actions)
|
||||
(def table-get-selection-rows table-core/get-selection-rows)
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
"All pages"
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.components.block :as component-block]
|
||||
[frontend.components.page :as component-page]
|
||||
[frontend.components.views :as views]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.state :as state]
|
||||
[logseq.db :as ldb]
|
||||
[frontend.db :as db]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]))
|
||||
[rum.core :as rum]
|
||||
[logseq.shui.ui :as shui]))
|
||||
|
||||
(defn- columns
|
||||
[db]
|
||||
|
@ -56,79 +58,12 @@
|
|||
[:div.ls-all-pages.w-full
|
||||
(views/view view-entity {:data 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
|
||||
: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!}})
|
||||
selected-rows (shui/table-get-selection-rows row-selection (:rows table))
|
||||
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))]])])))
|
||||
:columns columns
|
||||
:on-delete-rows (fn [table selected-rows]
|
||||
(shui/dialog-open!
|
||||
(component-page/batch-delete-dialog
|
||||
selected-rows false
|
||||
(fn []
|
||||
(when-let [f (get-in table [:data-fns :set-row-selection!])]
|
||||
(f {}))
|
||||
(set-data! (get-all-pages))))))})]))
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
[frontend.state :as state]
|
||||
[logseq.outliner.property :as outliner-property]
|
||||
[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
|
||||
[class]
|
||||
|
@ -69,7 +71,22 @@
|
|||
:add-property! (fn []
|
||||
(state/pub-event! [:editor/new-property {:block class
|
||||
: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
|
||||
[state class]
|
||||
|
|
|
@ -1031,47 +1031,33 @@
|
|||
(t :remove-orphaned-pages)
|
||||
(t :page/delete-confirmation))]]]
|
||||
|
||||
[:div.cp__all_pages_table-wrap
|
||||
[:table.w-full.cp__all_pages_table.mt-4
|
||||
[:thead
|
||||
[:tr.opacity-70
|
||||
[:th [:span "#"]]
|
||||
[: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)]])]]
|
||||
[:ol.p-2.pt-4
|
||||
(for [page pages]
|
||||
[:li
|
||||
[:a {:href (rfe/href :page {:name (:block/uuid page)})}
|
||||
(component-block/page-cp {} page)]])]
|
||||
|
||||
[:tbody
|
||||
(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))]]
|
||||
[:p.px-2.opacity-50 [:small (str "Total: " (count pages))]]
|
||||
|
||||
[:div.pt-6.flex.justify-end.gap-4
|
||||
(ui/button
|
||||
(t :cancel)
|
||||
:variant :outline
|
||||
:on-click close)
|
||||
(t :cancel)
|
||||
:variant :outline
|
||||
:on-click close)
|
||||
|
||||
(ui/button
|
||||
(t :yes)
|
||||
:on-click (fn []
|
||||
(close)
|
||||
(let [failed-pages (atom [])]
|
||||
(p/let [_ (p/all (map (fn [page]
|
||||
(page-handler/<delete! (:block/uuid page) nil
|
||||
{:error-handler
|
||||
(fn []
|
||||
(swap! failed-pages conj (:block/name page)))}))
|
||||
pages))]
|
||||
(if (seq @failed-pages)
|
||||
(notification/show! (t :all-pages/failed-to-delete-pages (string/join ", " (map pr-str @failed-pages)))
|
||||
:warning false)
|
||||
(notification/show! (t :tips/all-done) :success))))
|
||||
(js/setTimeout #(refresh-fn) 200)))]]))
|
||||
(t :yes)
|
||||
:on-click (fn []
|
||||
(close)
|
||||
(let [failed-pages (atom [])]
|
||||
(p/let [_ (p/all (map (fn [page]
|
||||
(page-handler/<delete! (:block/uuid page) nil
|
||||
{:error-handler
|
||||
(fn []
|
||||
(swap! failed-pages conj (:block/name page)))}))
|
||||
pages))]
|
||||
(if (seq @failed-pages)
|
||||
(notification/show! (t :all-pages/failed-to-delete-pages (string/join ", " (map pr-str @failed-pages)))
|
||||
:warning false)
|
||||
(notification/show! (t :tips/all-done) :success))))
|
||||
(js/setTimeout #(refresh-fn) 200)))]]))
|
||||
|
|
|
@ -215,8 +215,25 @@
|
|||
(ui/icon "plus")
|
||||
"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
|
||||
[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!])
|
||||
items (mapv (fn [column]
|
||||
{:id (:name column)
|
||||
|
@ -241,11 +258,15 @@
|
|||
:value :add-new-property
|
||||
:content (add-property-button)
|
||||
:disabled? true})
|
||||
items)]
|
||||
items)
|
||||
selection-rows-count (count selected-rows)]
|
||||
(shui/table-header
|
||||
(dnd/items items {:vertical? false
|
||||
: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
|
||||
[{:keys [row-selected?] :as table} row columns props {:keys [show-add-property?]}]
|
||||
|
@ -887,9 +908,7 @@
|
|||
:set-ordered-columns! set-ordered-columns!
|
||||
:set-row-selection! set-row-selection!
|
||||
:add-new-object! add-new-object!}})
|
||||
;; selected-rows (shui/table-get-selection-rows row-selection (:rows table))
|
||||
;; selected-rows-count (count selected-rows)
|
||||
]
|
||||
selected-rows (shui/table-get-selection-rows row-selection (:rows table))]
|
||||
|
||||
(rum/use-effect!
|
||||
(fn [] (debounced-set-row-filter!
|
||||
|
@ -921,7 +940,7 @@
|
|||
rows (:rows table)]
|
||||
[:div.ls-table-rows.content.overflow-x-auto.force-visible-scrollbar
|
||||
[:div.relative
|
||||
(table-header table columns' option)
|
||||
(table-header table columns' option selected-rows)
|
||||
|
||||
(ui/virtualized-list
|
||||
{:custom-scroll-parent (gdom/getElement "main-content-container")
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
[blocks opts]
|
||||
(op-transact!
|
||||
(let [ids (map :db/id blocks)]
|
||||
[:delete-blocks [ids opts]])))
|
||||
(when (seq ids)
|
||||
[:delete-blocks [ids opts]]))))
|
||||
|
||||
(defn move-blocks!
|
||||
[blocks target-block sibling?]
|
||||
|
|
Loading…
Reference in New Issue