model.cljs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. (ns frontend.db.file-based.model
  2. "Core db functions for file graphs"
  3. (:require [clojure.string :as string]
  4. [datascript.core :as d]
  5. [frontend.common.file-based.db :as common-file-db]
  6. [frontend.db.conn :as conn]
  7. [frontend.db.utils :as db-utils]
  8. [frontend.state :as state]
  9. [frontend.util :as util]
  10. [logseq.db :as ldb]
  11. [logseq.graph-parser.db :as gp-db]))
  12. (def file-graph-block-attrs
  13. "In file graphs, use it to replace '*' for datalog queries"
  14. '[:db/id
  15. :block/uuid
  16. :block/parent
  17. :block/order
  18. :block/collapsed?
  19. :block/format
  20. :block/refs
  21. :block/_refs
  22. :block/path-refs
  23. :block/tags
  24. :block/link
  25. :block/title
  26. :block/marker
  27. :block/priority
  28. :block/properties
  29. :block/properties-order
  30. :block/properties-text-values
  31. :block/pre-block?
  32. :block/scheduled
  33. :block/deadline
  34. :block/repeated?
  35. :block/created-at
  36. :block/updated-at
  37. ;; TODO: remove this in later releases
  38. :block/heading-level
  39. :block/file
  40. {:block/page [:db/id :block/name :block/title :block/uuid :block/journal-day :block/type]}
  41. {:block/_parent ...}])
  42. ;; File-based only
  43. ;; Diverged of get-sorted-page-block-ids
  44. (defn get-sorted-page-block-ids-and-levels
  45. "page-name: the page name, original name
  46. return: a list with elements in:
  47. :id - a list of block ids, sorted by :block/order
  48. :level - the level of the block, 1 for root, 2 for children of root, etc."
  49. [page-name]
  50. {:pre [(string? page-name)]}
  51. (let [root (ldb/get-page (conn/get-db) page-name)]
  52. (loop [result []
  53. children (ldb/sort-by-order (:block/_parent root))
  54. ;; BFS log of walking depth
  55. levels (repeat (count children) 1)]
  56. (if (seq children)
  57. (let [child (first children)
  58. cur-level (first levels)
  59. next-children (ldb/sort-by-order (:block/_parent child))]
  60. (recur (conj result {:id (:db/id child) :level cur-level})
  61. (concat
  62. next-children
  63. (rest children))
  64. (concat
  65. (repeat (count next-children) (inc cur-level))
  66. (rest levels))))
  67. result))))
  68. (defn get-page-file
  69. ([page-name]
  70. (get-page-file (state/get-current-repo) page-name))
  71. ([repo page-name]
  72. (when-let [db (conn/get-db repo)]
  73. (gp-db/get-page-file db page-name))))
  74. (defn get-block-file-path
  75. [block]
  76. (when-let [page-id (:db/id (:block/page block))]
  77. (:file/path (:block/file (db-utils/entity page-id)))))
  78. (defn get-file-page-id
  79. [file-path]
  80. (when-let [repo (state/get-current-repo)]
  81. (when-let [db (conn/get-db repo)]
  82. (some->
  83. (d/q
  84. '[:find ?page
  85. :in $ ?path
  86. :where
  87. [?file :file/path ?path]
  88. [?page :block/name]
  89. [?page :block/file ?file]]
  90. db file-path)
  91. db-utils/seq-flatten
  92. first))))
  93. (defn- get-files-blocks
  94. [repo-url paths]
  95. (let [paths (set paths)
  96. pred (fn [_db e]
  97. (contains? paths e))]
  98. (-> (d/q '[:find ?block
  99. :in $ ?pred
  100. :where
  101. [?file :file/path ?path]
  102. [(?pred $ ?path)]
  103. [?p :block/file ?file]
  104. [?block :block/page ?p]]
  105. (conn/get-db repo-url) pred)
  106. db-utils/seq-flatten)))
  107. (defn delete-blocks
  108. [repo-url files _delete-page?]
  109. (when (seq files)
  110. (let [blocks (->> (get-files-blocks repo-url files)
  111. (remove nil?))]
  112. (mapv (fn [eid] [:db.fn/retractEntity eid]) blocks))))
  113. (defn get-file-page
  114. ([file-path]
  115. (get-file-page file-path true))
  116. ([file-path title?]
  117. (when-let [repo (state/get-current-repo)]
  118. (when-let [db (conn/get-db repo)]
  119. (some->
  120. (d/q
  121. (if title?
  122. '[:find ?page-name
  123. :in $ ?path
  124. :where
  125. [?file :file/path ?path]
  126. [?page :block/file ?file]
  127. [?page :block/title ?page-name]]
  128. '[:find ?page-name
  129. :in $ ?path
  130. :where
  131. [?file :file/path ?path]
  132. [?page :block/file ?file]
  133. [?page :block/name ?page-name]])
  134. db file-path)
  135. db-utils/seq-flatten
  136. first)))))
  137. ;; file-based only so it's safe to use :block/name lookup refs here
  138. (defn delete-pages-by-files
  139. [files]
  140. (let [pages (->> (mapv get-file-page files)
  141. (remove nil?))]
  142. (when (seq pages)
  143. (mapv (fn [page] [:db.fn/retractEntity [:block/name page]]) (map util/page-name-sanity-lc pages)))))
  144. ;; TODO: check whether this works when adding pdf back on Web
  145. (defn get-pre-block
  146. [repo page-id]
  147. (-> (d/q '[:find (pull ?b [*])
  148. :in $ ?page
  149. :where
  150. [?b :block/page ?page]
  151. [?b :block/pre-block? true]]
  152. (conn/get-db repo)
  153. page-id)
  154. ffirst))
  155. (defn- get-all-namespace-relation
  156. [repo]
  157. (gp-db/get-all-namespace-relation (conn/get-db repo)))
  158. (defn get-all-namespace-parents
  159. [repo]
  160. (let [db (conn/get-db repo)]
  161. (->> (get-all-namespace-relation repo)
  162. (map (fn [[_ ?parent]]
  163. (db-utils/entity db ?parent))))))
  164. (defn get-namespace-pages
  165. "Accepts both sanitized and unsanitized namespaces"
  166. [repo namespace]
  167. (common-file-db/get-namespace-pages (conn/get-db repo) namespace))
  168. (defn- tree [flat-col root]
  169. (let [sort-fn #(sort-by :block/name %)
  170. children (group-by :block/namespace flat-col)
  171. namespace-children (fn namespace-children [parent-id]
  172. (map (fn [m]
  173. (assoc m :namespace/children
  174. (sort-fn (namespace-children {:db/id (:db/id m)}))))
  175. (sort-fn (get children parent-id))))]
  176. (namespace-children root)))
  177. (defn get-namespace-hierarchy
  178. "Unsanitized namespaces"
  179. [repo namespace]
  180. (let [children (get-namespace-pages repo namespace)
  181. namespace-id (:db/id (db-utils/entity [:block/name (util/page-name-sanity-lc namespace)]))
  182. root {:db/id namespace-id}
  183. col (conj children root)]
  184. (tree col root)))
  185. (defn get-page-namespace
  186. [repo page]
  187. (:block/namespace (db-utils/entity repo [:block/name (util/page-name-sanity-lc page)])))
  188. (defn get-page-namespace-routes
  189. [repo page]
  190. (assert (string? page))
  191. (when-let [db (conn/get-db repo)]
  192. (when-not (string/blank? page)
  193. (let [page (util/page-name-sanity-lc (string/trim page))
  194. page-exist? (db-utils/entity repo [:block/name page])
  195. ids (if page-exist?
  196. '()
  197. (->> (d/datoms db :aevt :block/name)
  198. (filter (fn [datom]
  199. (string/ends-with? (:v datom) (str "/" page))))
  200. (map :e)))]
  201. (when (seq ids)
  202. (db-utils/pull-many repo
  203. '[:db/id :block/name :block/title
  204. {:block/file [:db/id :file/path]}]
  205. ids))))))