model.cljs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365
  1. (ns frontend.db.model
  2. "Core db functions."
  3. (:require [clojure.set :as set]
  4. [clojure.string :as string]
  5. [clojure.walk :as walk]
  6. [datascript.core :as d]
  7. [frontend.config :as config]
  8. [frontend.date :as date]
  9. [frontend.db-schema :as db-schema]
  10. [frontend.db.conn :as conn]
  11. [frontend.db.react :as react]
  12. [frontend.db.utils :as db-utils]
  13. [frontend.format :as format]
  14. [frontend.state :as state]
  15. [frontend.util :as util :refer [react]]
  16. [medley.core :as medley]
  17. [frontend.db.rules :refer [rules]]))
  18. ;; TODO: extract to specific models and move data transform logic to the
  19. ;; correponding handlers.
  20. ;; Use it as an input argument for datalog queries
  21. (def block-attrs
  22. '[:db/id
  23. :block/uuid
  24. :block/type
  25. :block/left
  26. :block/format
  27. :block/title
  28. :block/refs
  29. :block/_refs
  30. :block/path-refs
  31. :block/tags
  32. :block/content
  33. :block/marker
  34. :block/priority
  35. :block/properties
  36. :block/body
  37. :block/pre-block?
  38. :block/scheduled
  39. :block/deadline
  40. :block/repeated?
  41. :block/created-at
  42. :block/updated-at
  43. :block/file
  44. :block/parent
  45. :block/unordered
  46. :block/heading-level
  47. {:block/page [:db/id :block/name :block/original-name :block/journal-day]}
  48. {:block/_parent ...}])
  49. (defn transact-files-db!
  50. ([tx-data]
  51. (db-utils/transact! (state/get-current-repo) tx-data))
  52. ([repo-url tx-data]
  53. (when-not config/publishing?
  54. (let [tx-data (->> (util/remove-nils tx-data)
  55. (remove nil?)
  56. (map #(dissoc % :file/handle :file/type)))]
  57. (when (seq tx-data)
  58. (when-let [conn (conn/get-conn repo-url false)]
  59. (d/transact! conn (vec tx-data))))))))
  60. (defn pull-block
  61. [id]
  62. (let [repo (state/get-current-repo)]
  63. (when (conn/get-conn repo)
  64. (->
  65. (react/q repo [:blocks id] {}
  66. '[:find (pull ?block [*])
  67. :in $ ?id
  68. :where
  69. [?block :block/uuid ?id]]
  70. id)
  71. react
  72. ffirst))))
  73. (defn get-tag-pages
  74. [repo tag-name]
  75. (when tag-name
  76. (d/q '[:find ?original-name ?name
  77. :in $ ?tag
  78. :where
  79. [?e :block/name ?tag]
  80. [?page :block/tags ?e]
  81. [?page :block/original-name ?original-name]
  82. [?page :block/name ?name]]
  83. (conn/get-conn repo)
  84. (string/lower-case tag-name))))
  85. (defn get-all-tagged-pages
  86. [repo]
  87. (d/q '[:find ?page-name ?tag
  88. :where
  89. [?page :block/tags ?e]
  90. [?e :block/name ?tag]
  91. [?page :block/name ?page-name]]
  92. (conn/get-conn repo)))
  93. (defn get-all-namespace-relation
  94. [repo]
  95. (d/q '[:find ?page-name ?parent
  96. :where
  97. [?page :block/name ?page-name]
  98. [?page :block/namespace ?e]
  99. [?e :block/name ?parent]]
  100. (conn/get-conn repo)))
  101. (defn get-pages
  102. [repo]
  103. (->> (d/q
  104. '[:find ?page-original-name
  105. :where
  106. [?page :block/name ?page-name]
  107. [(get-else $ ?page :block/original-name ?page-name) ?page-original-name]]
  108. (conn/get-conn repo))
  109. (map first)))
  110. (defn get-all-pages
  111. [repo]
  112. (d/q
  113. '[:find [(pull ?page [*]) ...]
  114. :where
  115. [?page :block/name]]
  116. (conn/get-conn repo)))
  117. (defn get-page-alias
  118. [repo page-name]
  119. (when-let [conn (and repo (conn/get-conn repo))]
  120. (some->> (d/q '[:find ?alias
  121. :in $ ?page-name
  122. :where
  123. [?page :block/name ?page-name]
  124. [?page :block/alias ?alias]]
  125. conn
  126. page-name)
  127. db-utils/seq-flatten
  128. distinct)))
  129. (defn get-alias-source-page
  130. [repo alias]
  131. (when-let [conn (and repo (conn/get-conn repo))]
  132. (let [pages (->>
  133. (d/q '[:find (pull ?p [*])
  134. :in $ ?alias
  135. :where
  136. [?a :block/name ?alias]
  137. [?p :block/alias ?a]]
  138. conn
  139. alias)
  140. (db-utils/seq-flatten))]
  141. (when (seq pages)
  142. (some (fn [page]
  143. (let [aliases (->> (get-in page [:block/properties :alias])
  144. (map string/lower-case)
  145. set)]
  146. (when (contains? aliases alias)
  147. page)))
  148. pages)))))
  149. (defn get-files
  150. [repo]
  151. (when-let [conn (conn/get-conn repo)]
  152. (->> (d/q
  153. '[:find ?path
  154. ;; ?modified-at
  155. :where
  156. [?file :file/path ?path]
  157. ;; [?file :file/last-modified-at ?modified-at]
  158. ]
  159. conn)
  160. (seq)
  161. ;; (sort-by last)
  162. (reverse))))
  163. (defn get-files-blocks
  164. [repo-url paths]
  165. (let [paths (set paths)
  166. pred (fn [_db e]
  167. (contains? paths e))]
  168. (-> (d/q '[:find ?block
  169. :in $ ?pred
  170. :where
  171. [?file :file/path ?path]
  172. [(?pred $ ?path)]
  173. [?block :block/file ?file]]
  174. (conn/get-conn repo-url) pred)
  175. db-utils/seq-flatten)))
  176. (defn get-files-non-page-blocks
  177. [repo-url paths]
  178. (let [paths (set paths)
  179. pred (fn [_db e]
  180. (contains? paths e))]
  181. (-> (d/q '[:find ?block
  182. :in $ ?pred
  183. :where
  184. [?file :file/path ?path]
  185. [(?pred $ ?path)]
  186. [?block :block/file ?file]
  187. [(missing? $ ?block :block/name)]]
  188. (conn/get-conn repo-url) pred)
  189. db-utils/seq-flatten)))
  190. (defn get-file-blocks
  191. [repo-url path]
  192. (-> (d/q '[:find ?block
  193. :in $ ?path
  194. :where
  195. [?file :file/path ?path]
  196. [?block :block/file ?file]]
  197. (conn/get-conn repo-url) path)
  198. db-utils/seq-flatten))
  199. (defn get-file-pages
  200. [repo-url path]
  201. (-> (d/q '[:find ?page
  202. :in $ ?path
  203. :where
  204. [?file :file/path ?path]
  205. [?page :block/file ?file]]
  206. (conn/get-conn repo-url) path)
  207. db-utils/seq-flatten))
  208. (defn set-file-last-modified-at!
  209. [repo path last-modified-at]
  210. (when (and repo path last-modified-at)
  211. (when-let [conn (conn/get-conn repo false)]
  212. (d/transact! conn
  213. [{:file/path path
  214. :file/last-modified-at last-modified-at}]))))
  215. (defn get-file-last-modified-at
  216. [repo path]
  217. (when (and repo path)
  218. (when-let [conn (conn/get-conn repo false)]
  219. (-> (d/entity (d/db conn) [:file/path path])
  220. :file/last-modified-at))))
  221. (defn file-exists?
  222. [repo path]
  223. (when (and repo path)
  224. (when-let [conn (conn/get-conn repo false)]
  225. (d/entity (d/db conn) [:file/path path]))))
  226. (defn get-file
  227. ([path]
  228. (get-file (state/get-current-repo) path))
  229. ([repo path]
  230. (when (and repo path)
  231. (->
  232. (react/q repo [:file/content path]
  233. {:use-cache? true}
  234. '[:find ?content
  235. :in $ ?path
  236. :where
  237. [?file :file/path ?path]
  238. [?file :file/content ?content]]
  239. path)
  240. react
  241. ffirst))))
  242. (defn get-file-contents
  243. [repo]
  244. (when-let [conn (conn/get-conn repo)]
  245. (->>
  246. (d/q
  247. '[:find ?path ?content
  248. :where
  249. [?file :file/path ?path]
  250. [?file :file/content ?content]]
  251. conn)
  252. (into {}))))
  253. (defn get-files-full
  254. [repo]
  255. (when-let [conn (conn/get-conn repo)]
  256. (->>
  257. (d/q
  258. '[:find (pull ?file [*])
  259. :where
  260. [?file :file/path]]
  261. conn)
  262. (flatten))))
  263. (defn get-file-by-path
  264. [file-path]
  265. (when-let [repo (state/get-current-repo)]
  266. (when-let [conn (conn/get-conn repo)]
  267. (d/pull conn '[*] [:file/path file-path]))))
  268. (defn get-custom-css
  269. []
  270. (when-let [repo (state/get-current-repo)]
  271. (get-file (config/get-file-path repo "logseq/custom.css"))))
  272. (defn get-file-no-sub
  273. ([path]
  274. (get-file-no-sub (state/get-current-repo) path))
  275. ([repo path]
  276. (when (and repo path)
  277. (when-let [conn (conn/get-conn repo)]
  278. (:file/content (d/entity conn [:file/path path]))))))
  279. (defn get-block-by-uuid
  280. [id]
  281. (db-utils/entity [:block/uuid (if (uuid? id) id (uuid id))]))
  282. (defn query-block-by-uuid
  283. [id]
  284. (db-utils/pull [:block/uuid (if (uuid? id) id (uuid id))]))
  285. (defn get-page-format
  286. [page-name]
  287. (or
  288. (let [page (db-utils/entity [:block/name page-name])]
  289. (or
  290. (:block/format page)
  291. (when-let [file (:block/file page)]
  292. (when-let [path (:file/path (db-utils/entity (:db/id file)))]
  293. (format/get-format path)))))
  294. (state/get-preferred-format)
  295. :markdown))
  296. (defn page-alias-set
  297. [repo-url page]
  298. (when-let [page-id (:db/id (db-utils/entity repo-url [:block/name page]))]
  299. (->>
  300. (d/q '[:find ?e
  301. :in $ ?page-name %
  302. :where
  303. [?page :block/name ?page-name]
  304. (alias ?page ?e)]
  305. (conn/get-conn repo-url)
  306. page
  307. '[[(alias ?e2 ?e1)
  308. [?e2 :block/alias ?e1]]
  309. [(alias ?e2 ?e1)
  310. [?e1 :block/alias ?e2]]
  311. [(alias ?e1 ?e3)
  312. [?e1 :block/alias ?e2]
  313. [?e2 :block/alias ?e3]]
  314. [(alias ?e3 ?e1)
  315. [?e1 :block/alias ?e2]
  316. [?e2 :block/alias ?e3]]])
  317. db-utils/seq-flatten
  318. (set)
  319. (set/union #{page-id}))))
  320. (defn get-page-names-by-ids
  321. ([ids]
  322. (get-page-names-by-ids (state/get-current-repo) ids))
  323. ([repo ids]
  324. (when repo
  325. (->> (db-utils/pull-many repo '[:block/name] ids)
  326. (map :block/name)))))
  327. (defn get-page-ids-by-names
  328. ([names]
  329. (get-page-ids-by-names (state/get-current-repo) names))
  330. ([repo names]
  331. (when repo
  332. (let [lookup-refs (map (fn [name]
  333. [:block/name (string/lower-case name)]) names)]
  334. (->> (db-utils/pull-many repo '[:db/id] lookup-refs)
  335. (mapv :db/id))))))
  336. (defn get-page-alias-names
  337. [repo page-name]
  338. (let [alias-ids (page-alias-set repo page-name)]
  339. (when (seq alias-ids)
  340. (let [names (->> (get-page-names-by-ids repo alias-ids)
  341. distinct
  342. (remove #(= (string/lower-case %) (string/lower-case page-name))))
  343. lookup-refs (map (fn [name]
  344. [:block/name (string/lower-case name)]) names)]
  345. (->> (db-utils/pull-many repo '[:block/name :block/original-name] lookup-refs)
  346. (map (fn [m]
  347. (or (:block/original-name m) (:block/name m)))))))))
  348. (defn page-blocks-transform
  349. [repo-url result]
  350. (db-utils/with-repo repo-url result))
  351. (defn with-pages
  352. [blocks]
  353. (let [pages-ids (->> (map (comp :db/id :block/page) blocks)
  354. (remove nil?))
  355. pages (when (seq pages-ids)
  356. (db-utils/pull-many '[:db/id :block/name :block/original-name :block/journal-day] pages-ids))
  357. pages-map (reduce (fn [acc p] (assoc acc (:db/id p) p)) {} pages)
  358. blocks (map
  359. (fn [block]
  360. (assoc block :block/page
  361. (get pages-map (:db/id (:block/page block)))))
  362. blocks)]
  363. blocks))
  364. (defn get-page-properties
  365. [page]
  366. (when-let [page (db-utils/entity [:block/name page])]
  367. (:block/properties page)))
  368. ;; FIXME: alert
  369. (defn- keep-only-one-file
  370. [blocks]
  371. (filter (fn [b] (= (:block/file b) (:block/file (first blocks)))) blocks))
  372. (defn sort-by-left
  373. ([blocks parent]
  374. (sort-by-left blocks parent true))
  375. ([blocks parent check?]
  376. (let [blocks (keep-only-one-file blocks)]
  377. (when check?
  378. (when (not= (count blocks) (count (set (map :block/left blocks))))
  379. (let [duplicates (->> (map (comp :db/id :block/left) blocks)
  380. frequencies
  381. (filter (fn [[_k v]] (> v 1)))
  382. (map (fn [[k _v]]
  383. (let [left (db-utils/pull k)]
  384. {:left left
  385. :duplicates (->>
  386. (filter (fn [block]
  387. (= k (:db/id (:block/left block))))
  388. blocks)
  389. (map #(select-keys % [:db/id :block/level :block/content :block/file])))}))))]
  390. (util/pprint duplicates)))
  391. (assert (= (count blocks) (count (set (map :block/left blocks)))) "Each block should have a different left node"))
  392. (let [left->blocks (reduce (fn [acc b] (assoc acc (:db/id (:block/left b)) b)) {} blocks)]
  393. (loop [block parent
  394. result []]
  395. (if-let [next (get left->blocks (:db/id block))]
  396. (recur next (conj result next))
  397. (vec result)))))))
  398. (defn- sort-by-left-recursive
  399. [form]
  400. (walk/postwalk (fn [f]
  401. (if (and (map? f)
  402. (:block/_parent f))
  403. (let [children (:block/_parent f)]
  404. (-> f
  405. (dissoc :block/_parent)
  406. (assoc :block/children (sort-by-left children f))))
  407. f))
  408. form))
  409. (defn flatten-blocks-sort-by-left
  410. [blocks parent]
  411. (let [ids->blocks (zipmap (map (fn [b] [(:db/id (:block/parent b))
  412. (:db/id (:block/left b))]) blocks) blocks)
  413. top-block (get ids->blocks [(:db/id parent) (:db/id parent)])]
  414. (loop [node parent
  415. next-siblings '()
  416. result []]
  417. (let [id (:db/id node)
  418. child-block (get ids->blocks [id id])
  419. next-sibling (get ids->blocks [(:db/id (:block/parent node)) id])
  420. next-siblings (if (and next-sibling child-block)
  421. (cons next-sibling next-siblings)
  422. next-siblings)]
  423. (if-let [node (or child-block next-sibling)]
  424. (recur node next-siblings (conj result node))
  425. (if-let [sibling (first next-siblings)]
  426. (recur sibling (rest next-siblings) (conj result sibling))
  427. result))))))
  428. (defn get-page-blocks
  429. ([page]
  430. (get-page-blocks (state/get-current-repo) page nil))
  431. ([repo-url page]
  432. (get-page-blocks repo-url page nil))
  433. ([repo-url page {:keys [use-cache? pull-keys]
  434. :or {use-cache? true
  435. pull-keys block-attrs}}]
  436. (let [page (string/lower-case (string/trim page))
  437. page-entity (or (db-utils/entity repo-url [:block/name page])
  438. (db-utils/entity repo-url [:block/original-name page]))
  439. page-id (:db/id page-entity)
  440. db (conn/get-conn repo-url)]
  441. (when page-id
  442. (some->
  443. (react/q repo-url [:page/blocks page-id]
  444. {:use-cache? use-cache?
  445. :transform-fn #(page-blocks-transform repo-url %)
  446. :query-fn (fn [db]
  447. (let [datoms (d/datoms db :avet :block/page page-id)
  448. block-eids (mapv :e datoms)]
  449. (db-utils/pull-many repo-url pull-keys block-eids)))}
  450. nil)
  451. react
  452. (flatten-blocks-sort-by-left page-entity))))))
  453. (defn get-page-blocks-no-cache
  454. ([page]
  455. (get-page-blocks-no-cache (state/get-current-repo) page nil))
  456. ([repo-url page]
  457. (get-page-blocks-no-cache repo-url page nil))
  458. ([repo-url page {:keys [pull-keys]
  459. :or {pull-keys '[*]}}]
  460. (let [page (string/lower-case page)
  461. page-id (or (:db/id (db-utils/entity repo-url [:block/name page]))
  462. (:db/id (db-utils/entity repo-url [:block/original-name page])))
  463. db (conn/get-conn repo-url)]
  464. (when page-id
  465. (let [datoms (d/datoms db :avet :block/page page-id)
  466. block-eids (mapv :e datoms)]
  467. (some->> (db-utils/pull-many repo-url pull-keys block-eids)
  468. (page-blocks-transform repo-url)))))))
  469. (defn get-page-blocks-count
  470. [repo page-id]
  471. (when-let [db (conn/get-conn repo)]
  472. (count (d/datoms db :avet :block/page page-id))))
  473. (defn page-empty?
  474. [repo page-id]
  475. (let [page-id (if (integer? page-id)
  476. page-id
  477. [:block/name page-id])]
  478. (empty? (:block/_parent (db-utils/entity repo page-id)))))
  479. (defn page-empty-or-dummy?
  480. [repo page-id]
  481. (or
  482. (page-empty? repo page-id)
  483. (when-let [db (conn/get-conn repo)]
  484. (let [datoms (d/datoms db :avet :block/page page-id)]
  485. (and (= (count datoms) 1)
  486. (= "" (:block/content (db-utils/pull (:e (first datoms))))))))))
  487. (defn get-block-parent
  488. ([block-id]
  489. (get-block-parent (state/get-current-repo) block-id))
  490. ([repo block-id]
  491. (when-let [conn (conn/get-conn repo)]
  492. (when-let [block (d/entity conn [:block/uuid block-id])]
  493. (:block/parent block)))))
  494. ;; non recursive query
  495. (defn get-block-parents
  496. [repo block-id depth]
  497. (when-let [conn (conn/get-conn repo)]
  498. (loop [block-id block-id
  499. parents (list)
  500. d 1]
  501. (if (> d depth)
  502. parents
  503. (if-let [parent (get-block-parent repo block-id)]
  504. (recur (:block/uuid parent) (conj parents parent) (inc d))
  505. parents)))))
  506. (comment
  507. (defn get-immediate-children-v2
  508. [repo block-id]
  509. (d/pull (conn/get-conn repo)
  510. '[:block/_parent]
  511. [:block/uuid block-id])))
  512. ;; Use built-in recursive
  513. (defn get-block-parents-v2
  514. [repo block-id]
  515. (d/pull (conn/get-conn repo)
  516. '[:db/id :block/properties {:block/parent ...}]
  517. [:block/uuid block-id]))
  518. (defn parents-collapsed?
  519. [repo block-id]
  520. (when-let [block (:block/parent (get-block-parents-v2 repo block-id))]
  521. (->> (tree-seq map? (fn [x] [(:block/parent x)]) block)
  522. (map (comp :collapsed :block/properties))
  523. (some true?))))
  524. (defn get-block-page
  525. [repo block-id]
  526. (when-let [block (db-utils/entity repo [:block/uuid block-id])]
  527. (db-utils/entity repo (:db/id (:block/page block)))))
  528. (defn block-and-children-transform
  529. [result repo-url block-uuid]
  530. (some->> result
  531. db-utils/seq-flatten
  532. (db-utils/with-repo repo-url)))
  533. (defn get-block-children-ids
  534. [repo block-uuid]
  535. (when-let [conn (conn/get-conn repo)]
  536. (let [eid (:db/id (db-utils/entity repo [:block/uuid block-uuid]))]
  537. (->> (d/q
  538. '[:find ?id
  539. :in $ ?p %
  540. :where
  541. (parent ?p ?c)
  542. [?c :block/uuid ?id]]
  543. conn
  544. eid
  545. rules)
  546. (apply concat)))))
  547. (defn get-block-immediate-children
  548. "Doesn't include nested children."
  549. [repo block-uuid]
  550. (when-let [conn (conn/get-conn repo)]
  551. (-> (d/q
  552. '[:find [(pull ?b [*]) ...]
  553. :in $ ?parent-id
  554. :where
  555. [?b :block/parent ?parent]
  556. [?parent :block/uuid ?parent-id]]
  557. conn
  558. block-uuid)
  559. (sort-by-left (db-utils/entity [:block/uuid block-uuid])))))
  560. (defn get-blocks-by-page
  561. [id-or-lookup-ref]
  562. (when-let [conn (conn/get-conn)]
  563. (->
  564. (d/q
  565. '[:find (pull ?block [*])
  566. :in $ ?page
  567. :where
  568. [?block :block/page ?page]]
  569. conn id-or-lookup-ref)
  570. flatten)))
  571. (defn get-block-children
  572. "Including nested children."
  573. [repo block-uuid]
  574. (when-let [conn (conn/get-conn repo)]
  575. (let [ids (get-block-children-ids repo block-uuid)
  576. ids (map (fn [id] [:block/uuid id]) ids)]
  577. (when (seq ids)
  578. (db-utils/pull-many repo '[*] ids)))))
  579. ;; TODO: use the tree directly
  580. (defn- flatten-tree
  581. [blocks-tree]
  582. (if-let [children (:block/_parent blocks-tree)]
  583. (cons (dissoc blocks-tree :block/_parent) (mapcat flatten-tree children))
  584. [blocks-tree]))
  585. (defn get-block-and-children
  586. ([repo block-uuid]
  587. (get-block-and-children repo block-uuid true))
  588. ([repo block-uuid use-cache?]
  589. (some-> (react/q repo [:block/block block-uuid]
  590. {:use-cache? use-cache?
  591. :transform-fn #(block-and-children-transform % repo block-uuid)}
  592. '[:find [(pull ?block ?block-attrs) ...]
  593. :in $ ?id ?block-attrs
  594. :where
  595. [?block :block/uuid ?id]]
  596. block-uuid
  597. block-attrs)
  598. react
  599. first
  600. flatten-tree)))
  601. (defn get-file-page
  602. ([file-path]
  603. (get-file-page file-path true))
  604. ([file-path original-name?]
  605. (when-let [repo (state/get-current-repo)]
  606. (when-let [conn (conn/get-conn repo)]
  607. (some->
  608. (d/q
  609. (if original-name?
  610. '[:find ?page-name
  611. :in $ ?path
  612. :where
  613. [?file :file/path ?path]
  614. [?page :block/file ?file]
  615. [?page :block/original-name ?page-name]]
  616. '[:find ?page-name
  617. :in $ ?path
  618. :where
  619. [?file :file/path ?path]
  620. [?page :block/file ?file]
  621. [?page :block/name ?page-name]])
  622. conn file-path)
  623. db-utils/seq-flatten
  624. first)))))
  625. (defn get-page-file
  626. [page-name]
  627. (some-> (or (db-utils/entity [:block/name page-name])
  628. (db-utils/entity [:block/original-name page-name]))
  629. :block/file))
  630. (defn get-file-page-id
  631. [file-path]
  632. (when-let [repo (state/get-current-repo)]
  633. (when-let [conn (conn/get-conn repo)]
  634. (some->
  635. (d/q
  636. '[:find ?page
  637. :in $ ?path
  638. :where
  639. [?file :file/path ?path]
  640. [?page :block/name]
  641. [?page :block/file ?file]]
  642. conn file-path)
  643. db-utils/seq-flatten
  644. first))))
  645. (defn get-page
  646. [page-name]
  647. (if (util/uuid-string? page-name)
  648. (db-utils/entity [:block/uuid (uuid page-name)])
  649. (db-utils/entity [:block/name (string/lower-case page-name)])))
  650. (defn- heading-block?
  651. [block]
  652. (and
  653. (vector? block)
  654. (= "Heading" (first block))))
  655. (defn get-redirect-page-name
  656. ([page-name] (get-redirect-page-name page-name false))
  657. ([page-name alias?]
  658. (when page-name
  659. (let [page-name (string/lower-case page-name)
  660. page-entity (db-utils/entity [:block/name page-name])]
  661. (cond
  662. alias?
  663. page-name
  664. (page-empty-or-dummy? (state/get-current-repo) (:db/id page-entity))
  665. (let [source-page (get-alias-source-page (state/get-current-repo)
  666. (string/lower-case page-name))]
  667. (or (when source-page (:block/name source-page))
  668. page-name))
  669. :else
  670. page-name)))))
  671. (defn get-page-original-name
  672. [page-name]
  673. (when (string? page-name)
  674. (let [page (db-utils/pull [:block/name (string/lower-case page-name)])]
  675. (or (:block/original-name page)
  676. (:block/name page)))))
  677. (defn get-journals-length
  678. []
  679. (let [today (db-utils/date->int (js/Date.))]
  680. (d/q '[:find (count ?page) .
  681. :in $ ?today
  682. :where
  683. [?page :block/journal? true]
  684. [?page :block/journal-day ?journal-day]
  685. [(<= ?journal-day ?today)]]
  686. (conn/get-conn (state/get-current-repo))
  687. today)))
  688. (defn get-latest-journals
  689. ([n]
  690. (get-latest-journals (state/get-current-repo) n))
  691. ([repo-url n]
  692. (when (conn/get-conn repo-url)
  693. (let [date (js/Date.)
  694. _ (.setDate date (- (.getDate date) (dec n)))
  695. today (db-utils/date->int (js/Date.))
  696. pages (->>
  697. (react/q repo-url [:journals] {:use-cache? false}
  698. '[:find ?page-name ?journal-day
  699. :in $ ?today
  700. :where
  701. [?page :block/name ?page-name]
  702. [?page :block/journal? true]
  703. [?page :block/journal-day ?journal-day]
  704. [(<= ?journal-day ?today)]]
  705. today)
  706. (react)
  707. (sort-by last)
  708. (reverse)
  709. (map first)
  710. (take n))]
  711. (mapv
  712. (fn [page]
  713. [page
  714. (get-page-format page)])
  715. pages)))))
  716. ;; get pages that this page referenced
  717. (defn get-page-referenced-pages
  718. [repo page]
  719. (when (conn/get-conn repo)
  720. (let [pages (page-alias-set repo page)
  721. page-id (:db/id (db-utils/entity [:block/name page]))
  722. ref-pages (->> (react/q repo [:page/ref-pages page-id] {:use-cache? false}
  723. '[:find ?ref-page-name
  724. :in $ ?pages
  725. :where
  726. [?block :block/page ?p]
  727. [(contains? ?pages ?p)]
  728. [?block :block/refs ?ref-page]
  729. [?ref-page :block/name ?ref-page-name]]
  730. pages)
  731. react
  732. db-utils/seq-flatten)]
  733. (mapv (fn [page] [page (get-page-alias repo page)]) ref-pages))))
  734. (defn get-page-linked-refs-refed-pages
  735. [repo page]
  736. (when-let [conn (conn/get-conn repo)]
  737. (->
  738. (d/q
  739. '[:find [?ref-page ...]
  740. :in $ % ?page
  741. :where
  742. [?p :block/name ?page]
  743. [?b :block/path-refs ?p]
  744. [?b :block/refs ?other-p]
  745. [(not= ?p ?other-p)]
  746. [?other-p :block/original-name ?ref-page]]
  747. conn
  748. rules
  749. page)
  750. (distinct))))
  751. ;; Ignore files with empty blocks for now
  752. (defn get-pages-relation
  753. [repo with-journal?]
  754. (when-let [conn (conn/get-conn repo)]
  755. (let [q (if with-journal?
  756. '[:find ?page ?ref-page-name
  757. :where
  758. [?p :block/name ?page]
  759. [?block :block/page ?p]
  760. [?block :block/refs ?ref-page]
  761. [?ref-page :block/name ?ref-page-name]]
  762. '[:find ?page ?ref-page-name
  763. :where
  764. [?p :block/journal? false]
  765. [?p :block/name ?page]
  766. [?block :block/page ?p]
  767. [?block :block/refs ?ref-page]
  768. [?ref-page :block/name ?ref-page-name]])]
  769. (->>
  770. (d/q q conn)
  771. (map (fn [[page ref-page-name]]
  772. [page ref-page-name]))))))
  773. ;; get pages who mentioned this page
  774. ;; TODO: use :block/_refs
  775. (defn get-pages-that-mentioned-page
  776. [repo page]
  777. (when (conn/get-conn repo)
  778. (let [page-id (:db/id (db-utils/entity [:block/name page]))
  779. pages (page-alias-set repo page)
  780. mentioned-pages (->> (react/q repo [:page/mentioned-pages page-id] {:use-cache? false}
  781. '[:find ?mentioned-page-name
  782. :in $ ?pages ?page-name
  783. :where
  784. [?block :block/refs ?p]
  785. [(contains? ?pages ?p)]
  786. [?block :block/page ?mentioned-page]
  787. [?mentioned-page :block/name ?mentioned-page-name]]
  788. pages
  789. page)
  790. react
  791. db-utils/seq-flatten)]
  792. (mapv (fn [page] [page (get-page-alias repo page)]) mentioned-pages))))
  793. (defn- remove-children!
  794. [blocks]
  795. (let [parents (->> (mapcat :block/parent blocks)
  796. (map :db/id)
  797. (set))]
  798. (if (seq parents)
  799. (filter (fn [block] (contains? parents (:db/id block))) blocks)
  800. blocks)))
  801. (defn has-children?
  802. ([block-id]
  803. (has-children? (state/get-current-repo) block-id))
  804. ([repo block-id]
  805. (let [db (conn/get-conn repo)]
  806. (when-let [block (db-utils/entity [:block/uuid block-id])]
  807. ;; perf: early stop
  808. (let [result (d/datoms db :avet :block/parent (:db/id block))]
  809. (boolean (seq result)))))))
  810. ;; TODO: improve perf
  811. (defn with-children-refs
  812. [repo blocks]
  813. (when-let [conn (conn/get-conn repo)]
  814. (when (seq blocks)
  815. (let [block-ids (set (map :db/id blocks))
  816. refs (d/q
  817. '[:find ?p ?ref
  818. :in $ % ?block-ids
  819. :where
  820. (parent ?p ?b)
  821. [(contains? ?block-ids ?p)]
  822. [?b :block/refs ?ref]]
  823. conn
  824. rules
  825. block-ids)
  826. refs (->> (group-by first refs)
  827. (medley/map-vals #(set (map (fn [[_ id]] {:db/id id}) %))))]
  828. (map (fn [block] (assoc block :block/children-refs
  829. (get refs (:db/id block)))) blocks)))))
  830. (defn get-page-referenced-blocks-no-cache
  831. [page-id]
  832. (when-let [repo (state/get-current-repo)]
  833. (->>
  834. (d/q '[:find (pull ?b [*])
  835. :in $ ?page-id
  836. :where
  837. [?b :block/refs ?page-id]]
  838. (conn/get-conn repo)
  839. page-id)
  840. (flatten))))
  841. (defn get-page-referenced-blocks
  842. ([page]
  843. (get-page-referenced-blocks (state/get-current-repo) page))
  844. ([repo page]
  845. (when repo
  846. (when (conn/get-conn repo)
  847. (let [page-id (:db/id (db-utils/entity [:block/name page]))
  848. pages (page-alias-set repo page)
  849. aliases (set/difference pages #{page-id})
  850. query-result (if (seq aliases)
  851. (let [rules '[[(find-blocks ?block ?ref-page ?pages ?alias ?aliases)
  852. [?block :block/page ?alias]
  853. [(contains? ?aliases ?alias)]]
  854. [(find-blocks ?block ?ref-page ?pages ?alias ?aliases)
  855. [?block :block/refs ?ref-page]
  856. [(contains? ?pages ?ref-page)]]]]
  857. (react/q repo [:block/refed-blocks page-id] {}
  858. '[:find [(pull ?block ?block-attrs) ...]
  859. :in $ % ?pages ?aliases ?block-attrs
  860. :where
  861. (find-blocks ?block ?ref-page ?pages ?alias ?aliases)]
  862. rules
  863. pages
  864. aliases
  865. block-attrs))
  866. (react/q repo [:block/refed-blocks page-id] {:use-cache? false}
  867. '[:find [(pull ?ref-block ?block-attrs) ...]
  868. :in $ ?page ?block-attrs
  869. :where
  870. [?ref-block :block/refs ?page]]
  871. page-id
  872. block-attrs))
  873. result (->> query-result
  874. react
  875. (sort-by-left-recursive)
  876. (remove (fn [block]
  877. (= page-id (:db/id (:block/page block)))))
  878. ;; (with-children-refs repo)
  879. db-utils/group-by-page
  880. (map (fn [[k blocks]]
  881. (let [k (if (contains? aliases (:db/id k))
  882. (assoc k :block/alias? true)
  883. k)]
  884. [k blocks]))))]
  885. result)))))
  886. (defn get-date-scheduled-or-deadlines
  887. [journal-title]
  888. (when-let [date (date/journal-title->int journal-title)]
  889. (let [future-days (state/get-scheduled-future-days)]
  890. (when-let [repo (state/get-current-repo)]
  891. (when-let [conn (conn/get-conn repo)]
  892. (->> (react/q repo [:custom :scheduled-deadline journal-title] {}
  893. '[:find [(pull ?block ?block-attrs) ...]
  894. :in $ ?day ?future ?block-attrs
  895. :where
  896. (or
  897. [?block :block/scheduled ?d]
  898. [?block :block/deadline ?d])
  899. [(get-else $ ?block :block/repeated? false) ?repeated]
  900. [(get-else $ ?block :block/marker "NIL") ?marker]
  901. [(not= ?marker "DONE")]
  902. [(not= ?marker "CANCELED")]
  903. [(not= ?marker "CANCELLED")]
  904. [(<= ?d ?future)]
  905. (or-join [?repeated ?d ?day]
  906. [(true? ?repeated)]
  907. [(>= ?d ?day)])]
  908. date
  909. (+ date future-days)
  910. block-attrs)
  911. react
  912. (sort-by-left-recursive)
  913. db-utils/group-by-page))))))
  914. (defn- pattern [name]
  915. (re-pattern (str "(?i)(?<!#)(?<!\\[\\[)"
  916. (util/regex-escape name)
  917. "(?!\\]\\])")))
  918. (defn get-page-unlinked-references
  919. [page]
  920. (when-let [repo (state/get-current-repo)]
  921. (when-let [conn (conn/get-conn repo)]
  922. (let [page-id (:db/id (db-utils/entity [:block/name page]))
  923. alias-names (get-page-alias-names repo page)
  924. patterns (->> (conj alias-names page)
  925. (map pattern))
  926. filter-fn (fn [datom]
  927. (some (fn [p] (re-find p (:v datom))) patterns))]
  928. (->> (react/q repo [:block/unlinked-refs page-id]
  929. {:query-fn (fn [db]
  930. (let [ids
  931. (->> (d/datoms db :aevt :block/content)
  932. (filter filter-fn)
  933. (map :e))
  934. result (d/pull-many db block-attrs ids)]
  935. (remove (fn [block] (= page-id (:db/id (:block/page block)))) result)))}
  936. nil)
  937. react
  938. (sort-by-left-recursive)
  939. db-utils/group-by-page)))))
  940. ;; TODO: Replace recursive queries with datoms index implementation
  941. ;; see https://github.com/tonsky/datascript/issues/130#issuecomment-169520434
  942. (defn get-block-referenced-blocks
  943. [block-uuid]
  944. (when-let [repo (state/get-current-repo)]
  945. (when (conn/get-conn repo)
  946. (let [block (db-utils/entity [:block/uuid block-uuid])]
  947. (->> (react/q repo [:block/refed-blocks (:db/id block)]
  948. {}
  949. '[:find [(pull ?ref-block ?block-attrs) ...]
  950. :in $ ?block-uuid ?block-attrs
  951. :where
  952. [?block :block/uuid ?block-uuid]
  953. [?ref-block :block/refs ?block]]
  954. block-uuid
  955. block-attrs)
  956. react
  957. (sort-by-left-recursive)
  958. db-utils/group-by-page)))))
  959. (defn get-matched-blocks
  960. [match-fn limit]
  961. (when-let [repo (state/get-current-repo)]
  962. (let [pred (fn [db content]
  963. (match-fn content))]
  964. (->> (d/q
  965. '[:find ?block
  966. :in $ ?pred
  967. :where
  968. [?block :block/content ?content]
  969. [(?pred $ ?content)]]
  970. (conn/get-conn)
  971. pred)
  972. (take limit)
  973. db-utils/seq-flatten
  974. (db-utils/pull-many '[:block/uuid
  975. :block/content
  976. :block/properties
  977. :block/format
  978. {:block/page [:block/name]}])))))
  979. ;; TODO: Does the result preserves the order of the arguments?
  980. (defn get-blocks-contents
  981. [repo block-uuids]
  982. (let [db (conn/get-conn repo)]
  983. (db-utils/pull-many repo '[:block/content]
  984. (mapv (fn [id] [:block/uuid id]) block-uuids))))
  985. (defn journal-page?
  986. [page-name]
  987. (:block/journal? (db-utils/entity [:block/name page-name])))
  988. (defn mark-repo-as-cloned!
  989. [repo-url]
  990. (db-utils/transact!
  991. [{:repo/url repo-url
  992. :repo/cloned? true}]))
  993. (defn cloned?
  994. [repo-url]
  995. (when-let [conn (conn/get-conn repo-url)]
  996. (->
  997. (d/q '[:find ?cloned
  998. :in $ ?repo-url
  999. :where
  1000. [?repo :repo/url ?repo-url]
  1001. [?repo :repo/cloned? ?cloned]]
  1002. conn
  1003. repo-url)
  1004. ffirst)))
  1005. (defn get-db-type
  1006. [repo]
  1007. (db-utils/get-key-value repo :db/type))
  1008. (defn local-native-fs?
  1009. [repo]
  1010. (= :local-native-fs (get-db-type repo)))
  1011. (defn get-public-pages
  1012. [db]
  1013. (-> (d/q
  1014. '[:find ?p
  1015. :where
  1016. [?p :block/name]
  1017. [?p :block/properties ?properties]
  1018. [(get ?properties :public) ?pub]
  1019. [(= true ?pub)]]
  1020. db)
  1021. (db-utils/seq-flatten)))
  1022. (defn get-public-false-pages
  1023. [db]
  1024. (-> (d/q
  1025. '[:find ?p
  1026. :where
  1027. [?p :block/name]
  1028. [?p :block/properties ?properties]
  1029. [(get ?properties :public) ?pub]
  1030. [(= false ?pub)]]
  1031. db)
  1032. (db-utils/seq-flatten)))
  1033. (defn get-public-false-block-ids
  1034. [db]
  1035. (-> (d/q
  1036. '[:find ?b
  1037. :where
  1038. [?p :block/name]
  1039. [?p :block/properties ?properties]
  1040. [(get ?properties :public) ?pub]
  1041. [(= false ?pub)]
  1042. [?b :block/page ?p]]
  1043. db)
  1044. (db-utils/seq-flatten)))
  1045. (defn get-all-templates
  1046. []
  1047. (let [pred (fn [db properties]
  1048. (some? (:template properties)))]
  1049. (->> (d/q
  1050. '[:find ?b ?p
  1051. :in $ ?pred
  1052. :where
  1053. [?b :block/properties ?p]
  1054. [(?pred $ ?p)]]
  1055. (conn/get-conn)
  1056. pred)
  1057. (map (fn [[e m]]
  1058. [(get m :template) e]))
  1059. (into {}))))
  1060. (defn get-template-by-name
  1061. [name]
  1062. (when (string? name)
  1063. (->> (d/q
  1064. '[:find (pull ?b [*])
  1065. :in $ ?name
  1066. :where
  1067. [?b :block/properties ?p]
  1068. [(get ?p :template) ?t]
  1069. [(= ?t ?name)]]
  1070. (conn/get-conn)
  1071. name)
  1072. ffirst)))
  1073. (defonce blocks-count-cache (atom nil))
  1074. (defn blocks-count
  1075. ([]
  1076. (blocks-count true))
  1077. ([cache?]
  1078. (if (and cache? @blocks-count-cache)
  1079. @blocks-count-cache
  1080. (when-let [conn (conn/get-conn)]
  1081. (let [n (count (d/datoms conn :avet :block/uuid))]
  1082. (reset! blocks-count-cache n)
  1083. n)))))
  1084. (defn get-all-block-uuids
  1085. []
  1086. (when-let [conn (conn/get-conn)]
  1087. (->> (d/datoms conn :avet :block/uuid)
  1088. (map :v))))
  1089. ;; block/uuid and block/content
  1090. (defn get-all-block-contents
  1091. []
  1092. (when-let [conn (conn/get-conn)]
  1093. (->> (d/datoms conn :avet :block/uuid)
  1094. (map :v)
  1095. (map (fn [id]
  1096. (let [e (db-utils/entity [:block/uuid id])]
  1097. (when (and (not (:block/name e))
  1098. (not (string/blank? (:block/content e))))
  1099. {:db/id (:db/id e)
  1100. :block/uuid id
  1101. :block/page (:db/id (:block/page e))
  1102. :block/content (:block/content e)
  1103. :block/format (:block/format e)}))))
  1104. (remove nil?))))
  1105. (defn get-assets
  1106. [datoms]
  1107. (keep
  1108. (fn [datom]
  1109. (when (= :block/content (:a datom))
  1110. (let [matched (re-seq #"\([./]*/assets/([^)]+)\)" (:v datom))
  1111. matched (get (into [] matched) 0)
  1112. path (get matched 1)]
  1113. (when (and (string? path)
  1114. (not (string/ends-with? path ".js")))
  1115. path))))
  1116. datoms))
  1117. (defn clean-export!
  1118. [db]
  1119. (let [remove? #(contains? #{"me" "recent" "file"} %)
  1120. non-public-pages (get-public-false-pages db)
  1121. non-public-datoms (get-public-false-block-ids db)
  1122. non-public-datom-ids (set (concat non-public-pages non-public-datoms))
  1123. filtered-db (d/filter db
  1124. (fn [db datom]
  1125. (let [ns (namespace (:a datom))]
  1126. (and (not (remove? ns))
  1127. (not (contains? #{:block/file} (:a datom)))
  1128. (not (contains? non-public-datom-ids (:e datom)))))))
  1129. datoms (d/datoms filtered-db :eavt)
  1130. assets (get-assets datoms)]
  1131. [@(d/conn-from-datoms datoms db-schema/schema) assets]))
  1132. (defn filter-only-public-pages-and-blocks
  1133. [db]
  1134. (let [public-pages (get-public-pages db)]
  1135. (when (seq public-pages)
  1136. (let [public-pages (set public-pages)
  1137. exported-namespace? #(contains? #{"block" "me" "recent"} %)
  1138. filtered-db (d/filter db
  1139. (fn [db datom]
  1140. (let [ns (namespace (:a datom))]
  1141. (and
  1142. (not (contains? #{:block/file} (:a datom)))
  1143. (not= ns "file")
  1144. (or
  1145. (not (exported-namespace? ns))
  1146. (and (= ns "block")
  1147. (or
  1148. (contains? public-pages (:e datom))
  1149. (contains? public-pages (:db/id (:block/page (d/entity db (:e datom))))))))))))
  1150. datoms (d/datoms filtered-db :eavt)
  1151. assets (get-assets datoms)]
  1152. [@(d/conn-from-datoms datoms db-schema/schema) assets]))))
  1153. (defn delete-blocks
  1154. [repo-url files delete-page?]
  1155. (when (seq files)
  1156. (let [f (if delete-page? get-files-blocks get-files-non-page-blocks)
  1157. blocks (f repo-url files)]
  1158. (mapv (fn [eid] [:db.fn/retractEntity eid]) blocks))))
  1159. (defn delete-files
  1160. [files]
  1161. (mapv (fn [path] [:db.fn/retractEntity [:file/path path]]) files))
  1162. (defn delete-file-blocks!
  1163. [repo-url path]
  1164. (let [blocks (get-file-blocks repo-url path)]
  1165. (mapv (fn [eid] [:db.fn/retractEntity eid]) blocks)))
  1166. (defn delete-file-pages!
  1167. [repo-url path]
  1168. (let [pages (get-file-pages repo-url path)]
  1169. (mapv (fn [eid] [:db.fn/retractEntity eid]) pages)))
  1170. (defn delete-file-tx
  1171. [repo-url file-path]
  1172. (->>
  1173. (concat
  1174. (delete-file-blocks! repo-url file-path)
  1175. (delete-file-pages! repo-url file-path)
  1176. [[:db.fn/retractEntity [:file/path file-path]]])
  1177. (remove nil?)))
  1178. (defn delete-file!
  1179. [repo-url file-path]
  1180. (db-utils/transact! repo-url (delete-file-tx repo-url file-path)))
  1181. (defn delete-pages-by-files
  1182. [files]
  1183. (let [pages (->> (mapv get-file-page files)
  1184. (remove nil?))]
  1185. (when (seq pages)
  1186. (mapv (fn [page] [:db.fn/retractEntity [:block/name page]]) (map string/lower-case pages)))))
  1187. (defn remove-all-aliases!
  1188. [repo]
  1189. (let [page-ids (->>
  1190. (d/q '[:find ?e
  1191. :where
  1192. [?e :block/alias]]
  1193. (conn/get-conn repo))
  1194. (apply concat)
  1195. (distinct))
  1196. tx-data (map (fn [page-id] [:db/retract page-id :block/alias]) page-ids)]
  1197. (when (seq tx-data)
  1198. (db-utils/transact! repo tx-data))))
  1199. (defn set-file-content!
  1200. [repo path content]
  1201. (when (and repo path)
  1202. (let [tx-data {:file/path path
  1203. :file/content content}]
  1204. (react/transact-react!
  1205. repo
  1206. [tx-data]
  1207. {:key [:file/content path]}))))
  1208. (defn get-pre-block
  1209. [repo page-id]
  1210. (-> (d/q '[:find (pull ?b [*])
  1211. :in $ ?page
  1212. :where
  1213. [?b :block/page ?page]
  1214. [?b :block/pre-block? true]]
  1215. (conn/get-conn repo)
  1216. page-id)
  1217. ffirst))
  1218. (defn get-namespace-pages
  1219. [repo namespace]
  1220. (assert (string? namespace))
  1221. (when-let [db (conn/get-conn repo)]
  1222. (when-not (string/blank? namespace)
  1223. (let [namespace (string/lower-case (string/trim namespace))
  1224. ids (->> (d/datoms db :aevt :block/name)
  1225. (filter (fn [datom]
  1226. (let [page (:v datom)]
  1227. (or
  1228. (= page namespace)
  1229. (string/starts-with? page (str namespace "/"))))))
  1230. (map :e))]
  1231. (when (seq ids)
  1232. (db-utils/pull-many repo
  1233. '[:db/id :block/name :block/original-name
  1234. {:block/file [:db/id :file/path]}]
  1235. ids))))))
  1236. (defn get-latest-changed-pages
  1237. [repo]
  1238. (->>
  1239. (d/q
  1240. '[:find [(pull ?page [:block/name :block/file :block/updated-at]) ...]
  1241. :where
  1242. [?page :block/name]]
  1243. (conn/get-conn repo))
  1244. (filter :block/file)
  1245. (sort-by :block/updated-at >)
  1246. (take 200)))
  1247. (defn refresh-recent-pages
  1248. []
  1249. (let [results (db-utils/get-key-value :recent/pages)]
  1250. (state/set-state! :editor/recent-pages results)))