mirror of https://github.com/logseq/logseq
Use new tables for all pages
parent
5fa81817de
commit
d523948803
|
@ -106,11 +106,13 @@
|
||||||
prop)
|
prop)
|
||||||
children]))
|
children]))
|
||||||
|
|
||||||
|
;; FIXME: sticky header
|
||||||
(rum/defc table-header < rum/static
|
(rum/defc table-header < 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)]
|
||||||
[:div.flex.flex-row.items-center.w-fit
|
[:div.flex.flex-row.items-center.w-fit
|
||||||
(merge {:class "border-y transition-colors bg-gray-01"}
|
(merge {:class "border-y transition-colors bg-gray-01"
|
||||||
|
:style {:z-index 100}}
|
||||||
prop)
|
prop)
|
||||||
children]))
|
children]))
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,6 @@
|
||||||
(def table-option table-core/table-option)
|
(def table-option table-core/table-option)
|
||||||
(def table table-core/table)
|
(def table table-core/table)
|
||||||
(def table-header table-core/table-header)
|
(def table-header table-core/table-header)
|
||||||
(def table-head table-core/table-head)
|
|
||||||
(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-get-selection-rows table-core/get-selection-rows)
|
(def table-get-selection-rows table-core/get-selection-rows)
|
||||||
|
|
|
@ -1,230 +1,126 @@
|
||||||
(ns frontend.components.all-pages
|
(ns frontend.components.all-pages
|
||||||
"All pages"
|
"All pages"
|
||||||
(:require [logseq.shui.ui :as shui]
|
(:require [clojure.string :as string]
|
||||||
[rum.core :as rum]
|
|
||||||
[frontend.util :as util]
|
|
||||||
[frontend.ui :as ui]
|
|
||||||
[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.handler.page :as page-handler]
|
[frontend.handler.page :as page-handler]
|
||||||
[frontend.state :as state]
|
[frontend.state :as state]
|
||||||
[frontend.date :as date]
|
|
||||||
[goog.object :as gobj]
|
|
||||||
[goog.dom :as gdom]
|
|
||||||
[cljs-bean.core :as bean]
|
|
||||||
[promesa.core :as p]
|
|
||||||
[logseq.db :as ldb]
|
[logseq.db :as ldb]
|
||||||
[frontend.search.fuzzy :as fuzzy-search]))
|
[promesa.core :as p]
|
||||||
|
[rum.core :as rum]))
|
||||||
;; columns:
|
|
||||||
;; page name, tags, backlinks, created at updated at
|
|
||||||
;; default sort: updated at
|
|
||||||
|
|
||||||
(defn header-checkbox [{:keys [selected-all? selected-some? toggle-selected-all!]}]
|
|
||||||
(shui/checkbox
|
|
||||||
{:checked (or selected-all? (and selected-some? "indeterminate"))
|
|
||||||
:on-checked-change toggle-selected-all!
|
|
||||||
:aria-label "Select all"}))
|
|
||||||
|
|
||||||
(defn row-checkbox [{:keys [row-selected? row-toggle-selected!]} row _column]
|
|
||||||
(shui/checkbox
|
|
||||||
{:checked (row-selected? row)
|
|
||||||
:on-checked-change (fn [v] (row-toggle-selected! row v))
|
|
||||||
:aria-label "Select row"}))
|
|
||||||
|
|
||||||
(defn- header-cp
|
|
||||||
[{:keys [column-toggle-sorting! state]} column]
|
|
||||||
(let [sorting (:sorting state)
|
|
||||||
[asc?] (some (fn [item] (when (= (:id item) (:id column))
|
|
||||||
(when-some [asc? (:asc? item)]
|
|
||||||
[asc?]))) sorting)]
|
|
||||||
(shui/button
|
|
||||||
{:variant "text"
|
|
||||||
:class "!pl-0 hover:text-foreground"
|
|
||||||
:onClick #(column-toggle-sorting! column)}
|
|
||||||
(:name column)
|
|
||||||
(case asc?
|
|
||||||
true
|
|
||||||
(ui/icon "arrow-up")
|
|
||||||
false
|
|
||||||
(ui/icon "arrow-down")
|
|
||||||
nil))))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(defn- default-cell-cp
|
|
||||||
[_table row column]
|
|
||||||
(str (get row (:id column)))))
|
|
||||||
|
|
||||||
(defn- timestamp-cell-cp
|
|
||||||
[_table row column]
|
|
||||||
(some-> (get row (:id column))
|
|
||||||
date/int->local-time-2))
|
|
||||||
|
|
||||||
(def columns
|
(def columns
|
||||||
[{:id :select
|
[{:id :block/original-name
|
||||||
:name "Select"
|
|
||||||
:header (fn [table _column] (header-checkbox table))
|
|
||||||
:cell (fn [table row column] (row-checkbox table row column))
|
|
||||||
:column-list? false}
|
|
||||||
{:id :block/original-name
|
|
||||||
:name "Page name"
|
:name "Page name"
|
||||||
:header header-cp
|
|
||||||
:cell (fn [_table row _column]
|
:cell (fn [_table row _column]
|
||||||
(component-block/page-cp {} row))}
|
(component-block/page-cp {} row))
|
||||||
|
:type :string}
|
||||||
{:id :block/type
|
{:id :block/type
|
||||||
:name "Type"
|
:name "Type"
|
||||||
:header header-cp
|
|
||||||
:cell (fn [_table row _column] [:div.capitalize (string/join ", " (get row :block/type))])
|
:cell (fn [_table row _column] [:div.capitalize (string/join ", " (get row :block/type))])
|
||||||
:get-value (fn [row] (string/join ", " (get row :block/type)))}
|
:get-value (fn [row] (string/join ", " (get row :block/type)))
|
||||||
|
:type :string}
|
||||||
{:id :block/tags
|
{:id :block/tags
|
||||||
:name "Tags"
|
:name "Tags"}
|
||||||
:header header-cp
|
|
||||||
:cell (fn [_table row _column]
|
|
||||||
(component-block/tags {} row))
|
|
||||||
:get-value (fn [row] (string/join ", " (map :block/original-name (get row :block/tags))))}
|
|
||||||
{:id :block.temp/refs-count
|
{:id :block.temp/refs-count
|
||||||
:name "Backlinks"
|
:name "Backlinks"
|
||||||
:header header-cp
|
:cell (fn [_table row _column] (:block.temp/refs-count row))
|
||||||
:cell (fn [_table row _column] (:block.temp/refs-count row))}
|
:type :number}])
|
||||||
{:id :block/created-at
|
|
||||||
:name "Created At"
|
|
||||||
:header header-cp
|
|
||||||
:cell timestamp-cell-cp}
|
|
||||||
{:id :block/updated-at
|
|
||||||
:name "Updated At"
|
|
||||||
:header header-cp
|
|
||||||
:cell timestamp-cell-cp}])
|
|
||||||
(defn- get-all-pages
|
(defn- get-all-pages
|
||||||
[]
|
[]
|
||||||
(->> (page-handler/get-all-pages (state/get-current-repo))
|
(->> (page-handler/get-all-pages (state/get-current-repo))
|
||||||
(map (fn [p] (assoc p :id (:db/id p))))))
|
(map (fn [p] (assoc p :id (:db/id p))))))
|
||||||
|
|
||||||
(rum/defc columns-select
|
|
||||||
[columns {:keys [column-visible? column-toggle-visibility]}]
|
|
||||||
(shui/dropdown-menu
|
|
||||||
(shui/dropdown-menu-trigger
|
|
||||||
{:asChild true}
|
|
||||||
(shui/button
|
|
||||||
{:variant "outline" :size :sm
|
|
||||||
:class "text-muted-foreground"}
|
|
||||||
"Columns"
|
|
||||||
(ui/icon "chevron-down")))
|
|
||||||
(shui/dropdown-menu-content
|
|
||||||
{:align "end"}
|
|
||||||
(for [column (remove #(false? (:column-list? %)) columns)]
|
|
||||||
(shui/dropdown-menu-checkbox-item
|
|
||||||
{:key (str (:id column))
|
|
||||||
:className "capitalize"
|
|
||||||
:checked (column-visible? column)
|
|
||||||
:onCheckedChange #(column-toggle-visibility column %)}
|
|
||||||
(:name column))))))
|
|
||||||
|
|
||||||
(defn table-header
|
|
||||||
[table columns]
|
|
||||||
(shui/table-row
|
|
||||||
{:class "bg-gray-01 shadow"}
|
|
||||||
(for [column columns]
|
|
||||||
(let [style (case (:id column)
|
|
||||||
:block/original-name
|
|
||||||
{}
|
|
||||||
:select
|
|
||||||
{:width 32}
|
|
||||||
{:width 180})]
|
|
||||||
(shui/table-head
|
|
||||||
{:key (str (:id column))
|
|
||||||
:style style}
|
|
||||||
(let [header-fn (:header column)]
|
|
||||||
(if (fn? header-fn)
|
|
||||||
(header-fn table column)
|
|
||||||
header-fn)))))))
|
|
||||||
|
|
||||||
(defn table-row
|
|
||||||
[{:keys [row-selected?] :as table} rows columns props]
|
|
||||||
(let [idx (gobj/get props "data-index")
|
|
||||||
row (nth rows idx)]
|
|
||||||
(shui/table-row
|
|
||||||
(merge
|
|
||||||
(bean/->clj props)
|
|
||||||
{: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)]
|
|
||||||
(shui/table-cell
|
|
||||||
{:key id}
|
|
||||||
(render table row column)))))))
|
|
||||||
|
|
||||||
(rum/defc all-pages < rum/static
|
(rum/defc all-pages < rum/static
|
||||||
[]
|
[]
|
||||||
(let [[input set-input!] (rum/use-state "")
|
(let [[data set-data!] (rum/use-state (get-all-pages))
|
||||||
[sorting set-sorting!] (rum/use-state [{:id :block/updated-at, :asc? false}])
|
columns (views/build-columns {} columns
|
||||||
[row-filter set-row-filter!] (rum/use-state nil)
|
{:with-object-name? false})]
|
||||||
[visible-columns set-visible-columns!] (rum/use-state {:block/type false})
|
(rum/use-effect!
|
||||||
[row-selection set-row-selection!] (rum/use-state {})
|
(fn []
|
||||||
[data set-data!] (rum/use-state (get-all-pages))
|
(when-let [^js worker @state/*db-worker]
|
||||||
_ (rum/use-effect!
|
(p/let [result-str (.get-page-refs-count worker (state/get-current-repo))
|
||||||
(fn []
|
result (ldb/read-transit-str result-str)
|
||||||
(when-let [^js worker @state/*db-worker]
|
data (map (fn [row] (assoc row :block.temp/refs-count (get result (:db/id row) 0))) data)]
|
||||||
(p/let [result-str (.get-page-refs-count worker (state/get-current-repo))
|
(set-data! data))))
|
||||||
result (ldb/read-transit-str result-str)
|
[])
|
||||||
data (map (fn [row] (assoc row :block.temp/refs-count (get result (:db/id row) 0))) data)]
|
[:div.ls-all-pages.max-w-fit.m-auto
|
||||||
(set-data! data))))
|
(views/view nil {:data data
|
||||||
[])
|
:set-data! set-data!
|
||||||
table (shui/table-option {:data data
|
:columns columns})]))
|
||||||
:columns columns
|
|
||||||
:state {:sorting sorting
|
(comment
|
||||||
:row-filter row-filter
|
(rum/defc all-pages < rum/static
|
||||||
:row-selection row-selection
|
[]
|
||||||
:visible-columns visible-columns}
|
(let [[input set-input!] (rum/use-state "")
|
||||||
:data-fns {:set-sorting! set-sorting!
|
[sorting set-sorting!] (rum/use-state [{:id :block/updated-at, :asc? false}])
|
||||||
:set-visible-columns! set-visible-columns!
|
[row-filter set-row-filter!] (rum/use-state nil)
|
||||||
:set-row-selection! set-row-selection!}})
|
[visible-columns set-visible-columns!] (rum/use-state {:block/type false})
|
||||||
selected-rows (shui/table-get-selection-rows row-selection (:rows table))
|
[row-selection set-row-selection!] (rum/use-state {})
|
||||||
selected-rows-count (count selected-rows)
|
[data set-data!] (rum/use-state (get-all-pages))
|
||||||
selected? (pos? selected-rows-count)]
|
_ (rum/use-effect!
|
||||||
[:div.w-full
|
(fn []
|
||||||
[:div.flex.items-center.pb-4.justify-between
|
(when-let [^js worker @state/*db-worker]
|
||||||
[:div.ml-1
|
(p/let [result-str (.get-page-refs-count worker (state/get-current-repo))
|
||||||
(when selected?
|
result (ldb/read-transit-str result-str)
|
||||||
(shui/button {:variant :destructive
|
data (map (fn [row] (assoc row :block.temp/refs-count (get result (:db/id row) 0))) data)]
|
||||||
:class "text-red-500"
|
(set-data! data))))
|
||||||
:size :sm
|
[])
|
||||||
:on-click #(shui/dialog-open!
|
table (shui/table-option {:data data
|
||||||
(component-page/batch-delete-dialog selected-rows false (fn [] (set-data! (get-all-pages)))))}
|
:columns columns
|
||||||
(ui/icon "trash-x")))]
|
:state {:sorting sorting
|
||||||
[:div.flex.items-center.gap-2
|
:row-filter row-filter
|
||||||
(shui/input
|
:row-selection row-selection
|
||||||
{:placeholder "Search pages"
|
:visible-columns visible-columns}
|
||||||
:value input
|
:data-fns {:set-sorting! set-sorting!
|
||||||
:onChange (fn [e]
|
:set-visible-columns! set-visible-columns!
|
||||||
(let [value (util/evalue e)]
|
:set-row-selection! set-row-selection!}})
|
||||||
(set-input! value)
|
selected-rows (shui/table-get-selection-rows row-selection (:rows table))
|
||||||
(set-row-filter! (fn []
|
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.
|
;; Returns a fn here.
|
||||||
;; https://stackoverflow.com/questions/55621212/is-it-possible-to-react-usestate-in-react
|
;; https://stackoverflow.com/questions/55621212/is-it-possible-to-react-usestate-in-react
|
||||||
(fn [row]
|
(fn [row]
|
||||||
(if (string/blank? value)
|
(if (string/blank? value)
|
||||||
true
|
true
|
||||||
(when row
|
(when row
|
||||||
(pos? (fuzzy-search/score (string/lower-case value) (:block/name row))))))))))
|
(pos? (fuzzy-search/score (string/lower-case value) (:block/name row))))))))))
|
||||||
:class "max-w-sm !h-7 !py-0"})
|
:class "max-w-sm !h-7 !py-0"})
|
||||||
(columns-select columns table)]]
|
(columns-select columns table)]]
|
||||||
(let [columns' (:columns table)
|
(let [columns' (:columns table)
|
||||||
rows (:rows table)]
|
rows (:rows table)]
|
||||||
[:div.rounded-md.border
|
[:div.rounded-md.border
|
||||||
(ui/virtualized-table
|
(ui/virtualized-table
|
||||||
{:custom-scroll-parent (gdom/getElement "main-content-container")
|
{:custom-scroll-parent (gdom/getElement "main-content-container")
|
||||||
:total-count (count rows)
|
:total-count (count rows)
|
||||||
:fixedHeaderContent (fn [] (table-header table columns'))
|
:fixedHeaderContent (fn [] (table-header table columns'))
|
||||||
:components {:Table (fn [props]
|
:components {:Table (fn [props]
|
||||||
(shui/table {}
|
(shui/table {}
|
||||||
(.-children props)))
|
(.-children props)))
|
||||||
:TableRow (fn [props] (table-row table rows columns' props))}})])
|
:TableRow (fn [props] (table-row table rows columns' props))}})])
|
||||||
|
|
||||||
(let [rows-count (count (:rows table))]
|
(let [rows-count (count (:rows table))]
|
||||||
[:div.flex.items-center.justify-end.space-x-2.py-4
|
[:div.flex.items-center.justify-end.space-x-2.py-4
|
||||||
[:div.flex-1.text-sm.text-muted-foreground
|
[:div.flex-1.text-sm.text-muted-foreground
|
||||||
(if (pos? selected-rows-count)
|
(if (pos? selected-rows-count)
|
||||||
(str selected-rows-count " of " rows-count " row(s) selected.")
|
(str selected-rows-count " of " rows-count " row(s) selected.")
|
||||||
(str "Total: " rows-count))]])]))
|
(str "Total: " rows-count))]])])))
|
||||||
|
|
|
@ -75,10 +75,10 @@
|
||||||
(cond
|
(cond
|
||||||
(uuid? entity)
|
(uuid? entity)
|
||||||
(db-property/property-value-content (db/entity [:block/uuid entity]))
|
(db-property/property-value-content (db/entity [:block/uuid entity]))
|
||||||
(map? entity)
|
(de/entity? entity)
|
||||||
(db-property/property-value-content entity)
|
(db-property/property-value-content entity)
|
||||||
:else
|
:else
|
||||||
(str entity))))
|
entity)))
|
||||||
|
|
||||||
(defn- get-property-value-for-search
|
(defn- get-property-value-for-search
|
||||||
[block property]
|
[block property]
|
||||||
|
@ -95,42 +95,56 @@
|
||||||
(string/join ", " col))))
|
(string/join ", " col))))
|
||||||
|
|
||||||
(defn build-columns
|
(defn build-columns
|
||||||
[config properties]
|
[config properties & {:keys [with-object-name?]
|
||||||
|
:or {with-object-name? true}}]
|
||||||
(let [container-id (state/get-next-container-id)]
|
(let [container-id (state/get-next-container-id)]
|
||||||
(concat
|
(->> (concat
|
||||||
[{:id :select
|
[{:id :select
|
||||||
:name "Select"
|
:name "Select"
|
||||||
:header (fn [table _column] (header-checkbox table))
|
:header (fn [table _column] (header-checkbox table))
|
||||||
:cell (fn [table row column]
|
:cell (fn [table row column]
|
||||||
(row-checkbox table row column))
|
(row-checkbox table row column))
|
||||||
:column-list? false}
|
:column-list? false}
|
||||||
{:id :object/name
|
(when with-object-name?
|
||||||
:name "Name"
|
{:id :object/name
|
||||||
:type :string
|
:name "Name"
|
||||||
:header header-cp
|
:type :string
|
||||||
:cell (fn [_table row _column]
|
:header header-cp
|
||||||
(component-block/block-container (assoc config :table? true) row))
|
:cell (fn [_table row _column]
|
||||||
:disable-hide? true}]
|
(component-block/block-container (assoc config :table? true) row))
|
||||||
(map
|
:disable-hide? true})]
|
||||||
(fn [property]
|
(map
|
||||||
{:id (:db/ident property)
|
(fn [property]
|
||||||
:name (:block/original-name property)
|
(let [ident (or (:id property) (:db/ident property))
|
||||||
:header header-cp
|
property (if (de/entity? property)
|
||||||
:cell (fn [_table row _column]
|
property
|
||||||
(pv/property-value row property (get row (:db/ident property)) {:container-id container-id}))
|
(or (db/entity ident) property))]
|
||||||
:get-value (fn [row] (get-property-value-for-search row property))})
|
{:id ident
|
||||||
properties)
|
:name (or (:name property)
|
||||||
|
(:block/original-name property))
|
||||||
|
:header (or (:header property)
|
||||||
|
header-cp)
|
||||||
|
:cell (or (:cell property)
|
||||||
|
(when (de/entity? property)
|
||||||
|
(fn [_table row _column]
|
||||||
|
(pv/property-value row property (get row (:db/ident property)) {:container-id container-id}))))
|
||||||
|
:get-value (or (:get-value property)
|
||||||
|
(when (de/entity? property)
|
||||||
|
(fn [row] (get-property-value-for-search row property))))
|
||||||
|
:type (:type property)}))
|
||||||
|
properties)
|
||||||
|
|
||||||
[{:id :block/created-at
|
[{:id :block/created-at
|
||||||
:name "Created At"
|
:name "Created At"
|
||||||
:type :date-time
|
:type :date-time
|
||||||
:header header-cp
|
:header header-cp
|
||||||
:cell timestamp-cell-cp}
|
:cell timestamp-cell-cp}
|
||||||
{:id :block/updated-at
|
{:id :block/updated-at
|
||||||
:name "Updated At"
|
:name "Updated At"
|
||||||
:type :date-time
|
:type :date-time
|
||||||
:header header-cp
|
:header header-cp
|
||||||
:cell timestamp-cell-cp}])))
|
:cell timestamp-cell-cp}])
|
||||||
|
(remove nil?))))
|
||||||
|
|
||||||
(defn- sort-columns
|
(defn- sort-columns
|
||||||
[columns ordered-column-ids]
|
[columns ordered-column-ids]
|
||||||
|
@ -177,7 +191,7 @@
|
||||||
[column]
|
[column]
|
||||||
(case (:id column)
|
(case (:id column)
|
||||||
:select 32
|
:select 32
|
||||||
:object/name 360
|
(:object/name :block/original-name :block/name :block/content) 360
|
||||||
(:block/created-at :block/updated-at) 160
|
(:block/created-at :block/updated-at) 160
|
||||||
180))
|
180))
|
||||||
|
|
||||||
|
@ -204,8 +218,9 @@
|
||||||
[{:keys [row-selected?] :as table} rows columns props]
|
[{:keys [row-selected?] :as table} rows columns props]
|
||||||
(let [idx (gobj/get props "data-index")
|
(let [idx (gobj/get props "data-index")
|
||||||
row (nth rows idx)
|
row (nth rows idx)
|
||||||
row (db/sub-block (:id row))
|
row' (db/sub-block (:id row))
|
||||||
row (assoc row :id (:db/id row))]
|
;; merge entity temporal attributes
|
||||||
|
row (reduce (fn [e [k v]] (assoc e k v)) row' (.-kv ^js row))]
|
||||||
(shui/table-row
|
(shui/table-row
|
||||||
(merge
|
(merge
|
||||||
(bean/->clj props)
|
(bean/->clj props)
|
||||||
|
@ -312,6 +327,7 @@
|
||||||
(rum/defc filter-property < rum/static
|
(rum/defc filter-property < rum/static
|
||||||
[columns {:keys [data-fns] :as table}]
|
[columns {:keys [data-fns] :as table}]
|
||||||
(let [[property set-property!] (rum/use-state nil)
|
(let [[property set-property!] (rum/use-state nil)
|
||||||
|
schema (:schema (db/get-db))
|
||||||
timestamp? (timestamp-property? (:db/ident property))
|
timestamp? (timestamp-property? (:db/ident property))
|
||||||
set-filters! (:set-filters! data-fns)
|
set-filters! (:set-filters! data-fns)
|
||||||
filters (get-in table [:state :filters])
|
filters (get-in table [:state :filters])
|
||||||
|
@ -328,8 +344,11 @@
|
||||||
(let [id (:id column)
|
(let [id (:id column)
|
||||||
property (db/entity id)
|
property (db/entity id)
|
||||||
internal-property {:db/ident (:id column)
|
internal-property {:db/ident (:id column)
|
||||||
:block/original-name (:name column)}]
|
:block/original-name (:name column)
|
||||||
(if (or property (timestamp-property? id))
|
:block/schema {:type (:type column)}}]
|
||||||
|
(if (or property
|
||||||
|
(= :db.cardinality/many (:db/cardinality (get schema id)))
|
||||||
|
(not= (:type column) :string))
|
||||||
(set-property! (or property internal-property))
|
(set-property! (or property internal-property))
|
||||||
(do
|
(do
|
||||||
(shui/popup-hide!)
|
(shui/popup-hide!)
|
||||||
|
@ -364,8 +383,11 @@
|
||||||
:input-default-placeholder (if property (:block/original-name property) "Select")
|
:input-default-placeholder (if property (:block/original-name property) "Select")
|
||||||
:multiple-choices? true
|
:multiple-choices? true
|
||||||
:on-chosen (fn [_value _selected? selected]
|
:on-chosen (fn [_value _selected? selected]
|
||||||
(let [filters' (if (seq selected)
|
(let [selected-value (if (de/entity? (first selected))
|
||||||
(conj filters [(:db/ident property) :is selected])
|
(set (map :block/uuid selected))
|
||||||
|
selected)
|
||||||
|
filters' (if (seq selected)
|
||||||
|
(conj filters [(:db/ident property) :is selected-value])
|
||||||
filters)]
|
filters)]
|
||||||
(set-filters! filters')))})))
|
(set-filters! filters')))})))
|
||||||
:else
|
:else
|
||||||
|
@ -598,7 +620,7 @@
|
||||||
(filter-value-select table property value operator idx))))
|
(filter-value-select table property value operator idx))))
|
||||||
|
|
||||||
(rum/defc filters-row < rum/static
|
(rum/defc filters-row < rum/static
|
||||||
[{:keys [data-fns] :as table}]
|
[{:keys [data-fns columns] :as table}]
|
||||||
(let [filters (get-in table [:state :filters])
|
(let [filters (get-in table [:state :filters])
|
||||||
{:keys [set-filters!]} data-fns]
|
{:keys [set-filters!]} data-fns]
|
||||||
(when (seq filters)
|
(when (seq filters)
|
||||||
|
@ -609,7 +631,10 @@
|
||||||
property (if (= property-ident :object/name)
|
property (if (= property-ident :object/name)
|
||||||
{:db/ident property-ident
|
{:db/ident property-ident
|
||||||
:block/original-name "Name"}
|
:block/original-name "Name"}
|
||||||
(db/entity property-ident))]
|
(or (db/entity property-ident)
|
||||||
|
(some (fn [column] (when (= (:id column) property-ident)
|
||||||
|
{:db/ident (:id column)
|
||||||
|
:block/original-name (:name column)})) columns)))]
|
||||||
[:div.flex.flex-row.items-center.border.rounded
|
[:div.flex.flex-row.items-center.border.rounded
|
||||||
(shui/button
|
(shui/button
|
||||||
{:class "!px-2 rounded-none border-r"
|
{:class "!px-2 rounded-none border-r"
|
||||||
|
@ -650,26 +675,30 @@
|
||||||
(set? value) value
|
(set? value) value
|
||||||
(nil? value) #{}
|
(nil? value) #{}
|
||||||
:else #{value})
|
:else #{value})
|
||||||
|
entity? (de/entity? (first value'))
|
||||||
result
|
result
|
||||||
(case operator
|
(case operator
|
||||||
:is
|
:is
|
||||||
(if (boolean? match)
|
(if (boolean? match)
|
||||||
(= (boolean (get-property-value-content (get row property-ident))) match)
|
(= (boolean (get-property-value-content (get row property-ident))) match)
|
||||||
(if (and (empty? match) (empty? value))
|
(if (and (empty? match) (empty? value'))
|
||||||
true
|
true
|
||||||
(when (coll? value)
|
(if entity?
|
||||||
(boolean (seq (set/intersection (set (map :block/uuid value')) match))))))
|
(boolean (seq (set/intersection (set (map :block/uuid value')) match)))
|
||||||
|
(boolean (seq (set/intersection (set value') match))))))
|
||||||
|
|
||||||
:is-not
|
:is-not
|
||||||
(if (boolean? match)
|
(if (boolean? match)
|
||||||
(not= (boolean (get-property-value-content (get row property-ident))) match)
|
(not= (boolean (get-property-value-content (get row property-ident))) match)
|
||||||
(cond
|
(cond
|
||||||
(and (empty? match) (seq value))
|
(and (empty? match) (seq value'))
|
||||||
true
|
true
|
||||||
(and (seq match) (empty? value))
|
(and (seq match) (empty? value'))
|
||||||
true
|
true
|
||||||
(coll? value)
|
:else
|
||||||
(boolean (empty? (set/intersection (set (map :block/uuid value')) match)))))
|
(if entity?
|
||||||
|
(boolean (empty? (set/intersection (set (map :block/uuid value')) match)))
|
||||||
|
(boolean (empty? (set/intersection (set value') match))))))
|
||||||
|
|
||||||
:text-contains
|
:text-contains
|
||||||
(some #(fuzzy-matched? match (get-property-value-content %)) value')
|
(some #(fuzzy-matched? match (get-property-value-content %)) value')
|
||||||
|
@ -751,29 +780,31 @@
|
||||||
filters))
|
filters))
|
||||||
|
|
||||||
(defn- db-set-table-state!
|
(defn- db-set-table-state!
|
||||||
[entity {:keys [set-sorting! set-filters! set-visible-columns! set-ordered-columns!]}]
|
[entity {:keys [set-sorting! set-filters! set-visible-columns! set-ordered-columns!] :as option}]
|
||||||
(let [repo (state/get-current-repo)]
|
(if entity
|
||||||
{:set-sorting!
|
(let [repo (state/get-current-repo)]
|
||||||
(fn [sorting]
|
{:set-sorting!
|
||||||
(set-sorting! sorting)
|
(fn [sorting]
|
||||||
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-sorting sorting))
|
(set-sorting! sorting)
|
||||||
:set-filters!
|
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-sorting sorting))
|
||||||
(fn [filters]
|
:set-filters!
|
||||||
(let [filters (table-filters->persist-state filters)]
|
(fn [filters]
|
||||||
(set-filters! filters)
|
(let [filters (table-filters->persist-state filters)]
|
||||||
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-filters filters)))
|
(set-filters! filters)
|
||||||
:set-visible-columns!
|
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-filters filters)))
|
||||||
(fn [columns]
|
:set-visible-columns!
|
||||||
(let [hidden-columns (vec (keep (fn [[column visible?]]
|
(fn [columns]
|
||||||
(when (false? visible?)
|
(let [hidden-columns (vec (keep (fn [[column visible?]]
|
||||||
column)) columns))]
|
(when (false? visible?)
|
||||||
(set-visible-columns! columns)
|
column)) columns))]
|
||||||
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-hidden-columns hidden-columns)))
|
(set-visible-columns! columns)
|
||||||
:set-ordered-columns!
|
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-hidden-columns hidden-columns)))
|
||||||
(fn [ordered-columns]
|
:set-ordered-columns!
|
||||||
(let [ids (vec (remove #{:select} ordered-columns))]
|
(fn [ordered-columns]
|
||||||
(set-ordered-columns! ordered-columns)
|
(let [ids (vec (remove #{:select} ordered-columns))]
|
||||||
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-ordered-columns ids)))}))
|
(set-ordered-columns! ordered-columns)
|
||||||
|
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-ordered-columns ids)))})
|
||||||
|
option))
|
||||||
|
|
||||||
(rum/defc view < rum/static
|
(rum/defc view < rum/static
|
||||||
[view-entity {:keys [data set-data! columns add-new-object!]}]
|
[view-entity {:keys [data set-data! columns add-new-object!]}]
|
||||||
|
@ -841,13 +872,14 @@
|
||||||
(let [columns' (:columns table)
|
(let [columns' (:columns table)
|
||||||
rows (:rows table)]
|
rows (:rows table)]
|
||||||
[:div.ls-table-rows.rounded-md.content.overflow-x-auto.force-visible-scrollbar
|
[:div.ls-table-rows.rounded-md.content.overflow-x-auto.force-visible-scrollbar
|
||||||
(table-header table columns')
|
[:div.relative
|
||||||
|
(table-header table columns')
|
||||||
|
|
||||||
(ui/virtualized-table
|
(ui/virtualized-table
|
||||||
{:custom-scroll-parent (gdom/getElement "main-content-container")
|
{:custom-scroll-parent (gdom/getElement "main-content-container")
|
||||||
:total-count (count rows)
|
:total-count (count rows)
|
||||||
:components {:Table (fn [props]
|
:components {:Table (fn [props]
|
||||||
(shui/table {}
|
(shui/table {}
|
||||||
(.-children props)))
|
(.-children props)))
|
||||||
:TableRow (fn [props] (table-row table rows columns' props))}})
|
:TableRow (fn [props] (table-row table rows columns' props))}})
|
||||||
(when add-new-object! (add-new-row table))])]))
|
(when add-new-object! (add-new-row table))]])]))
|
||||||
|
|
Loading…
Reference in New Issue