async.cljs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. (ns frontend.db.async
  2. "Async queries"
  3. (:require [promesa.core :as p]
  4. [frontend.state :as state]
  5. [frontend.config :as config]
  6. [clojure.string :as string]
  7. [frontend.util :as util]
  8. [frontend.db.utils :as db-utils]
  9. [frontend.db.async.util :as db-async-util]
  10. [frontend.db.file-based.async :as file-async]
  11. [frontend.db :as db]
  12. [frontend.db.model :as db-model]
  13. [frontend.persist-db.browser :as db-browser]
  14. [datascript.core :as d]
  15. [frontend.db.react :as react]
  16. [frontend.date :as date]
  17. [cljs-time.core :as t]
  18. [cljs-time.format :as tf]
  19. [datascript.transit :as dt]))
  20. (def <q db-async-util/<q)
  21. (def <pull db-async-util/<pull)
  22. (comment
  23. (def <pull-many db-async-util/<pull-many))
  24. (defn <get-files
  25. [graph]
  26. (p/let [result (<q
  27. graph
  28. '[:find ?path ?modified-at
  29. :where
  30. [?file :file/path ?path]
  31. [(get-else $ ?file :file/last-modified-at 0) ?modified-at]])]
  32. (->> result seq reverse)))
  33. (defn <get-all-templates
  34. [graph]
  35. (p/let [result (<q graph
  36. '[:find ?t (pull ?b [*])
  37. :where
  38. [?b :block/properties ?p]
  39. [(get ?p :template) ?t]])]
  40. (into {} result)))
  41. (defn <get-template-by-name
  42. [name]
  43. (let [repo (state/get-current-repo)]
  44. (p/let [templates (<get-all-templates repo)]
  45. (get templates name))))
  46. (defn <db-based-get-all-properties
  47. ":block/type could be one of [property, class]."
  48. [graph]
  49. (<q graph
  50. '[:find [?n ...]
  51. :where
  52. [?e :block/type "property"]
  53. [?e :block/original-name ?n]]))
  54. (defn <get-all-properties
  55. "Returns a seq of property name strings"
  56. []
  57. (when-let [graph (state/get-current-repo)]
  58. (if (config/db-based-graph? graph)
  59. (<db-based-get-all-properties graph)
  60. (file-async/<file-based-get-all-properties graph))))
  61. (comment
  62. (defn <get-pages
  63. [graph]
  64. (p/let [result (<q graph
  65. '[:find [?page-original-name ...]
  66. :where
  67. [?page :block/name ?page-name]
  68. [(get-else $ ?page :block/original-name ?page-name) ?page-original-name]])]
  69. (remove db-model/hidden-page? result))))
  70. (defn <get-db-based-property-values
  71. [graph property]
  72. (let [property-name (if (keyword? property)
  73. (name property)
  74. (util/page-name-sanity-lc property))]
  75. (p/let [result (<q graph
  76. '[:find ?prop-type ?v
  77. :in $ ?prop-name
  78. :where
  79. [?b :block/properties ?bp]
  80. [?prop-b :block/name ?prop-name]
  81. [?prop-b :block/uuid ?prop-uuid]
  82. [?prop-b :block/schema ?prop-schema]
  83. [(get ?prop-schema :type) ?prop-type]
  84. [(get ?bp ?prop-uuid) ?v]]
  85. property-name)]
  86. (->> result
  87. (map (fn [[prop-type v]] [prop-type (if (coll? v) v [v])]))
  88. (mapcat (fn [[prop-type vals]]
  89. (let [result (case prop-type
  90. :default
  91. ;; Remove multi-block properties as there isn't a supported approach to query them yet
  92. (map str (remove uuid? vals))
  93. (:page :date)
  94. (map #(:block/original-name (db-utils/entity graph [:block/uuid %]))
  95. vals)
  96. :number
  97. vals
  98. ;; Checkboxes returned as strings as builder doesn't display boolean values correctly
  99. (map str vals))]
  100. (map (fn [value]
  101. (if (uuid? value)
  102. (get-in (db-utils/entity graph [:block/uuid value]) [:block/schema :value])
  103. value)) result))))
  104. ;; Remove blanks as they match on everything
  105. (remove string/blank?)
  106. (distinct)
  107. (sort)))))
  108. (defn <get-property-values
  109. [graph property]
  110. (if (config/db-based-graph? graph)
  111. (<get-db-based-property-values graph property)
  112. (file-async/<get-file-based-property-values graph property)))
  113. (defn <get-block-property-values
  114. [graph property-uuid]
  115. (<q graph
  116. '[:find ?b ?v
  117. :in $ ?property-uuid
  118. :where
  119. [?b :block/properties ?p]
  120. [(get ?p ?property-uuid) ?v]
  121. [(some? ?v)]]
  122. property-uuid))
  123. ;; TODO: batch queries for better performance and UX
  124. (defn <get-block
  125. [graph name-or-uuid & {:keys [children?]
  126. :or {children? true}}]
  127. (let [name' (str name-or-uuid)
  128. e (cond
  129. (number? name-or-uuid)
  130. (db/entity name-or-uuid)
  131. (util/uuid-string? name')
  132. (db/entity [:block/uuid (uuid name')])
  133. :else
  134. (db/entity [:block/name (util/page-name-sanity-lc name')]))]
  135. (if (:block.temp/fully-loaded? e)
  136. e
  137. (when-let [^Object sqlite @db-browser/*worker]
  138. (state/update-state! :db/async-queries (fn [s] (conj s name')))
  139. (p/let [result (.get-block-and-children sqlite graph name' children?)
  140. {:keys [block children] :as result'} (dt/read-transit-str result)
  141. conn (db/get-db graph false)
  142. block-and-children (cons block children)
  143. _ (d/transact! conn block-and-children)]
  144. (state/update-state! :db/async-queries (fn [s] (disj s name')))
  145. (react/refresh-affected-queries!
  146. graph
  147. [[:frontend.worker.react/block (:db/id block)]])
  148. (if children?
  149. block
  150. result'))))))
  151. (defn <get-right-sibling
  152. [graph db-id]
  153. (assert (integer? db-id))
  154. (when-let [^Object worker @db-browser/*worker]
  155. (p/let [result-str (.get-right-sibling worker graph db-id)
  156. result (dt/read-transit-str result-str)
  157. conn (db/get-db graph false)
  158. _ (when result (d/transact! conn [result]))]
  159. result)))
  160. (defn <get-block-parents
  161. [graph id depth]
  162. (assert (integer? id))
  163. (when-let [^Object worker @db-browser/*worker]
  164. (when-let [block-id (:block/uuid (db/entity graph id))]
  165. (state/update-state! :db/async-queries (fn [s] (conj s (str block-id "-parents"))))
  166. (p/let [result-str (.get-block-parents worker graph id depth)
  167. result (dt/read-transit-str result-str)
  168. conn (db/get-db graph false)
  169. _ (d/transact! conn result)]
  170. (state/update-state! :db/async-queries (fn [s] (disj s (str block-id "-parents"))))
  171. result))))
  172. (defn <get-block-refs
  173. [graph eid]
  174. (assert (integer? eid))
  175. (when-let [^Object worker @db-browser/*worker]
  176. (state/update-state! :db/async-queries (fn [s] (conj s (str eid "-refs"))))
  177. (p/let [result-str (.get-block-refs worker graph eid)
  178. result (dt/read-transit-str result-str)
  179. conn (db/get-db graph false)
  180. _ (d/transact! conn result)]
  181. (state/update-state! :db/async-queries (fn [s] (disj s (str eid "-refs"))))
  182. result)))
  183. (defn <get-block-refs-count
  184. [graph eid]
  185. (assert (integer? eid))
  186. (when-let [^Object worker @db-browser/*worker]
  187. (.get-block-refs-count worker graph eid)))
  188. (defn <get-all-referenced-blocks-uuid
  189. "Get all uuids of blocks with any back link exists."
  190. [graph]
  191. (<q graph
  192. '[:find [?refed-uuid ...]
  193. :where
  194. ;; ?referee-b is block with ref towards ?refed-b
  195. [?refed-b :block/uuid ?refed-uuid]
  196. [?referee-b :block/refs ?refed-b]]))
  197. (defn <get-file
  198. [graph path]
  199. (when (and graph path)
  200. (p/let [result (<pull graph [:file/path path])]
  201. (:file/content result))))
  202. (defn <get-date-scheduled-or-deadlines
  203. [journal-title]
  204. (when-let [date (date/journal-title->int journal-title)]
  205. (let [future-days (state/get-scheduled-future-days)
  206. date-format (tf/formatter "yyyyMMdd")
  207. current-day (tf/parse date-format (str date))
  208. future-day (some->> (t/plus current-day (t/days future-days))
  209. (tf/unparse date-format)
  210. (parse-long))]
  211. (when future-day
  212. (when-let [repo (state/get-current-repo)]
  213. (p/let [result (<q repo
  214. '[:find [(pull ?block ?block-attrs) ...]
  215. :in $ ?day ?future ?block-attrs
  216. :where
  217. (or
  218. [?block :block/scheduled ?d]
  219. [?block :block/deadline ?d])
  220. [(get-else $ ?block :block/repeated? false) ?repeated]
  221. [(get-else $ ?block :block/marker "NIL") ?marker]
  222. [(not= ?marker "DONE")]
  223. [(not= ?marker "CANCELED")]
  224. [(not= ?marker "CANCELLED")]
  225. [(<= ?d ?future)]
  226. (or-join [?repeated ?d ?day]
  227. [(true? ?repeated)]
  228. [(>= ?d ?day)])]
  229. date
  230. future-day
  231. db-model/block-attrs)]
  232. (->> result
  233. db-model/sort-by-left-recursive
  234. db-utils/group-by-page)))))))
  235. (defn <fetch-all-pages
  236. [graph]
  237. (when-let [^Object worker @db-browser/*worker]
  238. (.fetch-all-pages worker graph)))