fix: Accessing date page from Graph View breaks Journals (#11525)

related to https://github.com/logseq/db-test/issues/80
pull/11526/merge
Tienson Qin 2024-09-16 02:35:22 +08:00 committed by GitHub
parent 3f3ab05d0a
commit 23f8e9ca44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 206 additions and 335 deletions

View File

@ -234,7 +234,7 @@
#{:block/alias :block/tags})
(def read-only-properties
"Propery values that shouldn't be updated"
"Property values that shouldn't be updated"
#{:logseq.property/built-in?})
(assert (= db-attribute-properties

View File

@ -986,13 +986,7 @@
(seq focus-nodes)
(not (:orphan-pages? settings)))
(graph-handler/n-hops graph focus-nodes n-hops)
graph)
graph (update graph :links (fn [links]
(let [nodes (set (map :id (:nodes graph)))]
(remove (fn [link]
(and (not (nodes (:source link)))
(not (nodes (:target link)))))
links))))]
graph)]
[:div.relative#global-graph
(graph/graph-2d {:nodes (:nodes graph)
:links (:links graph)
@ -1013,7 +1007,7 @@
[nodes filters]
(if (seq filters)
(let [filter-patterns (map #(re-pattern (str "(?i)" (util/regex-escape %))) filters)]
(filter (fn [node] (some #(re-find % (:id node)) filter-patterns)) nodes))
(filter (fn [node] (some #(re-find % (:label node)) filter-patterns)) nodes))
nodes))
(rum/defcs global-graph < rum/reactive

View File

@ -1,27 +1,26 @@
(ns frontend.components.page-menu
(:require [frontend.commands :as commands]
(:require [electron.ipc :as ipc]
[frontend.commands :as commands]
[frontend.components.export :as export]
[frontend.config :as config]
[frontend.context.i18n :refer [t]]
[frontend.db :as db]
[logseq.db :as ldb]
[frontend.handler.common.developer :as dev-common-handler]
[frontend.handler.db-based.page :as db-page-handler]
[frontend.handler.file-sync :as file-sync-handler]
[frontend.handler.notification :as notification]
[frontend.handler.page :as page-handler]
[frontend.handler.common.developer :as dev-common-handler]
[frontend.handler.route :as route-handler]
[frontend.handler.db-based.page :as db-page-handler]
[frontend.handler.property.util :as pu]
[frontend.handler.shell :as shell]
[frontend.handler.user :as user-handler]
[frontend.mobile.util :as mobile-util]
[frontend.state :as state]
[logseq.shui.ui :as shui]
[promesa.core :as p]
[frontend.util :as util]
[frontend.util.page :as page-util]
[frontend.handler.shell :as shell]
[frontend.mobile.util :as mobile-util]
[electron.ipc :as ipc]
[frontend.config :as config]
[frontend.handler.user :as user-handler]
[frontend.handler.file-sync :as file-sync-handler]
[logseq.common.path :as path]
[frontend.handler.property.util :as pu]))
[logseq.db :as ldb]
[logseq.shui.ui :as shui]
[promesa.core :as p]))
(defn- delete-page!
[page]

View File

@ -211,7 +211,7 @@
[:div
(case @*mode
"namespace"
(let [items (sort (db-model/get-all-namespace-parents repo))]
(let [items (sort (map :block/title (db-model/get-all-namespace-parents repo)))]
(select items
(fn [{:keys [value]}]
(append-tree! *tree opts loc [:namespace value]))))
@ -276,7 +276,7 @@
"full text search"
(search (fn [v] (append-tree! *tree opts loc v))
(:toggle-fn opts))
(:toggle-fn opts))
"between"
(between (merge opts

View File

@ -1,12 +1,14 @@
(ns frontend.components.title
(:require [clojure.string :as string]
[frontend.db :as db]))
[frontend.db :as db]
[logseq.db :as ldb]))
(defn block-unique-title
"Multiple pages/objects may have the same `:block/title`.
Notice: this doesn't prevent for pages/objects that have the same tag or created by different clients."
[block]
(if (seq (:block/tags block))
(if (and (seq (:block/tags block))
(not (ldb/journal? block)))
(str (:block/title block)
" "
(string/join

View File

@ -18,8 +18,7 @@
[logseq.common.util :as common-util]
[logseq.common.util.date-time :as date-time-util]
[frontend.config :as config]
[logseq.db :as ldb]
[logseq.graph-parser.text :as text]))
[logseq.db :as ldb]))
;; TODO: extract to specific models and move data transform logic to the
;; corresponding handlers.
@ -30,11 +29,9 @@
(defn get-all-tagged-pages
[repo]
(d/q '[:find ?page-name ?tag
(d/q '[:find ?page ?tag
:where
[?page :block/tags ?e]
[?e :block/title ?tag]
[?page :block/name ?page-name]]
[?page :block/tags ?tag]]
(conn/get-db repo)))
(defn get-all-pages
@ -47,18 +44,6 @@
(->> (get-all-pages repo)
(map :block/title)))
(defn get-page-alias
[repo page-id]
(when-let [db (and repo (conn/get-db repo))]
(some->> (d/q '[:find ?alias
:in $ ?page-id
:where
[?page-id :block/alias ?alias]]
db
page-id)
db-utils/seq-flatten
distinct)))
(defn get-alias-source-page
"return the source page of an alias"
[repo alias-id]
@ -553,43 +538,36 @@ independent of format as format specific heading characters are stripped"
(when-let [db (conn/get-db repo)]
(let [pages (page-alias-set repo page-id)
ref-pages (d/q
'[:find ?ref-page ?ref-page-name
'[:find [?ref-page ...]
:in $ ?pages
:where
[(untuple ?pages) [?page ...]]
[?block :block/page ?page]
[?block :block/refs ?ref-page]
[?ref-page :block/name ?ref-page-name]]
[?block :block/refs ?ref-page]]
db
pages)]
(mapv (fn [[ref-page ref-page-name]]
[ref-page-name (get-page-alias repo ref-page)])
ref-pages))))
ref-pages)))
;; get pages who mentioned this page
(defn get-pages-that-mentioned-page
[repo page-id include-journals?]
(when (conn/get-db repo)
(let [pages (page-alias-set repo page-id)
mentioned-pages (->> (react/q repo [:frontend.worker.react/page<-pages page-id]
{:query-fn (fn [_]
(->>
(mapcat
(fn [id]
(let [page (db-utils/entity repo id)]
(->> (:block/_refs page)
(keep (fn [ref]
(:block/page ref)))
(util/distinct-by :db/id))))
pages)))}
{:use-cache? false})
react)]
(->> mentioned-pages
(keep (fn [page]
(when-not (and (not include-journals?) (ldb/journal? page))
page)))
(mapv (fn [page]
[(:block/name page) (get-page-alias-names repo (:db/id page))]))))))
mentioned-pages (->>
(mapcat
(fn [id]
(let [page (db-utils/entity repo id)]
(->> (:block/_refs page)
(keep (fn [ref]
(if (ldb/page? ref)
page
(:block/page ref)))))))
pages)
(util/distinct-by :db/id))]
(keep (fn [page]
(when-not (and (not include-journals?) (ldb/journal? page))
(:db/id page)))
mentioned-pages))))
(defn get-page-referenced-blocks-full
([page-id]
@ -822,87 +800,34 @@ independent of format as format specific heading characters are stripped"
(defn get-all-namespace-relation
[repo]
(d/q '[:find ?page-name ?parent
(d/q '[:find ?page ?parent
:where
[?page :block/name ?page-name]
[?page :block/namespace ?e]
[?e :block/title ?parent]]
[?page :block/namespace ?parent]]
(conn/get-db repo)))
(defn get-all-namespace-parents
[repo]
(->> (get-all-namespace-relation repo)
(map second)))
(def ns-char "/")
(def ns-re #"/")
(defn- get-parents-namespace-list
"Return list of parents namespace"
[page-namespace & nested-found]
(if (text/namespace-page? page-namespace)
(let [pre-nested-vec (drop-last (string/split page-namespace ns-re))
my-nested-found (if (nil? nested-found)
[]
nested-found)]
(if (= (count pre-nested-vec) 1)
(conj my-nested-found (nth pre-nested-vec 0))
(let [pre-nested-str (string/join ns-char pre-nested-vec)]
(recur pre-nested-str (conj my-nested-found pre-nested-str)))))
[]))
(defn- get-unnecessary-namespaces-name
"Return unnecessary namespace from a list of page's name"
[pages-list]
(->> pages-list
(remove nil?)
(mapcat get-parents-namespace-list)
distinct))
(defn- remove-nested-namespaces-link
"Remove relations between pages and their nested namespace"
[pages-relations]
(let [pages-relations-to-return (distinct (mapcat
identity
(for [item (for [a-link-from (mapv (fn [a-rel] (first a-rel)) pages-relations)]
[a-link-from (mapv
(fn [a-rel] (second a-rel))
(filterv
(fn [link-target] (= a-link-from (first link-target)))
pages-relations))])
:let [list-to (get item 1)
page (get item 0)
namespaces-to-remove (get-unnecessary-namespaces-name list-to)
list-to-without-nested-ns (filterv (fn [elem] (not (some #{elem} namespaces-to-remove))) list-to)
node-links (for [item-ok list-to-without-nested-ns]
[page item-ok])]]
(seq node-links))))]
pages-relations-to-return))
(let [db (conn/get-db repo)]
(->> (get-all-namespace-relation repo)
(map (fn [[_ ?parent]]
(db-utils/entity db ?parent))))))
;; Ignore files with empty blocks for now
(defn get-pages-relation
[repo with-journal?]
(when-let [db (conn/get-db repo)]
(let [q (if with-journal?
'[:find ?page ?ref-page-name
'[:find ?p ?ref-page
:where
[?p :block/name ?page]
[?block :block/page ?p]
[?block :block/refs ?ref-page]
[?ref-page :block/name ?ref-page-name]]
'[:find ?page ?ref-page-name
[?block :block/refs ?ref-page]]
'[:find ?p ?ref-page
:where
[?p :block/name ?page]
[?block :block/page ?p]
[(get-else $ ?p :block/type "N/A") ?type]
[(not= ?type "journal")]
[?block :block/page ?p]
[?block :block/refs ?ref-page]
[?ref-page :block/name ?ref-page-name]])]
(->>
(d/q q db)
(map (fn [[page ref-page-name]]
[page ref-page-name]))
(remove-nested-namespaces-link)))))
[?block :block/refs ?ref-page]])]
(d/q q db))))
(defn get-namespace-pages
"Accepts both sanitized and unsanitized namespaces"

View File

@ -3,6 +3,7 @@
[frontend.extensions.graph.pixi :as pixi]
[frontend.handler.route :as route-handler]
[frontend.colors :as colors]
[frontend.db :as db]
[goog.object :as gobj]
[rum.core :as rum]))
@ -42,7 +43,9 @@
(highlight-edges! graph node dark?))
(when-not drag?
(.unhoverNode ^js graph node)
(route-handler/redirect-to-page! node))))
(when-let [page (and (string? node)
(some-> (js/parseInt node) db/entity))]
(route-handler/redirect-to-page! (:block/uuid page))))))
(rum/defcs graph-2d <
(rum/local nil :ref)

View File

@ -40,7 +40,7 @@
(let [v (js/Math.abs (hash parent))]
(nth colors (mod v (count colors)))))
(.-color node)))
:label {:content (fn [node] (.-id node))
:label {:content (fn [node] (.-label node))
:type (.-TEXT (.-TextType Pixi-Graph))
:fontSize 12
:color (if dark? "rgba(255, 255, 255, 0.8)" "rgba(0, 0, 0, 0.8)")
@ -201,39 +201,39 @@
(clear-nodes! (:graph @*graph-instance))
(destroy-instance!))
(let [{:keys [nodes links style hover-style height register-handlers-fn dark? link-dist charge-strength charge-range]} (first (:rum/args state))
style (or style (default-style dark?))
hover-style (or hover-style (default-hover-style dark?))
graph (Graph.)
nodes-set (set (map :id nodes))
links (->>
(filter
(fn [link]
(and (nodes-set (:source link)) (nodes-set (:target link))))
links)
(distinct)) ;; #3331 (@zhaohui0923) seems caused by duplicated links. Why distinct doesn't work?
nodes (remove nil? nodes)
links (remove (fn [{:keys [source target]}] (or (nil? source) (nil? target))) links)
nodes-js (bean/->js nodes)
links-js (bean/->js links)
simulation (layout! nodes-js links-js link-dist charge-strength charge-range)]
style (or style (default-style dark?))
hover-style (or hover-style (default-hover-style dark?))
graph (Graph.)
nodes-set (set (map :id nodes))
links (->>
(filter
(fn [link]
(and (nodes-set (:source link)) (nodes-set (:target link))))
links)
(distinct)) ;; #3331 (@zhaohui0923) seems caused by duplicated links. Why distinct doesn't work?
nodes (remove nil? nodes)
links (remove (fn [{:keys [source target]}] (or (nil? source) (nil? target))) links)
nodes-js (bean/->js nodes)
links-js (bean/->js links)
simulation (layout! nodes-js links-js link-dist charge-strength charge-range)]
(doseq [node nodes-js]
(try (.addNode graph (.-id node) node)
(catch :default e
(js/console.error e))))
(catch :default e
(js/console.error e))))
(doseq [link links-js]
(let [source (.-id (.-source link))
target (.-id (.-target link))]
(try (.addEdge graph source target link)
(catch :default e
(js/console.error e)))))
(catch :default e
(js/console.error e)))))
(when-let [container-ref (:ref state)]
(let [pixi-graph (new (.-PixiGraph Pixi-Graph)
(bean/->js
{:container @container-ref
:graph graph
:style style
:hoverStyle hover-style
:height height}))]
(bean/->js
{:container @container-ref
:graph graph
:style style
:hoverStyle hover-style
:height height}))]
(reset! *graph-instance
{:graph graph
:pixi pixi-graph})

View File

@ -42,31 +42,32 @@
([title {:keys [redirect?]
:or {redirect? true}
:as options}]
(p/let [repo (state/get-current-repo)
conn (db/get-db repo false)
db-based? (config/db-based-graph? repo)
title (if (and db-based? (string/includes? title " #")) ; tagged page
(wrap-tags title)
title)
parsed-result (when db-based? (db-editor-handler/wrap-parse-block {:block/title title}))
title' (if (and db-based? (seq (:block/tags parsed-result)))
(string/trim (first
(or (common-util/split-first (str "#" db-content/page-ref-special-chars) (:block/title parsed-result))
(common-util/split-first (str "#" page-ref/left-brackets db-content/page-ref-special-chars) (:block/title parsed-result)))))
title)
options' (if db-based?
(update options :tags concat (:block/tags parsed-result))
options)
result (ui-outliner-tx/transact!
{:outliner-op :create-page}
(outliner-op/create-page! title' options'))
[_page-name page-uuid] (ldb/read-transit-str result)]
(when redirect?
(route-handler/redirect-to-page! page-uuid))
(let [page (db/get-page (or page-uuid title'))]
(when-let [first-block (ldb/get-first-child @conn (:db/id page))]
(block-handler/edit-block! first-block :max {:container-id :unknown-container}))
page))))
(when (string? title)
(p/let [repo (state/get-current-repo)
conn (db/get-db repo false)
db-based? (config/db-based-graph? repo)
title (if (and db-based? (string/includes? title " #")) ; tagged page
(wrap-tags title)
title)
parsed-result (when db-based? (db-editor-handler/wrap-parse-block {:block/title title}))
title' (if (and db-based? (seq (:block/tags parsed-result)))
(string/trim (first
(or (common-util/split-first (str "#" db-content/page-ref-special-chars) (:block/title parsed-result))
(common-util/split-first (str "#" page-ref/left-brackets db-content/page-ref-special-chars) (:block/title parsed-result)))))
title)
options' (if db-based?
(update options :tags concat (:block/tags parsed-result))
options)
result (ui-outliner-tx/transact!
{:outliner-op :create-page}
(outliner-op/create-page! title' options'))
[_page-name page-uuid] (ldb/read-transit-str result)]
(when redirect?
(route-handler/redirect-to-page! page-uuid))
(let [page (db/get-page (or page-uuid title'))]
(when-let [first-block (ldb/get-first-child @conn (:db/id page))]
(block-handler/edit-block! first-block :max {:container-id :unknown-container}))
page)))))
;; favorite fns
;; ============

View File

@ -11,82 +11,70 @@
[frontend.storage :as storage]
[logseq.graph-parser.db :as gp-db]
[logseq.db.sqlite.create-graph :as sqlite-create-graph]
[logseq.common.util :as common-util]
[logseq.db :as ldb]
[frontend.components.title :as title]))
(defn- build-links
[links]
(map (fn [[from to]]
{:source from
:target to})
links))
(keep (fn [[from to]]
(when (and from to)
{:source (str from)
:target (str to)}))
links))
(defn- build-nodes
[dark? current-page page-links tags nodes namespaces]
(let [parents (set (map last namespaces))
current-page (or current-page "")
pages (set (flatten nodes))]
pages (util/distinct-by :db/id nodes)]
(->>
pages
(remove nil?)
(mapv (fn [p]
(let [p (str p)
current-page? (= p current-page)
(let [page-title (:block/title p)
current-page? (= page-title current-page)
color (case [dark? current-page?] ; FIXME: Put it into CSS
[false false] "#999"
[false true] "#045591"
[true false] "#93a1a1"
[true true] "#ffffff")
color (if (contains? tags p)
color (if (contains? tags (:db/id p))
(if dark? "orange" "green")
color)
n (get page-links p 1)
n (get page-links page-title 1)
size (int (* 8 (max 1.0 (js/Math.cbrt n))))]
(cond->
{:id p
:label p
:size size
:color color}
(contains? parents p)
(assoc :parent true))))))))
(cond->
{:id (str (:db/id p))
:label (title/block-unique-title p)
:size size
:color color
:block/created-at (:block/created-at p)}
(contains? parents (:db/id p))
(assoc :parent true))))))))
;; slow
(defn- uuid-or-asset?
[id]
(or (util/uuid-string? id)
(string/starts-with? id "../assets/")
(= id "..")
(string/starts-with? id "assets/")
(string/ends-with? id ".gif")
(string/ends-with? id ".jpg")
(string/ends-with? id ".png")))
[label]
(or (util/uuid-string? label)
(string/starts-with? label "../assets/")
(= label "..")
(string/starts-with? label "assets/")
(string/ends-with? label ".gif")
(string/ends-with? label ".jpg")
(string/ends-with? label ".png")))
(defn- remove-uuids-and-files!
[nodes]
(remove
(fn [node] (uuid-or-asset? (:id node)))
(fn [node] (uuid-or-asset? (:label node)))
nodes))
(defn- normalize-page-name
[{:keys [nodes links page-name->title]}]
(let [links (->>
(map
(fn [{:keys [source target]}]
(let [source (get page-name->title source)
target (get page-name->title target)]
(when (and source target)
{:source source :target target})))
links)
(remove nil?))
nodes (->> (remove-uuids-and-files! nodes)
[{:keys [nodes links]}]
(let [nodes' (->> (remove-uuids-and-files! nodes)
(util/distinct-by (fn [node] (:id node)))
(map (fn [node]
(if-let [title (get page-name->title (:id node))]
(assoc node :id title :label title)
nil)))
(remove nil?))]
{:nodes nodes
{:nodes nodes'
:links links}))
(defn build-global-graph
@ -95,13 +83,11 @@
current-page (or (:block/name (db/get-current-page)) "")]
(when-let [repo (state/get-current-repo)]
(let [relation (db/get-pages-relation repo journal?)
tagged-pages (map (fn [[x y]] [x (common-util/page-name-sanity-lc y)]) (db-model/get-all-tagged-pages repo))
namespaces (map (fn [[x y]] [x (common-util/page-name-sanity-lc y)]) (db/get-all-namespace-relation repo))
tagged-pages (db-model/get-all-tagged-pages repo)
namespaces (db/get-all-namespace-relation repo)
tags (set (map second tagged-pages))
full-pages (db/get-all-pages repo)
full-pages-map (into {} (map (juxt :block/name identity) full-pages))
all-pages (map title/block-unique-title full-pages)
page-name->title (zipmap (map :block/name full-pages) all-pages)
db-based? (config/db-based-graph? repo)
created-ats (map :block/created-at full-pages)
;; build up nodes
@ -113,26 +99,23 @@
(remove ldb/journal?)
(not excluded-pages?)
(remove (fn [p] (true? (pu/get-block-property-value p :logseq.property/exclude-from-graph-view)))))
links (concat (seq relation)
(seq tagged-pages)
(seq namespaces))
linked (set (flatten links))
build-in-pages (->> (if (config/db-based-graph? repo) sqlite-create-graph/built-in-pages-names gp-db/built-in-pages-names)
links (concat relation tagged-pages namespaces)
linked (set (mapcat identity links))
build-in-pages (->> (if db-based? sqlite-create-graph/built-in-pages-names gp-db/built-in-pages-names)
(map string/lower-case)
set)
nodes (cond->> (map :block/name full-pages')
nodes (cond->> full-pages'
(not builtin-pages?)
(remove (fn [p] (contains? build-in-pages (string/lower-case p))))
(remove #(contains? build-in-pages (:block/name %)))
(not orphan-pages?)
(filter #(contains? linked (string/lower-case %))))
(filter #(contains? linked (:db/id %))))
links (map (fn [[x y]] [(str x) (str y)]) links)
page-links (reduce (fn [m [k v]] (-> (update m k inc)
(update v inc))) {} links)
links (build-links (remove (fn [[_ to]] (nil? to)) links))
links (build-links links)
nodes (build-nodes dark? (string/lower-case current-page) page-links tags nodes namespaces)]
(-> {:nodes (map #(assoc % :block/created-at (get-in full-pages-map [(:id %) :block/created-at])) nodes)
:links links
:page-name->title page-name->title}
(-> {:nodes nodes
:links links}
normalize-page-name
(assoc :all-pages
{:created-at-min (apply min created-ats)
@ -144,95 +127,79 @@
(when-let [repo (state/get-current-repo)]
(let [page-entity (db/get-page page)
page-id (:db/id page-entity)
tags (if (config/db-based-graph? repo)
(set (map #(:block/name (db/entity repo (:db/id %)))
(:block/tags page-entity)))
(:tags (:block/properties page-entity)))
tags (remove #(= page %) tags)
tags (when (config/db-based-graph? repo)
(set (map :db/id (:block/tags page-entity))))
tags (set (remove #(= page-id %) tags))
ref-pages (db/get-page-referenced-pages repo page-id)
mentioned-pages (db/get-pages-that-mentioned-page repo page-id show-journal)
namespaces (map (fn [[x y]] [x (common-util/page-name-sanity-lc y)]) (db/get-all-namespace-relation repo))
namespaces (db/get-all-namespace-relation repo)
links (concat
namespaces
(map (fn [[p _aliases]]
[page p]) ref-pages)
(map (fn [[p _aliases]]
[p page]) mentioned-pages)
(map (fn [ref-page]
[page-id ref-page]) ref-pages)
(map (fn [page]
[page-id page]) mentioned-pages)
(map (fn [tag]
[page tag])
[page-id tag])
tags))
other-pages (->> (concat (map first ref-pages)
(map first mentioned-pages))
other-pages (->> (concat ref-pages mentioned-pages)
(remove nil?)
(set))
other-pages-links (mapcat
(fn [page]
(let [page-id (:db/id (db/get-page page))
ref-pages (-> (map first (db/get-page-referenced-pages repo page-id))
(fn [page-id]
(let [ref-pages (-> (db/get-page-referenced-pages repo page-id)
(set)
(set/intersection other-pages))
mentioned-pages (-> (map first (db/get-pages-that-mentioned-page repo page-id show-journal))
mentioned-pages (-> (db/get-pages-that-mentioned-page repo page-id show-journal)
(set)
(set/intersection other-pages))]
(concat
(map (fn [p] [page p]) ref-pages)
(map (fn [p] [p page]) mentioned-pages))))
(map (fn [p] [page-id p]) ref-pages)
(map (fn [p] [p page-id]) mentioned-pages))))
other-pages)
links (->> (concat links other-pages-links)
(remove nil?)
(distinct)
(build-links))
nodes (->> (concat
[page]
(map first ref-pages)
(map first mentioned-pages)
[page-id]
ref-pages
mentioned-pages
tags)
(remove nil?)
(distinct))
nodes (build-nodes dark? page links (set tags) nodes namespaces)
full-pages (db/get-all-pages repo)
all-pages (map common-util/get-page-title full-pages)
page-name->title (zipmap (map :block/name full-pages) all-pages)]
(map db/entity)
(util/distinct-by :db/id))
nodes (build-nodes dark? page links tags nodes namespaces)]
(normalize-page-name
{:nodes nodes
:links links
:page-name->title page-name->title})))))
:links links})))))
(defn build-block-graph
"Builds a citation/reference graph for a given block uuid."
[block theme]
[block-uuid theme]
(when-let [repo (state/get-current-repo)]
(let [dark? (= "dark" theme)
ref-blocks (db/get-block-referenced-blocks block)
namespaces (map (fn [[x y]] [x (common-util/page-name-sanity-lc y)]) (db/get-all-namespace-relation repo))
other-blocks (->> (concat (map first ref-blocks))
(remove nil?)
(set))
other-blocks-links (mapcat
(fn [block]
(let [ref-blocks (-> (map first (db/get-block-referenced-blocks block))
(set)
(set/intersection other-blocks))]
(concat
(map (fn [p] [block p]) ref-blocks))))
other-blocks)
links (concat
(->> other-blocks-links
(remove nil?)
(distinct)
(build-links))
namespaces)
nodes (->> (concat
[block]
(map first ref-blocks))
(remove nil?)
(distinct)
(when-let [block (and (uuid? block-uuid) (db/entity [:block/uuid block-uuid]))]
(let [dark? (= "dark" theme)
ref-blocks (->> (concat (:block/_refs block) (:block/refs block))
(map (fn [b]
(if (ldb/page? b) b (:block/page b))))
(remove (fn [node] (= (:db/id block) (:db/id node))))
(util/distinct-by :db/id))
namespaces (db/get-all-namespace-relation repo)
links (->> (concat
namespaces
(map (fn [p] [(:db/id block) (:db/id p)]) ref-blocks))
(remove nil?)
(distinct)
(build-links))
nodes (->> (cons block ref-blocks)
distinct
;; FIXME: get block tags
)
nodes (build-nodes dark? block links #{} nodes namespaces)]
(normalize-page-name
{:nodes nodes
:links links}))))
)
nodes (build-nodes dark? block links #{} nodes namespaces)]
(normalize-page-name
{:nodes nodes
:links links})))))
(defn n-hops
"Get all nodes that are n hops from nodes (a collection of node ids)"

View File

@ -73,30 +73,10 @@
2 (count a-ref-blocks)
#{"ab" "ac"} (set alias-names))))
(deftest remove-links-for-each-level-of-the-namespaces
(load-test-files [{:file/path "pages/generic page.md"
:file/content "tags:: [[one/two/tree]], one/two
- link to ns [[one]]
- link to page one [[page ONE]]"}])
(is (= '("one/two/tree" "tags" "page one")
(map second (model/get-pages-relation test-helper/test-db true)))
"(get-pages-relation) Must be only ns one/two/tree")
(is (= '("one/two/tree" "page one")
(map second (#'model/remove-nested-namespaces-link [["generic page" "one/two/tree"]
["generic page" "one/two"]
["generic page" "one"]
["generic page" "page one"]])))
"(model/remove-nested-namespaces-link) Must be only ns one/two/tree")
(is (= '("one/two/tree" "one/two" "one")
(#'model/get-parents-namespace-list "one/two/tree/four"))
"Must be one/two/tree one/two one")
(is (= '("one/two" "one")
(#'model/get-unnecessary-namespaces-name '("one/two/tree" "one" "one/two" "non nested tag" "non nested link")))
"Must be one/two one"))
(defn- page-mention-check?
[page-name include-journals?]
(->> (model/get-pages-that-mentioned-page test-helper/test-db (:db/id (db/entity [:block/name page-name])) include-journals?)
(map (fn [id] (:block/name (db/entity id))))))
(deftest get-pages-that-mentioned-page-with-show-journal
(load-test-files [{:file/path "journals/2020_08_15.md"
@ -112,19 +92,19 @@
:file/content "- link to page one [[page ONE]]"}])
(is (= '("sep 18th, 2020" "aug 15th, 2020" "generic page")
(map first (model/get-pages-that-mentioned-page test-helper/test-db (:db/id (db/entity [:block/name "page one"])) true)))
(page-mention-check? "page one" true))
"Must be 'generic page' + 2 journals")
(is (= '("generic page")
(map first (model/get-pages-that-mentioned-page test-helper/test-db (:db/id (db/entity [:block/name "page one"])) false)))
(page-mention-check? "page one" false))
"Must be only 'generic page'")
(is (= '("aug 15th, 2020")
(map first (model/get-pages-that-mentioned-page test-helper/test-db (:db/id (db/entity [:block/name "generic page"])) true)))
(page-mention-check? "generic page" true))
"Must show only 'aug 15th, 2020'")
(is (= '()
(map first (model/get-pages-that-mentioned-page test-helper/test-db (:db/id (db/entity [:block/name "generic page"])) false)))
(page-mention-check? "generic page" false))
"Must be empty"))
(deftest entity-query-should-return-nil-if-id-not-exists