mirror of
https://github.com/logseq/logseq.git
synced 2026-06-01 19:01:22 +00:00
Merge branch 'feat/db' into enhance/reference-view
This commit is contained in:
37
src/main/frontend/common/file_based/db.cljs
Normal file
37
src/main/frontend/common/file_based/db.cljs
Normal 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)))))
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
[]
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -119,10 +119,6 @@ html.is-resizing-buf {
|
||||
|
||||
th, td {
|
||||
@apply p-1.5 border border-collapse;
|
||||
|
||||
&[data-key=":block"] {
|
||||
@apply whitespace-normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 %)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user