Merge branch 'feat/db' into enhance/reference-view

This commit is contained in:
Gabriel Horner
2025-02-21 15:33:40 -05:00
30 changed files with 319 additions and 172 deletions

View File

@@ -0,0 +1,37 @@
(ns frontend.common.file-based.db
"Database fns for file graphs that are used by worker and frontend"
(:require [clojure.string :as string]
[datascript.core :as d]
[logseq.common.util :as common-util]
[logseq.db.file-based.rules :as file-rules]))
(defn get-namespace-pages
"Accepts both sanitized and unsanitized namespaces"
[db namespace']
(assert (string? namespace'))
(let [namespace'' (common-util/page-name-sanity-lc namespace')
pull-attrs [:db/id :block/name :block/original-name :block/namespace
{:block/file [:db/id :file/path]}]]
(d/q
[:find [(list 'pull '?c pull-attrs) '...]
:in '$ '% '?namespace
:where
['?p :block/name '?namespace]
(list 'namespace '?p '?c)]
db
(:namespace file-rules/rules)
namespace'')))
(defn get-pages-by-name-partition
[db partition']
(when-not (string/blank? partition')
(let [partition'' (common-util/page-name-sanity-lc (string/trim partition'))
ids (->> (d/datoms db :aevt :block/name)
(filter (fn [datom]
(let [page (:v datom)]
(string/includes? page partition''))))
(map :e))]
(when (seq ids)
(d/pull-many db
'[:db/id :block/name :block/title]
ids)))))

View File

@@ -5,7 +5,13 @@
[clojure.core.async :as a]
[lambdaisland.glogi :as log]
[missionary.core :as m]
[promesa.protocols :as pt]))
[promesa.protocols :as pt])
(:import [missionary Cancelled]))
(extend-type Cancelled
IPrintWithWriter
(-pr-writer [o w _opts]
(write-all w "#missionary.Cancelled \"" (.-message o) "\"")))
(defn continue-flow
"ensure f is a continuous flow"

View File

@@ -39,15 +39,8 @@
(defn- get-all-pages
[]
(let [pages (->> (page-handler/get-all-pages (state/get-current-repo))
(map (fn [p] (assoc p :id (:db/id p)))))]
(if (config/db-based-graph? (state/get-current-repo))
pages
;; FIXME: Remove when bug with page named 'page with #tag' is fixed
(let [buggy-pages (remove :block/type pages)]
(when (seq buggy-pages)
(js/console.error "The following pages aren't displayed because they don't have a :block/type" buggy-pages))
(filter :block/type pages)))))
(->> (page-handler/get-all-pages (state/get-current-repo))
(map (fn [p] (assoc p :id (:db/id p))))))
(rum/defc all-pages < rum/static
[]

View File

@@ -1056,6 +1056,7 @@
(contains? config/audio-formats asset-type)
(contains? config/video-formats asset-type))))
(declare block-positioned-properties)
(rum/defc page-reference < rum/reactive
"Component for page reference"
[html-export? uuid-or-title* {:keys [nested-link? show-brackets? id] :as config} label]
@@ -1082,6 +1083,10 @@
(not html-export?)
(not contents-page?))
[:span.text-gray-500.bracket page-ref/left-brackets])
(when (and (config/db-based-graph?) (ldb/class-instance? (db/entity :logseq.class/Task) block))
[:div.inline-block {:style {:margin-right 1}
:on-pointer-down (fn [e]
(util/stop e))} (block-positioned-properties config block :block-left)])
(page-cp config' (if (uuid? uuid-or-title)
{:block/uuid uuid-or-title}
{:block/name uuid-or-title}))
@@ -1573,7 +1578,7 @@
{:builder (query-builder-component/builder build-option {})
:query query}))])
(defn- macro-function-cp
(rum/defc macro-function-cp < rum/reactive
[config arguments]
(or
(some-> (:query-result config) rum/react (block-macros/function-macro arguments))
@@ -3425,7 +3430,7 @@
own-number-list? (:own-order-number-list? config)
order-list? (boolean own-number-list?)
children (ldb/get-children block)
selected? (contains? (set (state/get-selection-block-ids)) (:block/uuid block))
selected? (when (uuid? (:block/uuid block)) (contains? (set (state/get-selection-block-ids)) (:block/uuid block)))
db-based? (config/db-based-graph? repo)
page-icon (when (:page-title? config)
(let [icon' (get block (pu/get-pid :logseq.property/icon))]

View File

@@ -379,7 +379,7 @@
}
.page-reference {
@apply inline rounded transition-[background];
@apply inline-flex flex-row items-center rounded transition-[background];
.bracket {
@apply opacity-30;

View File

@@ -30,6 +30,7 @@
[goog.dom :as gdom]
[goog.string :as gstring]
[logseq.common.util :as common-util]
[logseq.common.util.page-ref :as page-ref]
[logseq.db :as ldb]
[logseq.db.frontend.class :as db-class]
[logseq.graph-parser.property :as gp-property]
@@ -338,7 +339,17 @@
(when (>= (count edit-content) current-pos)
(subs edit-content pos current-pos)))]
(when input
(block-search-auto-complete edit-block input id q format selected-text))))
(let [db? (config/db-based-graph? (state/get-current-repo))
embed? (and db? (= @commands/*current-command "Block embed"))
page (when embed? (page-ref/get-page-name edit-content))
embed-block-id (when (and embed? page (common-util/uuid-string? page))
(uuid page))]
(if embed-block-id
(let [f (block-on-chosen-handler true input id q format nil)
block (db/entity embed-block-id)]
(when block (f block))
nil)
(block-search-auto-complete edit-block input id q format selected-text))))))
(rum/defc template-search-aux
[id q]
@@ -372,26 +383,30 @@
(rum/defc property-search
[id]
(let [input (gdom/getElement id)
[matched-properties set-matched-properties!] (rum/use-state nil)]
[matched-properties set-matched-properties!] (rum/use-state nil)
[q set-q!] (rum/use-state "")]
(when input
(let [q (or (:searching-property (editor-handler/get-searching-property input))
"")]
(hooks/use-effect!
(fn []
(p/let [matched-properties (editor-handler/<get-matched-properties q)]
(set-matched-properties! matched-properties)))
[q])
(let [q-property (string/replace (string/lower-case q) #"\s+" "-")
non-exist-handler (fn [_state]
((editor-handler/property-on-chosen-handler id q-property) nil))]
(ui/auto-complete
matched-properties
{:on-chosen (editor-handler/property-on-chosen-handler id q-property)
:on-enter non-exist-handler
:empty-placeholder [:div.px-4.py-2.text-sm (str "Create a new property: " q-property)]
:header [:div.px-4.py-2.text-sm.font-medium "Matched properties: "]
:item-render (fn [property] property)
:class "black"}))))))
(hooks/use-effect!
(fn []
(.addEventListener input "input" (fn [_e]
(set-q! (or (:searching-property (editor-handler/get-searching-property input)) "")))))
[])
(hooks/use-effect!
(fn []
(p/let [matched-properties (editor-handler/<get-matched-properties q)]
(set-matched-properties! matched-properties)))
[q])
(let [q-property (string/replace (string/lower-case q) #"\s+" "-")
non-exist-handler (fn [_state]
((editor-handler/property-on-chosen-handler id q-property) nil))]
(ui/auto-complete
matched-properties
{:on-chosen (editor-handler/property-on-chosen-handler id q-property)
:on-enter non-exist-handler
:empty-placeholder [:div.px-4.py-2.text-sm (str "Create a new property: " q-property)]
:header [:div.px-4.py-2.text-sm.font-medium "Matched properties: "]
:item-render (fn [property] property)
:class "black"})))))
(rum/defc property-value-search-aux
[id property q]

View File

@@ -189,7 +189,7 @@
property-separated-by-commas? (partial text/separated-by-commas? (state/get-config))]
[:div.overflow-x-auto {:on-pointer-down (fn [e] (.stopPropagation e))
:style {:width "100%"}
:class (when-not page? "query-table")}
:class "query-table"}
[:table.table-auto
[:thead
[:tr.cursor

View File

@@ -241,8 +241,9 @@
blocks (if block? [block] (db/sort-by-order children block))]
(let [add-button? (not (or config/publishing?
(let [last-child-id (model/get-block-deep-last-open-child-id (db/get-db) (:db/id (last blocks)))
block' (if last-child-id (db/entity last-child-id) (last blocks))]
(string/blank? (:block/title block')))))]
block' (if last-child-id (db/entity last-child-id) (last blocks))
link (:block/link block')]
(string/blank? (:block/title (or link block'))))))]
[:div
{:class (when add-button? "show-add-button")}
(page-blocks-inner page-e blocks config sidebar? whiteboard? block-id)

View File

@@ -213,6 +213,11 @@
[:p.text-sm
(t :plugin/security-warning)]))
(defn format-number [num & {:keys [precision] :or {precision 2}}]
(cond
(< num 1000) (str num)
(>= num 1000) (str (.toFixed (/ num 1000) precision) "k")))
(rum/defc card-ctls-of-market < rum/static
[item stat installed? installing-or-updating?]
[:div.ctl
@@ -225,7 +230,7 @@
(when-let [downloads (and stat (:total_downloads stat))]
(when (and downloads (> downloads 0))
[:li.flex.text-sm.items-center.pr-3
(svg/cloud-down 16) [:span.pl-1 downloads]]))]
(svg/cloud-down 16) [:span.pl-1 (format-number downloads)]]))]
[:div.r.flex.items-center
@@ -769,23 +774,25 @@
pkgs (get grouped-pkgs false)
;; calculate weight
[key pkgs] (if default?
(let [decay-factor 0.01
(let [decay-factor 0.001
download-weight 0.8
star-weight 0.2]
(letfn [(normalize [vals val]
(let [min-val (apply min vals)
max-val (apply max vals)]
(if (= max-val min-val) 1
(/ (- val min-val) (- max-val val)))))
(if (= max-val min-val) 0
(/ (- val min-val) (- max-val min-val)))))
(time-diff-in-days [ts]
(let [time-diff (- (js/Date.now) ts)]
(when-let [time-diff (and (number? ts) (- (js/Date.now) ts))]
(/ time-diff (* 1000 60 60 24))))]
[:weight
(let [all-downloads (map :downloads pkgs)
all-stars (map :stars pkgs)]
(let [all-downloads (->> (map :downloads pkgs) (remove #(not (number? %))))
all-stars (->> (map :stars pkgs) (remove #(not (number? %))))]
(->> pkgs
(map (fn [{:keys [downloads stars latestAt] :as pkg}]
(let [days-since-latest (time-diff-in-days latestAt)
(let [downloads (if (number? downloads) downloads 1)
stars (if (number? stars) stars 1)
days-since-latest (time-diff-in-days latestAt)
decay (js/Math.exp (* -1 decay-factor days-since-latest))
normalized-downloads (normalize all-downloads downloads)
normalize-stars (normalize all-stars stars)

View File

@@ -177,10 +177,9 @@
(custom-query-inner config q opts))
{:default-collapsed? collapsed?
:title-trigger? true})]
(when-not (:table? config)
[:div.bd
(when-not collapsed?'
(custom-query-inner config q opts))]))])))))
[:div.bd
(when-not collapsed?'
(custom-query-inner config q opts))])])))))
(rum/defc trigger-custom-query
[config q]

View File

@@ -119,10 +119,6 @@ html.is-resizing-buf {
th, td {
@apply p-1.5 border border-collapse;
&[data-key=":block"] {
@apply whitespace-normal;
}
}
}

View File

@@ -22,7 +22,7 @@
(goog-define REVISION "unknown")
(defonce revision REVISION)
(def ENABLE-FILE-SYNC-PRODUCTION false)
(goog-define ENABLE-FILE-SYNC-PRODUCTION false)
;; this is a feature flag to enable the account tab
;; when it launches (when pro plan launches) it should be removed

View File

@@ -6,6 +6,7 @@
[clojure.string :as string]
[clojure.walk :as walk]
[datascript.core :as d]
[frontend.common.file-based.db :as common-file-db]
[frontend.config :as config]
[frontend.date :as date]
[frontend.db.conn :as conn]
@@ -912,7 +913,7 @@ independent of format as format specific heading characters are stripped"
(defn get-namespace-pages
"Accepts both sanitized and unsanitized namespaces"
[repo namespace]
(ldb/get-namespace-pages (conn/get-db repo) namespace {:db-graph? (config/db-based-graph? repo)}))
(common-file-db/get-namespace-pages (conn/get-db repo) namespace))
(defn- tree [flat-col root]
(let [sort-fn #(sort-by :block/name %)

View File

@@ -800,12 +800,14 @@
(when-not (and has-children? left-has-children?)
(when block-parent-id
(let [block-parent (gdom/getElement block-parent-id)
sibling-block (if (:embed? config)
(util/get-prev-block-non-collapsed
block-parent
{:container (util/rec-get-blocks-container block-parent)})
(util/get-prev-block-non-collapsed-non-embed block-parent))
{:keys [prev-block new-content edit-block-f]} (move-to-prev-block repo sibling-block format value)
sibling-or-parent-block
(if (:embed? config)
(util/get-prev-block-non-collapsed
block-parent
{:container (util/rec-get-blocks-container block-parent)})
(util/get-prev-block-non-collapsed-non-embed block-parent))
{:keys [prev-block new-content edit-block-f]}
(move-to-prev-block repo sibling-or-parent-block format value)
concat-prev-block? (boolean (and prev-block new-content))
transact-opts {:outliner-op :delete-blocks}]
(cond
@@ -817,7 +819,9 @@
concat-prev-block?
(let [children (:block/_parent (db/entity (:db/id block)))
db-based? (config/db-based-graph? repo)
prev-block-is-not-parent? (not= (:block/uuid (:block/parent block)) (:block/uuid prev-block))
delete-prev-block? (and db-based?
prev-block-is-not-parent?
(empty? (:block/tags block))
(not (:logseq.property.node/display-type block))
(seq (:block/properties block))
@@ -3235,10 +3239,14 @@
(when-let [block-id (:block/uuid current-block)]
(let [db? (config/db-based-graph? (state/get-current-repo))]
(if (= format "embed")
(copy-block-ref! block-id
(if db?
block-ref/->block-ref
#(str "{{embed ((" % "))}}")))
(if db?
(p/do!
(save-current-block!)
(util/copy-to-clipboard! (page-ref/->page-ref block-id)
{:graph (state/get-current-repo)
:blocks [{:block/uuid (:block/uuid current-block)}]
:embed-block? true}))
(copy-block-ref! block-id #(str "{{embed ((" % "))}}")))
(copy-block-ref! block-id
(if db?
page-ref/->page-ref

View File

@@ -190,7 +190,7 @@
[input text e html]
(util/stop e)
(->
(p/let [{:keys [graph blocks]} (get-copied-blocks)]
(p/let [{:keys [graph blocks embed-block?]} (get-copied-blocks)]
(if (and (seq blocks) (= graph (state/get-current-repo)))
;; Handle internal paste
(let [revert-cut-txs (get-revert-cut-txs blocks)
@@ -198,8 +198,18 @@
blocks (if (config/db-based-graph? (state/get-current-repo))
(map (fn [b] (dissoc b :block/properties)) blocks)
blocks)]
(editor-handler/paste-blocks blocks {:revert-cut-txs revert-cut-txs
:keep-uuid? keep-uuid?}))
(if embed-block?
(when-let [block-id (:block/uuid (first blocks))]
(when-let [current-block (state/get-edit-block)]
(p/do!
(editor-handler/api-insert-new-block! ""
{:block-uuid (:block/uuid current-block)
:sibling? true
:replace-empty-target? true
:other-attrs {:block/link (:db/id (db/entity [:block/uuid block-id]))}})
(state/clear-edit!))))
(editor-handler/paste-blocks blocks {:revert-cut-txs revert-cut-txs
:keep-uuid? keep-uuid?})))
(paste-copied-text input text html)))
(p/catch (fn [error]
(log/error :msg "Paste failed" :exception error)

View File

@@ -606,7 +606,7 @@ should be done through this fn in order to get global config and config defaults
(defn custom-shortcuts []
(merge (storage/get :ls-shortcuts)
(:shortcuts (get-config))))
(:shortcuts (get-config))))
(defn get-commands
[]
@@ -1168,6 +1168,13 @@ Similar to re-frame subscriptions"
[]
(get-selected-block-ids (get-selection-blocks)))
(defn sub-block-selected?
[block-id]
(assert (uuid? block-id))
(rum/react
(r/cached-derived-atom (:selection/blocks @state) [(get-current-repo) ::ui-selected block-id]
(fn [blocks] (some #{block-id} (get-selected-block-ids blocks))))))
(defn dom-clear-selection!
[]
(doseq [node (dom/by-class "ls-block selected")]

View File

@@ -807,7 +807,7 @@
#?(:cljs
(defn copy-to-clipboard!
[text & {:keys [graph html blocks owner-window]}]
[text & {:keys [graph html blocks embed-block? owner-window]}]
(let [blocks (map (fn [block] (if (de/entity? block)
(-> (into {} block)
;; FIXME: why :db/id is not included?
@@ -820,6 +820,7 @@
:blocks (when (and graph (seq blocks))
(pr-str
{:graph graph
:embed-block? embed-block?
:blocks (mapv #(dissoc % :block.temp/fully-loaded? %) blocks)}))}))]
(if owner-window
(utils/writeClipboard data owner-window)

View File

@@ -4,6 +4,7 @@
[clojure.walk :as walk]
[datascript.core :as d]
[frontend.common.file.util :as wfu]
[frontend.common.file-based.db :as common-file-db]
[frontend.worker.handler.page :as worker-page]
[logseq.common.config :as common-config]
[logseq.common.util :as common-util]
@@ -253,7 +254,7 @@
(defn- rename-namespace-pages!
"Original names (unsanitized only)"
[repo conn config old-name new-name]
(let [pages (ldb/get-namespace-pages @conn old-name {})
(let [pages (common-file-db/get-namespace-pages @conn old-name)
page (d/pull @conn '[*] [:block/name (common-util/page-name-sanity-lc old-name)])
pages (cons page pages)]
(doseq [{:block/keys [name title]} pages]
@@ -273,8 +274,8 @@
(let [nested-page-str (page-ref/->page-ref (common-util/page-name-sanity-lc old-ns-name))
ns-prefix-format-str (str page-ref/left-brackets "%s/")
ns-prefix (common-util/format ns-prefix-format-str (common-util/page-name-sanity-lc old-ns-name))
nested-pages (ldb/get-pages-by-name-partition @conn nested-page-str)
nested-pages-ns (ldb/get-pages-by-name-partition @conn ns-prefix)]
nested-pages (common-file-db/get-pages-by-name-partition @conn nested-page-str)
nested-pages-ns (common-file-db/get-pages-by-name-partition @conn ns-prefix)]
(when nested-pages
;; rename page "[[obsidian]] is a tool" to "[[logseq]] is a tool"
(doseq [{:block/keys [name title]} nested-pages]