|
|
@@ -1,64 +1,27 @@
|
|
|
(ns frontend.db.model
|
|
|
"Core db functions."
|
|
|
- ;; TODO: Remove this config once how repos are passed to this ns are standardized
|
|
|
- {:clj-kondo/config {:linters {:unused-binding {:level :off}}}}
|
|
|
(:require [clojure.set :as set]
|
|
|
[clojure.string :as string]
|
|
|
[clojure.walk :as walk]
|
|
|
[datascript.core :as d]
|
|
|
- [frontend.common.file-based.db :as common-file-db]
|
|
|
[frontend.common.graph-view :as graph-view]
|
|
|
[frontend.config :as config]
|
|
|
[frontend.date :as date]
|
|
|
[frontend.db.conn :as conn]
|
|
|
+ [frontend.db.file-based.model :as file-model]
|
|
|
[frontend.db.react :as react]
|
|
|
[frontend.db.utils :as db-utils]
|
|
|
[frontend.state :as state]
|
|
|
[frontend.util :as util :refer [react]]
|
|
|
[logseq.common.util :as common-util]
|
|
|
- [logseq.common.util.date-time :as date-time-util]
|
|
|
[logseq.db :as ldb]
|
|
|
[logseq.db.frontend.class :as db-class]
|
|
|
[logseq.db.frontend.content :as db-content]
|
|
|
- [logseq.db.frontend.rules :as rules]
|
|
|
- [logseq.graph-parser.db :as gp-db]
|
|
|
- [logseq.shui.hooks :as hooks]))
|
|
|
+ [logseq.db.frontend.rules :as rules]))
|
|
|
|
|
|
;; TODO: extract to specific models and move data transform logic to the
|
|
|
;; corresponding handlers.
|
|
|
|
|
|
-(def file-graph-block-attrs
|
|
|
- "In file graphs, use it to replace '*' for datalog queries"
|
|
|
- '[:db/id
|
|
|
- :block/uuid
|
|
|
- :block/parent
|
|
|
- :block/order
|
|
|
- :block/collapsed?
|
|
|
- :block/format
|
|
|
- :block/refs
|
|
|
- :block/_refs
|
|
|
- :block/path-refs
|
|
|
- :block/tags
|
|
|
- :block/link
|
|
|
- :block/title
|
|
|
- :block/marker
|
|
|
- :block/priority
|
|
|
- :block/properties
|
|
|
- :block/properties-order
|
|
|
- :block/properties-text-values
|
|
|
- :block/pre-block?
|
|
|
- :block/scheduled
|
|
|
- :block/deadline
|
|
|
- :block/repeated?
|
|
|
- :block/created-at
|
|
|
- :block/updated-at
|
|
|
- ;; TODO: remove this in later releases
|
|
|
- :block/heading-level
|
|
|
- :block/file
|
|
|
- :logseq.property/parent
|
|
|
- {:block/page [:db/id :block/name :block/title :block/uuid :block/journal-day :block/type]}
|
|
|
- {:block/_parent ...}])
|
|
|
-
|
|
|
(def hidden-page? ldb/hidden?)
|
|
|
|
|
|
(defn get-alias-source-page
|
|
|
@@ -67,21 +30,6 @@
|
|
|
(when-let [db (conn/get-db repo)]
|
|
|
(ldb/get-alias-source-page db alias-id)))
|
|
|
|
|
|
-(defn get-files-blocks
|
|
|
- [repo-url paths]
|
|
|
- (let [paths (set paths)
|
|
|
- pred (fn [_db e]
|
|
|
- (contains? paths e))]
|
|
|
- (-> (d/q '[:find ?block
|
|
|
- :in $ ?pred
|
|
|
- :where
|
|
|
- [?file :file/path ?path]
|
|
|
- [(?pred $ ?path)]
|
|
|
- [?p :block/file ?file]
|
|
|
- [?block :block/page ?p]]
|
|
|
- (conn/get-db repo-url) pred)
|
|
|
- db-utils/seq-flatten)))
|
|
|
-
|
|
|
(defn file-exists?
|
|
|
[repo path]
|
|
|
(when (and repo path)
|
|
|
@@ -197,8 +145,7 @@ independent of format as format specific heading characters are stripped"
|
|
|
|
|
|
(defn get-page-alias-names
|
|
|
[repo page-id]
|
|
|
- (let [page (db-utils/entity page-id)
|
|
|
- alias-ids (->> (page-alias-set repo page-id)
|
|
|
+ (let [alias-ids (->> (page-alias-set repo page-id)
|
|
|
(remove #{page-id}))]
|
|
|
(when (seq alias-ids)
|
|
|
(map (fn [id] (:block/title (db-utils/entity id))) alias-ids))))
|
|
|
@@ -234,21 +181,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
(when-let [id (:db/id e)]
|
|
|
(db-utils/entity id))))))))
|
|
|
|
|
|
-(defn sub-entity
|
|
|
- "Used for react function components"
|
|
|
- [entity* watch-id]
|
|
|
- (let [id (:db/id entity*)
|
|
|
- *ref (sub-block id {:ref? true})
|
|
|
- [entity set-entity!] (hooks/use-state @*ref)]
|
|
|
- (add-watch *ref watch-id (fn [_ _ _ new-value]
|
|
|
- (set-entity! new-value)))
|
|
|
- (hooks/use-effect!
|
|
|
- (fn []
|
|
|
- #(remove-watch *ref watch-id))
|
|
|
- [])
|
|
|
-
|
|
|
- [entity set-entity!]))
|
|
|
-
|
|
|
(defn sort-by-order-recursive
|
|
|
[form]
|
|
|
(walk/postwalk (fn [f]
|
|
|
@@ -261,33 +193,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
f))
|
|
|
form))
|
|
|
|
|
|
-;; File-based only
|
|
|
-;; Diverged of get-sorted-page-block-ids
|
|
|
-(defn get-sorted-page-block-ids-and-levels
|
|
|
- "page-name: the page name, original name
|
|
|
- return: a list with elements in:
|
|
|
- :id - a list of block ids, sorted by :block/order
|
|
|
- :level - the level of the block, 1 for root, 2 for children of root, etc."
|
|
|
- [page-name]
|
|
|
- {:pre [(string? page-name)]}
|
|
|
- (let [root (ldb/get-page (conn/get-db) page-name)]
|
|
|
- (loop [result []
|
|
|
- children (sort-by-order (:block/_parent root))
|
|
|
- ;; BFS log of walking depth
|
|
|
- levels (repeat (count children) 1)]
|
|
|
- (if (seq children)
|
|
|
- (let [child (first children)
|
|
|
- cur-level (first levels)
|
|
|
- next-children (sort-by-order (:block/_parent child))]
|
|
|
- (recur (conj result {:id (:db/id child) :level cur-level})
|
|
|
- (concat
|
|
|
- next-children
|
|
|
- (rest children))
|
|
|
- (concat
|
|
|
- (repeat (count next-children) (inc cur-level))
|
|
|
- (rest levels))))
|
|
|
- result))))
|
|
|
-
|
|
|
(defn has-children?
|
|
|
([block-id]
|
|
|
(has-children? (conn/get-db) block-id))
|
|
|
@@ -421,59 +326,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
(let [db (conn/get-db repo)]
|
|
|
(ldb/get-block-and-children db block-uuid opts)))
|
|
|
|
|
|
-(defn get-file-page
|
|
|
- ([file-path]
|
|
|
- (get-file-page file-path true))
|
|
|
- ([file-path title?]
|
|
|
- (when-let [repo (state/get-current-repo)]
|
|
|
- (when-let [db (conn/get-db repo)]
|
|
|
- (some->
|
|
|
- (d/q
|
|
|
- (if title?
|
|
|
- '[:find ?page-name
|
|
|
- :in $ ?path
|
|
|
- :where
|
|
|
- [?file :file/path ?path]
|
|
|
- [?page :block/file ?file]
|
|
|
- [?page :block/title ?page-name]]
|
|
|
- '[:find ?page-name
|
|
|
- :in $ ?path
|
|
|
- :where
|
|
|
- [?file :file/path ?path]
|
|
|
- [?page :block/file ?file]
|
|
|
- [?page :block/name ?page-name]])
|
|
|
- db file-path)
|
|
|
- db-utils/seq-flatten
|
|
|
- first)))))
|
|
|
-
|
|
|
-(defn get-page-file
|
|
|
- ([page-name]
|
|
|
- (get-page-file (state/get-current-repo) page-name))
|
|
|
- ([repo page-name]
|
|
|
- (when-let [db (conn/get-db repo)]
|
|
|
- (gp-db/get-page-file db page-name))))
|
|
|
-
|
|
|
-(defn get-block-file-path
|
|
|
- [block]
|
|
|
- (when-let [page-id (:db/id (:block/page block))]
|
|
|
- (:file/path (:block/file (db-utils/entity page-id)))))
|
|
|
-
|
|
|
-(defn get-file-page-id
|
|
|
- [file-path]
|
|
|
- (when-let [repo (state/get-current-repo)]
|
|
|
- (when-let [db (conn/get-db repo)]
|
|
|
- (some->
|
|
|
- (d/q
|
|
|
- '[:find ?page
|
|
|
- :in $ ?path
|
|
|
- :where
|
|
|
- [?file :file/path ?path]
|
|
|
- [?page :block/name]
|
|
|
- [?page :block/file ?file]]
|
|
|
- db file-path)
|
|
|
- db-utils/seq-flatten
|
|
|
- first))))
|
|
|
-
|
|
|
(defn get-page
|
|
|
[page-id-name-or-uuid]
|
|
|
(when page-id-name-or-uuid
|
|
|
@@ -522,27 +374,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
(:block/name page-entity)
|
|
|
page-name)))))))
|
|
|
|
|
|
-(defn get-journals-length
|
|
|
- []
|
|
|
- (let [today (date-time-util/date->int (js/Date.))]
|
|
|
- (if (config/db-based-graph?)
|
|
|
- (d/q '[:find (count ?page) .
|
|
|
- :in $ ?today
|
|
|
- :where
|
|
|
- [?page :block/tags :logseq.class/Journal]
|
|
|
- [?page :block/journal-day ?journal-day]
|
|
|
- [(<= ?journal-day ?today)]]
|
|
|
- (conn/get-db (state/get-current-repo))
|
|
|
- today)
|
|
|
- (d/q '[:find (count ?page) .
|
|
|
- :in $ ?today
|
|
|
- :where
|
|
|
- [?page :block/type "journal"]
|
|
|
- [?page :block/journal-day ?journal-day]
|
|
|
- [(<= ?journal-day ?today)]]
|
|
|
- (conn/get-db (state/get-current-repo))
|
|
|
- today))))
|
|
|
-
|
|
|
(defn get-latest-journals
|
|
|
([n]
|
|
|
(get-latest-journals (state/get-current-repo) n))
|
|
|
@@ -558,10 +389,8 @@ independent of format as format specific heading characters are stripped"
|
|
|
|
|
|
(defn get-page-referenced-blocks-full
|
|
|
([page-id]
|
|
|
- (get-page-referenced-blocks-full (state/get-current-repo) page-id nil))
|
|
|
- ([page-id options]
|
|
|
- (get-page-referenced-blocks-full (state/get-current-repo) page-id options))
|
|
|
- ([repo page-id options]
|
|
|
+ (get-page-referenced-blocks-full (state/get-current-repo) page-id))
|
|
|
+ ([repo page-id]
|
|
|
(when (and repo page-id)
|
|
|
(when-let [db (conn/get-db repo)]
|
|
|
(let [pages (page-alias-set repo page-id)
|
|
|
@@ -574,7 +403,7 @@ independent of format as format specific heading characters are stripped"
|
|
|
[?block :block/path-refs ?ref-page]]
|
|
|
db
|
|
|
pages
|
|
|
- (butlast file-graph-block-attrs))
|
|
|
+ (butlast file-model/file-graph-block-attrs))
|
|
|
(remove (fn [block] (= page-id (:db/id (:block/page block)))))
|
|
|
db-utils/group-by-page
|
|
|
(map (fn [[k blocks]]
|
|
|
@@ -585,10 +414,8 @@ independent of format as format specific heading characters are stripped"
|
|
|
|
|
|
(defn get-referenced-blocks
|
|
|
([eid]
|
|
|
- (get-referenced-blocks (state/get-current-repo) eid nil))
|
|
|
- ([eid options]
|
|
|
- (get-referenced-blocks (state/get-current-repo) eid options))
|
|
|
- ([repo eid options]
|
|
|
+ (get-referenced-blocks (state/get-current-repo) eid))
|
|
|
+ ([repo eid]
|
|
|
(when repo
|
|
|
(when (conn/get-db repo)
|
|
|
(let [entity (db-utils/entity eid)
|
|
|
@@ -606,14 +433,12 @@ independent of format as format specific heading characters are stripped"
|
|
|
(util/distinct-by :db/id)))))))
|
|
|
|
|
|
(defn get-block-referenced-blocks
|
|
|
- ([block-id]
|
|
|
- (get-block-referenced-blocks block-id {}))
|
|
|
- ([block-id options]
|
|
|
- (when-let [repo (state/get-current-repo)]
|
|
|
- (when (conn/get-db repo)
|
|
|
- (->> (get-referenced-blocks repo block-id options)
|
|
|
- (sort-by-order-recursive)
|
|
|
- db-utils/group-by-page)))))
|
|
|
+ [block-id]
|
|
|
+ (when-let [repo (state/get-current-repo)]
|
|
|
+ (when (conn/get-db repo)
|
|
|
+ (->> (get-referenced-blocks repo block-id)
|
|
|
+ (sort-by-order-recursive)
|
|
|
+ db-utils/group-by-page))))
|
|
|
|
|
|
(defn journal-page?
|
|
|
"sanitized page-name only"
|
|
|
@@ -635,37 +460,10 @@ independent of format as format specific heading characters are stripped"
|
|
|
[?refed-b :block/uuid ?refed-uuid]
|
|
|
[?referee-b :block/refs ?refed-b]] db)))
|
|
|
|
|
|
-(defn delete-blocks
|
|
|
- [repo-url files _delete-page?]
|
|
|
- (when (seq files)
|
|
|
- (let [blocks (->> (get-files-blocks repo-url files)
|
|
|
- (remove nil?))]
|
|
|
- (mapv (fn [eid] [:db.fn/retractEntity eid]) blocks))))
|
|
|
-
|
|
|
(defn delete-files
|
|
|
[files]
|
|
|
(mapv (fn [path] [:db.fn/retractEntity [:file/path path]]) files))
|
|
|
|
|
|
-;; file-based only so it's safe to use :block/name lookup refs here
|
|
|
-(defn delete-pages-by-files
|
|
|
- [files]
|
|
|
- (let [pages (->> (mapv get-file-page files)
|
|
|
- (remove nil?))]
|
|
|
- (when (seq pages)
|
|
|
- (mapv (fn [page] [:db.fn/retractEntity [:block/name page]]) (map util/page-name-sanity-lc pages)))))
|
|
|
-
|
|
|
-;; TODO: check whether this works when adding pdf back on Web
|
|
|
-(defn get-pre-block
|
|
|
- [repo page-id]
|
|
|
- (-> (d/q '[:find (pull ?b [*])
|
|
|
- :in $ ?page
|
|
|
- :where
|
|
|
- [?b :block/page ?page]
|
|
|
- [?b :block/pre-block? true]]
|
|
|
- (conn/get-db repo)
|
|
|
- page-id)
|
|
|
- ffirst))
|
|
|
-
|
|
|
(defn whiteboard-page?
|
|
|
"Given a page entity, page object or page name, check if it is a whiteboard page"
|
|
|
[page]
|
|
|
@@ -674,17 +472,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
page)]
|
|
|
(ldb/whiteboard? page)))
|
|
|
|
|
|
-(comment
|
|
|
- (defn get-orphaned-pages
|
|
|
- [opts]
|
|
|
- (let [db (conn/get-db)]
|
|
|
- (ldb/get-orphaned-pages db
|
|
|
- (merge opts
|
|
|
- {:built-in-pages-names
|
|
|
- (if (config/db-based-graph? (state/get-current-repo))
|
|
|
- sqlite-create-graph/built-in-pages-names
|
|
|
- gp-db/built-in-pages-names)})))))
|
|
|
-
|
|
|
;; FIXME: use `Untitled` instead of UUID for db based graphs
|
|
|
(defn untitled-page?
|
|
|
[page-name]
|
|
|
@@ -771,64 +558,6 @@ independent of format as format specific heading characters are stripped"
|
|
|
(:block/_tags class))
|
|
|
(remove ldb/hidden?))))
|
|
|
|
|
|
-(defn get-all-namespace-relation
|
|
|
- [repo]
|
|
|
- (gp-db/get-all-namespace-relation (conn/get-db repo)))
|
|
|
-
|
|
|
-(defn get-all-namespace-parents
|
|
|
- [repo]
|
|
|
- (let [db (conn/get-db repo)]
|
|
|
- (->> (get-all-namespace-relation repo)
|
|
|
- (map (fn [[_ ?parent]]
|
|
|
- (db-utils/entity db ?parent))))))
|
|
|
-
|
|
|
-(defn get-namespace-pages
|
|
|
- "Accepts both sanitized and unsanitized namespaces"
|
|
|
- [repo namespace]
|
|
|
- (common-file-db/get-namespace-pages (conn/get-db repo) namespace))
|
|
|
-
|
|
|
-(defn- tree [flat-col root]
|
|
|
- (let [sort-fn #(sort-by :block/name %)
|
|
|
- children (group-by :block/namespace flat-col)
|
|
|
- namespace-children (fn namespace-children [parent-id]
|
|
|
- (map (fn [m]
|
|
|
- (assoc m :namespace/children
|
|
|
- (sort-fn (namespace-children {:db/id (:db/id m)}))))
|
|
|
- (sort-fn (get children parent-id))))]
|
|
|
- (namespace-children root)))
|
|
|
-
|
|
|
-(defn get-namespace-hierarchy
|
|
|
- "Unsanitized namespaces"
|
|
|
- [repo namespace]
|
|
|
- (let [children (get-namespace-pages repo namespace)
|
|
|
- namespace-id (:db/id (db-utils/entity [:block/name (util/page-name-sanity-lc namespace)]))
|
|
|
- root {:db/id namespace-id}
|
|
|
- col (conj children root)]
|
|
|
- (tree col root)))
|
|
|
-
|
|
|
-(defn get-page-namespace
|
|
|
- [repo page]
|
|
|
- (:block/namespace (db-utils/entity repo [:block/name (util/page-name-sanity-lc page)])))
|
|
|
-
|
|
|
-(defn get-page-namespace-routes
|
|
|
- [repo page]
|
|
|
- (assert (string? page))
|
|
|
- (when-let [db (conn/get-db repo)]
|
|
|
- (when-not (string/blank? page)
|
|
|
- (let [page (util/page-name-sanity-lc (string/trim page))
|
|
|
- page-exist? (db-utils/entity repo [:block/name page])
|
|
|
- ids (if page-exist?
|
|
|
- '()
|
|
|
- (->> (d/datoms db :aevt :block/name)
|
|
|
- (filter (fn [datom]
|
|
|
- (string/ends-with? (:v datom) (str "/" page))))
|
|
|
- (map :e)))]
|
|
|
- (when (seq ids)
|
|
|
- (db-utils/pull-many repo
|
|
|
- '[:db/id :block/name :block/title
|
|
|
- {:block/file [:db/id :file/path]}]
|
|
|
- ids))))))
|
|
|
-
|
|
|
(comment
|
|
|
;; For debugging
|
|
|
(defn get-all-blocks
|