refactor: blocks->vec-tree

pull/1656/head
Tienson Qin 2021-04-05 19:16:02 +08:00
parent f6964065b6
commit 0099e2720d
7 changed files with 83 additions and 113 deletions

View File

@ -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)]

View File

@ -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

View File

@ -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]]
(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))
result))
(throw "Can't find the start block when sort-by-left"))))
(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,7 +661,6 @@
([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)}
@ -673,11 +669,12 @@
:where
[?b :block/uuid ?id]
(or-join [?b ?c ?id]
(parent ?b ?c)
[?c :block/uuid ?id])]
;; including the parent
[?c :block/uuid ?id]
(parent ?b ?c))]
block-uuid
rules)
react))))
react)))
(defn get-file-page
([file-path]

View File

@ -17,13 +17,14 @@
(defn transform-content
[pre-block? content level]
(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))))
(str prefix " " new-content)))))
(defn tree->file-content
[tree init-level]

View File

@ -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)))

View File

@ -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))))

View File

@ -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]))))