mirror of https://github.com/logseq/logseq
refactor: blocks->vec-tree
parent
f6964065b6
commit
0099e2720d
|
@ -2205,7 +2205,7 @@
|
|||
sidebar? (:sidebar? config)
|
||||
ref? (:ref? config)
|
||||
custom-query? (:custom-query? config)
|
||||
blocks->vec-tree #(if (or custom-query? ref?) % (tree/blocks->vec-tree %))
|
||||
blocks->vec-tree #(if (or custom-query? ref?) % (tree/blocks->vec-tree % (:id config)))
|
||||
;; FIXME: blocks->vec-tree not working for the block container (zoom view)
|
||||
blocks' (blocks->vec-tree blocks)
|
||||
blocks (if (seq blocks') blocks' blocks)]
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
add-properties! block-and-children-transform blocks-count blocks-count-cache clean-export! cloned? delete-blocks
|
||||
delete-file! delete-file-blocks! delete-file-pages! delete-file-tx delete-files delete-pages-by-files
|
||||
filter-only-public-pages-and-blocks get-all-block-contents get-all-tagged-pages
|
||||
get-all-templates get-block-and-children get-block-by-uuid get-block-children
|
||||
get-all-templates get-block-and-children get-block-by-uuid get-block-children sort-by-left
|
||||
get-block-children-ids get-block-file get-block-immediate-children get-block-page
|
||||
get-block-page-end-pos get-block-parent get-block-parents get-block-referenced-blocks get-block-refs-count
|
||||
get-blocks-by-priority get-blocks-contents get-collapsed-blocks get-custom-css
|
||||
|
|
|
@ -612,18 +612,15 @@
|
|||
rules)
|
||||
(apply concat)))))
|
||||
|
||||
(defn- sort-by-left
|
||||
[blocks]
|
||||
(defn sort-by-left
|
||||
[blocks parent]
|
||||
(assert (= (count blocks) (count (set (map :block/left blocks)))) "Each block should have a different left node")
|
||||
(let [left->blocks (reduce (fn [acc b] (assoc acc (:db/id (:block/left b)) b)) {} blocks)
|
||||
start (get left->blocks nil)]
|
||||
(if start
|
||||
(loop [block start
|
||||
result [start]]
|
||||
(if-let [next (get left->blocks (:db/id block))]
|
||||
(recur next (conj result next))
|
||||
result))
|
||||
(throw "Can't find the start block when sort-by-left"))))
|
||||
(let [left->blocks (reduce (fn [acc b] (assoc acc (:db/id (:block/left b)) b)) {} blocks)]
|
||||
(loop [block parent
|
||||
result []]
|
||||
(if-let [next (get left->blocks (:db/id block))]
|
||||
(recur next (conj result next))
|
||||
(vec result)))))
|
||||
|
||||
(defn get-block-immediate-children
|
||||
"Doesn't include nested children."
|
||||
|
@ -637,7 +634,7 @@
|
|||
[?parent :block/uuid ?parent-id]]
|
||||
conn
|
||||
block-uuid)
|
||||
sort-by-left)))
|
||||
(sort-by-left (db-utils/entity [:block/uuid block-uuid])))))
|
||||
|
||||
(defn get-blocks-by-page
|
||||
[id-or-lookup-ref]
|
||||
|
@ -664,20 +661,20 @@
|
|||
([repo block-uuid]
|
||||
(get-block-and-children repo block-uuid true))
|
||||
([repo block-uuid use-cache?]
|
||||
(let [block (db-utils/entity repo [:block/uuid block-uuid])]
|
||||
(some-> (react/q repo [:block/block block-uuid]
|
||||
{:use-cache? use-cache?
|
||||
:transform-fn #(block-and-children-transform % repo block-uuid)}
|
||||
'[:find (pull ?c [*])
|
||||
:in $ ?id %
|
||||
:where
|
||||
[?b :block/uuid ?id]
|
||||
(or-join [?b ?c ?id]
|
||||
(parent ?b ?c)
|
||||
[?c :block/uuid ?id])]
|
||||
block-uuid
|
||||
rules)
|
||||
react))))
|
||||
(some-> (react/q repo [:block/block block-uuid]
|
||||
{:use-cache? use-cache?
|
||||
:transform-fn #(block-and-children-transform % repo block-uuid)}
|
||||
'[:find (pull ?c [*])
|
||||
:in $ ?id %
|
||||
:where
|
||||
[?b :block/uuid ?id]
|
||||
(or-join [?b ?c ?id]
|
||||
;; including the parent
|
||||
[?c :block/uuid ?id]
|
||||
(parent ?b ?c))]
|
||||
block-uuid
|
||||
rules)
|
||||
react)))
|
||||
|
||||
(defn get-file-page
|
||||
([file-path]
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
|
||||
(defn transform-content
|
||||
[pre-block? content level]
|
||||
(if pre-block?
|
||||
(clip-content content)
|
||||
(let [prefix (->>
|
||||
(let [content (or content "")]
|
||||
(if pre-block?
|
||||
(clip-content content)
|
||||
(let [prefix (->>
|
||||
(repeat level "#")
|
||||
(apply str))
|
||||
new-content (clip-content content)]
|
||||
(str prefix " " new-content))))
|
||||
new-content (clip-content content)]
|
||||
(str prefix " " new-content)))))
|
||||
|
||||
(defn tree->file-content
|
||||
[tree init-level]
|
||||
|
@ -61,4 +62,4 @@
|
|||
{old-content :file/content :as file} (model/get-file-by-path file-path)
|
||||
files [[file-path new-content]]
|
||||
file->content {file-path old-content}]
|
||||
(push-to-write-chan files file->content)))
|
||||
(push-to-write-chan files file->content)))
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
{:pre [(tree/satisfied-inode? updated-block)]}
|
||||
(let [page-db-id (-> updated-block :data :block/page :db/id)
|
||||
blocks (model/get-blocks-by-page page-db-id)
|
||||
tree (tree/blocks->vec-tree blocks)
|
||||
tree (tree/blocks->vec-tree blocks page-db-id)
|
||||
page-block (db-utils/pull page-db-id)]
|
||||
(file/save-tree page-block tree)))
|
||||
(file/save-tree page-block tree)))
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
(ns frontend.modules.outliner.ref)
|
||||
|
||||
(defn- get-all-refs
|
||||
[block]
|
||||
(let [refs (if-let [refs (seq (:block/refs-with-children block))]
|
||||
refs
|
||||
(:block/refs block))]
|
||||
(distinct refs)))
|
||||
|
||||
(defn- wrap-refs-with-children
|
||||
([block]
|
||||
(->> (get-all-refs block)
|
||||
(remove nil?)
|
||||
(assoc block :block/refs-with-children)))
|
||||
([block other-children]
|
||||
(->>
|
||||
(cons block other-children)
|
||||
(mapcat get-all-refs)
|
||||
(remove nil?)
|
||||
(distinct)
|
||||
(assoc block :block/refs-with-children))))
|
|
@ -1,8 +1,9 @@
|
|||
(ns frontend.modules.outliner.tree
|
||||
(:require [frontend.modules.outliner.ref :as outliner-ref]
|
||||
[clojure.set :as set]
|
||||
(:require [clojure.set :as set]
|
||||
[frontend.modules.outliner.utils :as outliner-u]
|
||||
[frontend.debug :as debug]))
|
||||
[frontend.debug :as debug]
|
||||
[frontend.util :as util]
|
||||
[frontend.db :as db]))
|
||||
|
||||
(defprotocol INode
|
||||
(-get-id [this])
|
||||
|
@ -24,60 +25,52 @@
|
|||
[node]
|
||||
(satisfies? INode node))
|
||||
|
||||
(defn- prepare-blocks
|
||||
"Preparing blocks: index blocks,filter ids,and update some keys."
|
||||
[blocks]
|
||||
(loop [[f & r] blocks
|
||||
ids #{}
|
||||
parents #{}
|
||||
;; {[parent left] db-id}
|
||||
indexed-by-position {}]
|
||||
(if (nil? f)
|
||||
{:ids ids :parents parents :indexed-by-position indexed-by-position}
|
||||
(let [f (cond-> f
|
||||
(not (:block/dummy? f))
|
||||
(dissoc f :block/meta))
|
||||
{:block/keys [parent left] db-id :db/id} f
|
||||
new-ids (conj ids db-id)
|
||||
new-parents (conj parents (outliner-u/->db-id parent))
|
||||
new-indexed-by-position
|
||||
(let [position (mapv outliner-u/->db-id [parent left])]
|
||||
(when (get indexed-by-position position)
|
||||
(throw (js/Error. "Two block occupy the same position")))
|
||||
(assoc indexed-by-position position f))]
|
||||
(recur r new-ids new-parents new-indexed-by-position)))))
|
||||
(defn- get-children
|
||||
[blocks parent]
|
||||
(let [children (doall
|
||||
(-> (filter #(= (:block/parent %) {:db/id (:db/id parent)}) @blocks)
|
||||
(db/sort-by-left parent)))]
|
||||
(reset! blocks (remove (set children) @blocks))
|
||||
children))
|
||||
|
||||
(defn get-children-from-memory
|
||||
[parent-id indexed-by-position]
|
||||
(loop [left parent-id
|
||||
children []]
|
||||
(if-let [{db-id :db/id :as child} (get indexed-by-position [parent-id left])]
|
||||
(recur db-id (conj children child))
|
||||
children)))
|
||||
(defn- with-children-and-refs
|
||||
[block children]
|
||||
(let [all-refs (->> (mapcat :block/refs children)
|
||||
(distinct))]
|
||||
(assoc block
|
||||
:block/children children
|
||||
:block/refs-with-children all-refs)))
|
||||
|
||||
(defn- clip-block
|
||||
"For debug. It's should be removed."
|
||||
[x]
|
||||
(let [ks [:block/parent :block/left :block/pre-block? :block/uuid
|
||||
:block/level :block/title :db/id :block/page]]
|
||||
(map #(select-keys % ks) x)))
|
||||
(defn- blocks->vec-tree-aux
|
||||
[blocks root]
|
||||
(some->>
|
||||
(get-children blocks root)
|
||||
(map (fn [block]
|
||||
(let [children (blocks->vec-tree-aux blocks block)]
|
||||
(with-children-and-refs block children))))))
|
||||
|
||||
(defn- get-root-and-page
|
||||
[root-id]
|
||||
(if (string? root-id)
|
||||
(if (util/uuid-string? root-id)
|
||||
[false (db/entity [:block/uuid (uuid root-id)])]
|
||||
[true (db/entity [:block/name root-id])])
|
||||
[false root-id]))
|
||||
|
||||
(defn blocks->vec-tree
|
||||
[blocks]
|
||||
;; (debug/pprint "blocks->vec-tree" blocks)
|
||||
(let [{:keys [ids parents indexed-by-position]}
|
||||
(prepare-blocks blocks)
|
||||
root-id (first (set/difference parents ids))]
|
||||
(letfn [(build-tree [root]
|
||||
(let [root (outliner-ref/wrap-refs-with-children root)
|
||||
children (->>
|
||||
(get-children-from-memory (:db/id root) indexed-by-position)
|
||||
(map build-tree))]
|
||||
(if (seq children)
|
||||
(->
|
||||
(assoc root :block/children children)
|
||||
(outliner-ref/wrap-refs-with-children children))
|
||||
root)))]
|
||||
(->>
|
||||
(get-children-from-memory root-id indexed-by-position)
|
||||
(map build-tree)))))
|
||||
[blocks root-id]
|
||||
(let [original-blocks blocks
|
||||
blocks (atom blocks)
|
||||
[page? root] (get-root-and-page root-id)
|
||||
result (blocks->vec-tree-aux blocks root)]
|
||||
(cond
|
||||
(not root) ; custom query
|
||||
original-blocks
|
||||
|
||||
page?
|
||||
result
|
||||
|
||||
:else ; include root block
|
||||
(let [root-block (some #(when (= (:db/id %) (:db/id root)) %) @blocks)
|
||||
root-block (with-children-and-refs root-block result)]
|
||||
[root-block]))))
|
||||
|
|
Loading…
Reference in New Issue