Merge branch 'feat/db' into refactor/single-block-type

pull/11458/head
Tienson Qin 2024-08-06 07:24:29 +08:00
commit 9c60742519
13 changed files with 166 additions and 74 deletions

2
deps/db/bb.edn vendored
View File

@ -4,7 +4,7 @@
{logseq/bb-tasks {logseq/bb-tasks
#_{:local/root "../../../bb-tasks"} #_{:local/root "../../../bb-tasks"}
{:git/url "https://github.com/logseq/bb-tasks" {:git/url "https://github.com/logseq/bb-tasks"
:git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}} :git/sha "1d429e223baeade426d30a4ed1c8a110173a2402"}}
:pods :pods
{clj-kondo/clj-kondo {:version "2023.05.26"}} {clj-kondo/clj-kondo {:version "2023.05.26"}}

View File

@ -89,9 +89,14 @@
(let [datoms (d/datoms db :eavt) (let [datoms (d/datoms db :eavt)
ent-maps* (db-malli-schema/datoms->entities datoms) ent-maps* (db-malli-schema/datoms->entities datoms)
schema (update-schema db-malli-schema/DB db {:closed-schema? true}) schema (update-schema db-malli-schema/DB db {:closed-schema? true})
ent-maps (db-malli-schema/update-properties-in-ents db ent-maps*) ent-maps (mapv
;; Remove some UI interactions adding this e.g. import
#(dissoc % :block.temp/fully-loaded?)
(db-malli-schema/update-properties-in-ents db ent-maps*))
errors (->> ent-maps (m/explain schema) :errors)] errors (->> ent-maps (m/explain schema) :errors)]
(cond-> {:datom-count (count datoms) (cond-> {:datom-count (count datoms)
:entities ent-maps} :entities ent-maps}
(some? errors) (some? errors)
(assoc :errors (group-errors-by-entity db ent-maps errors))))) (assoc :errors (map #(-> (dissoc % :errors-by-type)
(update :errors (fn [errs] (me/humanize {:errors errs}))))
(group-errors-by-entity db ent-maps errors))))))

View File

@ -294,12 +294,19 @@
[(:name v) k])) [(:name v) k]))
(into {}))) (into {})))
(def built-in-property-names ;; Should this move to logseq.db.frontend.property to be better maintained?
"Set of all built-in property names as keywords. Using in-memory property (def db-only-built-in-property-names
names because these are legacy names already in a user's file graph" "Built-in property names that are are only used by DB graphs"
#{:description :page-tags :hide-properties? :created-from-property
:built-in? :includes :excludes :status :priority :deadline :sorting
:hidden-columns :ordered-columns :view-for :remote-metadata})
(def file-built-in-property-names
"Built-in property names for file graphs that are imported. Expressed as set of keywords"
(-> built-in-property-name-to-idents keys set (-> built-in-property-name-to-idents keys set
;; :filters is not in built-in-properties because it maps to 2 new properties ;; :filters is not in built-in-properties because it maps to 2 new properties
(conj :filters))) (conj :filters)
(set/difference db-only-built-in-property-names)))
(defn- update-built-in-property-values (defn- update-built-in-property-values
[props {:keys [ignored-properties all-idents]} {:block/keys [title name]} options] [props {:keys [ignored-properties all-idents]} {:block/keys [title name]} options]
@ -433,7 +440,7 @@
{:keys [import-state] :as options}] {:keys [import-state] :as options}]
(let [{:keys [all-idents property-schemas]} import-state (let [{:keys [all-idents property-schemas]} import-state
get-ident' #(get-ident @all-idents %) get-ident' #(get-ident @all-idents %)
user-properties (apply dissoc props built-in-property-names)] user-properties (apply dissoc props file-built-in-property-names)]
(when (seq user-properties) (when (seq user-properties)
(swap! (:block-properties-text-values import-state) (swap! (:block-properties-text-values import-state)
assoc assoc
@ -444,7 +451,7 @@
(if (contains? props :template) (if (contains? props :template)
{} {}
(let [props' (-> (update-built-in-property-values (let [props' (-> (update-built-in-property-values
(select-keys props built-in-property-names) (select-keys props file-built-in-property-names)
(select-keys import-state [:ignored-properties :all-idents]) (select-keys import-state [:ignored-properties :all-idents])
(select-keys block [:block/name :block/title]) (select-keys block [:block/name :block/title])
(select-keys options [:property-classes])) (select-keys options [:property-classes]))
@ -479,7 +486,7 @@
class-related-properties)] class-related-properties)]
(->> (apply dissoc properties dissoced-props) (->> (apply dissoc properties dissoced-props)
(keep (fn [[prop val]] (keep (fn [[prop val]]
(if (not (contains? built-in-property-names prop)) (if (not (contains? file-built-in-property-names prop))
;; only update user properties ;; only update user properties
(if (string? val) (if (string? val)
;; Ignore blank values as they were usually generated by templates ;; Ignore blank values as they were usually generated by templates
@ -508,7 +515,7 @@
properties-to-infer (if (:template properties') properties-to-infer (if (:template properties')
;; Ignore template properties as they don't consistently have representative property values ;; Ignore template properties as they don't consistently have representative property values
{} {}
(apply dissoc properties' built-in-property-names)) (apply dissoc properties' file-built-in-property-names))
property-changes property-changes
(->> properties-to-infer (->> properties-to-infer
(keep (fn [[prop val]] (keep (fn [[prop val]]
@ -676,9 +683,22 @@
(not (:block/file %)))) (not (:block/file %))))
;; remove file path relative ;; remove file path relative
(map #(dissoc % :block/file))) (map #(dissoc % :block/file)))
existing-pages (keep #(ldb/get-page @conn (:block/name %)) all-pages) existing-pages (keep #(first
;; don't fetch built-in as that would give the wrong entity if a user used
;; a db-only built-in property name e.g. description
(d/q '[:find [(pull ?b [*]) ...]
:in $ ?name
:where [?b :block/name ?name] [(missing? $ ?b :logseq.property/built-in?)]]
@conn
(:block/name %)))
all-pages)
existing-page-names-to-uuids (into {} (map (juxt :block/name :block/uuid) existing-pages)) existing-page-names-to-uuids (into {} (map (juxt :block/name :block/uuid) existing-pages))
new-pages (remove #(contains? existing-page-names-to-uuids (:block/name %)) all-pages) new-pages (->> all-pages
(remove #(contains? existing-page-names-to-uuids (:block/name %)))
;; fix extract incorrectly assigning user properties built-in property uuids
(map #(if (contains? db-only-built-in-property-names (keyword (:block/name %)))
(assoc % :block/uuid (d/squuid))
%)))
page-names-to-uuids (merge existing-page-names-to-uuids page-names-to-uuids (merge existing-page-names-to-uuids
(into {} (map (juxt :block/name :block/uuid) new-pages))) (into {} (map (juxt :block/name :block/uuid) new-pages)))
all-pages-m (mapv #(handle-page-properties % @conn page-names-to-uuids all-pages options) all-pages-m (mapv #(handle-page-properties % @conn page-names-to-uuids all-pages options)
@ -701,7 +721,11 @@
(update-page-alias page-names-to-uuids) (update-page-alias page-names-to-uuids)
(:block/tags m) (:block/tags m)
(update-page-tags @conn tag-classes page-names-to-uuids (:all-idents import-state))))) (update-page-tags @conn tag-classes page-names-to-uuids (:all-idents import-state)))))
(build-new-page m @conn tag-classes page-names-to-uuids (:all-idents import-state)))) (let [m' (if (contains? db-only-built-in-property-names (keyword (:block/name m)))
;; Use fixed uuid from above
(assoc m :block/uuid (get page-names-to-uuids (:block/name m)))
m)]
(build-new-page m' @conn tag-classes page-names-to-uuids (:all-idents import-state)))))
(map :block all-pages-m))] (map :block all-pages-m))]
{:pages-tx pages-tx {:pages-tx pages-tx
:page-properties-tx (mapcat :properties-tx all-pages-m) :page-properties-tx (mapcat :properties-tx all-pages-m)
@ -791,10 +815,10 @@
:tag-classes (set (map string/lower-case (:tag-classes user-options))) :tag-classes (set (map string/lower-case (:tag-classes user-options)))
:property-classes (set/difference :property-classes (set/difference
(set (map (comp keyword string/lower-case) (:property-classes user-options))) (set (map (comp keyword string/lower-case) (:property-classes user-options)))
built-in-property-names) file-built-in-property-names)
:property-parent-classes (set/difference :property-parent-classes (set/difference
(set (map (comp keyword string/lower-case) (:property-parent-classes user-options))) (set (map (comp keyword string/lower-case) (:property-parent-classes user-options)))
built-in-property-names)})) file-built-in-property-names)}))
(defn- split-pages-and-properties-tx (defn- split-pages-and-properties-tx
"Separates new pages from new properties tx in preparation for properties to "Separates new pages from new properties tx in preparation for properties to

View File

@ -900,6 +900,7 @@
granted? (state/sub [:nfs/user-granted? (state/get-current-repo)]) granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
theme (state/sub :ui/theme) theme (state/sub :ui/theme)
accent-color (some-> (state/sub :ui/radix-color) (name)) accent-color (some-> (state/sub :ui/radix-color) (name))
editor-font (some-> (state/sub :ui/editor-font) (name))
system-theme? (state/sub :ui/system-theme?) system-theme? (state/sub :ui/system-theme?)
light? (= "light" (state/sub :ui/theme)) light? (= "light" (state/sub :ui/theme))
sidebar-open? (state/sub :ui/sidebar-open?) sidebar-open? (state/sub :ui/sidebar-open?)
@ -929,6 +930,7 @@
{:t t {:t t
:theme theme :theme theme
:accent-color accent-color :accent-color accent-color
:editor-font editor-font
:route route-match :route route-match
:current-repo current-repo :current-repo current-repo
:edit? edit? :edit? edit?

View File

@ -277,7 +277,7 @@
(do (do
(log/error :import-errors {:msg (str "Import detected " (count errors) " invalid block(s):") (log/error :import-errors {:msg (str "Import detected " (count errors) " invalid block(s):")
:counts (assoc (counts-from-entities entities) :datoms datom-count)}) :counts (assoc (counts-from-entities entities) :datoms datom-count)})
(pprint/pprint (map :entity errors)) (pprint/pprint errors)
(notification/show! (str "Import detected " (count errors) " invalid block(s). These blocks may be buggy when you interact with them. See the javascript console for more.") (notification/show! (str "Import detected " (count errors) " invalid block(s). These blocks may be buggy when you interact with them. See the javascript console for more.")
:warning false)) :warning false))
(log/info :import-valid {:msg "Valid import!" (log/info :import-valid {:msg "Valid import!"
@ -413,7 +413,7 @@
(shui/dialog-open! (shui/dialog-open!
#(set-graph-name-dialog e {:sqlite? true})))}]]) #(set-graph-name-dialog e {:sqlite? true})))}]])
(when (and db-based? (or util/electron? util/web-platform?)) (when (or util/electron? util/web-platform?)
[:label.action-input.flex.items-center.mx-2.my-2 [:label.action-input.flex.items-center.mx-2.my-2
[:span.as-flex-center [:i (svg/logo 28)]] [:span.as-flex-center [:i (svg/logo 28)]]
[:span.flex.flex-col [:span.flex.flex-col

View File

@ -94,56 +94,56 @@
(shui/tabler-icon "folder-pin") [:span.pl-1 root]]) (shui/tabler-icon "folder-pin") [:span.pl-1 root]])
(let [db-graph? (config/db-based-graph? url) (let [db-graph? (config/db-based-graph? url)
manager? (and db-graph? (user-handler/manager? url))] manager? (and db-graph? (user-handler/manager? url))
title (cond
only-cloud?
"Deletes this remote graph. Note this can't be recovered."
db-based?
"Unsafe delete this DB-based graph. Note this can't be recovered."
:else
"Removes Logseq's access to the local file path of your graph. It won't remove your local files.")]
(when-not (and only-cloud? (not manager?)) (when-not (and only-cloud? (not manager?))
(ui/tippy {:html [:div.text-sm.max-w-xs [:a.text-gray-400.ml-4.font-medium.text-sm.whitespace-nowrap
(cond {:title title
only-cloud? :on-click (fn []
"Deletes this remote graph. Note this can't be recovered." (let [has-prompt? true
prompt-str (cond only-cloud?
(str "Are you sure to permanently delete the graph \"" GraphName "\" from our server?")
db-based?
(str "Are you sure to permanently delete the graph \"" url "\" from Logseq?")
:else
(str "Are you sure to unlink the graph \"" url "\" from local folder?"))
unlink-or-remote-fn! (fn []
(repo-handler/remove-repo! repo)
(state/pub-event! [:graph/unlinked repo (state/get-current-repo)]))
action-confirm-fn! (if only-cloud?
(fn []
(when (or manager? (not db-graph?))
(let [delete-graph (if db-graph?
rtc-handler/<rtc-delete-graph!
file-sync/<delete-graph)]
(state/set-state! [:file-sync/remote-graphs :loading] true)
(go (<! (delete-graph GraphUUID))
(state/delete-repo! repo)
(state/delete-remote-graph! repo)
(state/set-state! [:file-sync/remote-graphs :loading] false)))))
unlink-or-remote-fn!)
confirm-fn!
(fn []
(-> (shui/dialog-confirm!
[:p.font-medium.-my-4 prompt-str
[:span.mt-1.flex.font-normal.opacity-70
(if (or db-based? only-cloud?)
[:small.text-red-rx-11 "⚠️ Notice that we can't recover this graph after being deleted. Make sure you have backups before deleting it."]
[:small.opacity-70 "⚠️ It won't remove your local files!"])]])
(p/then #(action-confirm-fn!))))]
db-based? (if has-prompt?
"Unsafe delete this DB-based graph. Note this can't be recovered." (confirm-fn!)
(unlink-or-remote-fn!))))}
:else (if only-cloud? "Remove (server)" "Unlink (local)")]))]]]))
"Removes Logseq's access to the local file path of your graph. It won't remove your local files.")]
:class "tippy-hover"
:interactive true}
[:a.text-gray-400.ml-4.font-medium.text-sm.whitespace-nowrap
{:on-click (fn []
(let [has-prompt? (or only-cloud? db-based?)
prompt-str (cond only-cloud?
(str "Are you sure to permanently delete the graph \"" GraphName "\" from our server?")
db-based?
(str "Are you sure to permanently delete the graph \"" url "\" from Logseq?")
:else
"")
unlink-or-remote-fn! (fn []
(repo-handler/remove-repo! repo)
(state/pub-event! [:graph/unlinked repo (state/get-current-repo)]))
action-confirm-fn! (if only-cloud?
(fn []
(when (or manager? (not db-graph?))
(let [delete-graph (if db-graph?
rtc-handler/<rtc-delete-graph!
file-sync/<delete-graph)]
(state/set-state! [:file-sync/remote-graphs :loading] true)
(go (<! (delete-graph GraphUUID))
(state/delete-repo! repo)
(state/delete-remote-graph! repo)
(state/set-state! [:file-sync/remote-graphs :loading] false)))))
unlink-or-remote-fn!)
confirm-fn!
(fn []
(-> (shui/dialog-confirm!
[:p.font-medium.-my-4 prompt-str
[:span.mt-1.flex.font-normal.opacity-40
[:small "Notice that we can't recover this graph after being deleted. Make sure you have backups before deleting it."]]])
(p/then #(action-confirm-fn!))))]
(if has-prompt?
(confirm-fn!)
(unlink-or-remote-fn!))))}
(if only-cloud? "Remove (server)" "Unlink (local)")])))]]]))
(rum/defc repos < rum/reactive (rum/defc repos < rum/reactive
[] []

View File

@ -220,6 +220,38 @@
[:div {:style {:text-align "right"}} [:div {:style {:text-align "right"}}
(ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-brackets))])]) (ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-brackets))])])
(defn toggle-wide-mode-row [t wide-mode?]
[:div.it.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-center
[:label.block.text-sm.font-medium.leading-5.opacity-70
{:for "wide_mode"}
(t :settings-page/wide-mode)]
[:div
[:div.rounded-md.sm:max-w-xs
(ui/toggle wide-mode?
state/toggle-wide-mode!
true)]]
(when (not (or (util/mobile?) (mobile-util/native-platform?)))
[:div {:style {:text-align "right"}}
(ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-wide-mode))])])
(defn editor-font-family-row [t font]
[:div.it.sm:grid.sm:grid-cols-3.sm:gap-4.sm:items-center
[:label.block.text-sm.font-medium.leading-5.opacity-70
{:for "font_family"}
(t :settings-page/editor-font)]
[:div.rounded-md.sm:max-w-xs.flex.gap-2
(for [t [:default :serif :mono]
:let [t (name t)
tt (string/capitalize t)
active? (= font t)]]
(shui/button
{:variant :secondary
:class (when active? "border-primary border-[2px]")
:on-click #(state/set-editor-font! t)}
[:span.flex.flex-col
[:strong "Ag"]
[:small tt]]))]])
(rum/defcs switch-spell-check-row < rum/reactive (rum/defcs switch-spell-check-row < rum/reactive
[state t] [state t]
(let [enabled? (state/sub [:electron/user-cfgs :spell-check])] (let [enabled? (state/sub [:electron/user-cfgs :spell-check])]
@ -719,6 +751,8 @@
enable-tooltip? (state/enable-tooltip?) enable-tooltip? (state/enable-tooltip?)
enable-shortcut-tooltip? (state/sub :ui/shortcut-tooltip?) enable-shortcut-tooltip? (state/sub :ui/shortcut-tooltip?)
show-brackets? (state/show-brackets?) show-brackets? (state/show-brackets?)
wide-mode? (state/sub :ui/wide-mode?)
editor-font (state/sub :ui/editor-font)
enable-git-auto-push? (state/enable-git-auto-push? current-repo) enable-git-auto-push? (state/enable-git-auto-push? current-repo)
db-graph? (config/db-based-graph? (state/get-current-repo))] db-graph? (config/db-based-graph? (state/get-current-repo))]
@ -728,7 +762,9 @@
(date-format-row t preferred-date-format) (date-format-row t preferred-date-format)
(when-not db-graph? (when-not db-graph?
(workflow-row t preferred-workflow)) (workflow-row t preferred-workflow))
(editor-font-family-row t editor-font)
(show-brackets-row t show-brackets?) (show-brackets-row t show-brackets?)
(toggle-wide-mode-row t wide-mode?)
(when (util/electron?) (switch-spell-check-row t)) (when (util/electron?) (switch-spell-check-row t))
(outdenting-row t logical-outdenting?) (outdenting-row t logical-outdenting?)

View File

@ -183,14 +183,18 @@
} }
.sidebar-item .cp__shortcut-page-x { .sidebar-item .cp__shortcut-page-x {
padding: 12px 0 0 0; padding: 12px 0 0 0;
background-color: var(--color-level-2); background-color: var(--color-level-2);
} }
.sidebar-item article { .sidebar-item article {
max-height: unset; max-height: unset;
} }
.keyboard-shortcut { .keyboard-shortcut {
@apply inline-flex; @apply inline-flex;
.ui__button {
@apply cursor-default;
}
} }

View File

@ -34,8 +34,8 @@
(defonce *once-theme-loaded? (volatile! false)) (defonce *once-theme-loaded? (volatile! false))
(rum/defc ^:large-vars/cleanup-todo container (rum/defc ^:large-vars/cleanup-todo container < rum/static
[{:keys [route theme accent-color on-click current-repo nfs-granted? db-restoring? [{:keys [route theme accent-color editor-font on-click current-repo nfs-granted? db-restoring?
settings-open? sidebar-open? system-theme? sidebar-blocks-len onboarding-state preferred-language]} child] settings-open? sidebar-open? system-theme? sidebar-blocks-len onboarding-state preferred-language]} child]
(let [mounted-fn (use-mounted) (let [mounted-fn (use-mounted)
[restored-sidebar? set-restored-sidebar?] (rum/use-state false)] [restored-sidebar? set-restored-sidebar?] (rum/use-state false)]
@ -60,6 +60,11 @@
(or accent-color "logseq"))) (or accent-color "logseq")))
[accent-color]) [accent-color])
(rum/use-effect!
#(some-> js/document.documentElement
(.setAttribute "data-font" (or editor-font "default")))
[editor-font])
(rum/use-effect! (rum/use-effect!
#(let [doc js/document.documentElement] #(let [doc js/document.documentElement]
(.setAttribute doc "lang" preferred-language))) (.setAttribute doc "lang" preferred-language)))

View File

@ -153,4 +153,12 @@ main.ls-fold-button-on-right {
main.theme-container-inner { main.theme-container-inner {
--left-sidebar-bg-color: var(--lx-gray-02, hsl(var(--secondary, var(--rx-gray-03-hsl)))); --left-sidebar-bg-color: var(--lx-gray-02, hsl(var(--secondary, var(--rx-gray-03-hsl))));
}
html[data-font='serif'] .ls-block, .ls-font-serif {
font-family: Lyon-Text, Georgia, ui-serif, serif;
}
html[data-font='mono'] .ls-block, .ls-font-mono {
font-family: iawriter-mono, Nitti, Menlo, Courier, monospace;
} }

View File

@ -139,8 +139,8 @@
(if (false? bindings) (if (false? bindings)
[] []
(-> bindings (-> bindings
first last
(str/split #" |\+"))))) (str/split #" |\+")))))
(defn binding-for-display [k binding] (defn binding-for-display [k binding]
(let [tmp (cond (let [tmp (cond

View File

@ -95,6 +95,7 @@
:ui/custom-theme (or (storage/get :ui/custom-theme) {:light {:mode "light"} :dark {:mode "dark"}}) :ui/custom-theme (or (storage/get :ui/custom-theme) {:light {:mode "light"} :dark {:mode "dark"}})
:ui/wide-mode? (storage/get :ui/wide-mode) :ui/wide-mode? (storage/get :ui/wide-mode)
:ui/radix-color (storage/get :ui/radix-color) :ui/radix-color (storage/get :ui/radix-color)
:ui/editor-font (storage/get :ui/editor-font)
;; ui/collapsed-blocks is to separate the collapse/expand state from db for: ;; ui/collapsed-blocks is to separate the collapse/expand state from db for:
;; 1. right sidebar ;; 1. right sidebar
@ -2385,6 +2386,11 @@ Similar to re-frame subscriptions"
(storage/remove :ui/radix-color) (storage/remove :ui/radix-color)
(util/set-android-theme)) (util/set-android-theme))
(defn set-editor-font! [font]
(let [font (if (keyword? font) (name font) (str font))]
(swap! state assoc :ui/editor-font font)
(storage/set :ui/editor-font font)))
(defn handbook-open? (defn handbook-open?
[] []
(:ui/handbooks-open? @state)) (:ui/handbooks-open? @state))

View File

@ -270,6 +270,8 @@
:settings-page/custom-theme "Custom theme" :settings-page/custom-theme "Custom theme"
:settings-page/export-theme "Export theme" :settings-page/export-theme "Export theme"
:settings-page/show-brackets "Show brackets" :settings-page/show-brackets "Show brackets"
:settings-page/wide-mode "Wide mode"
:settings-page/editor-font "Font family"
:settings-page/spell-checker "Spell checker" :settings-page/spell-checker "Spell checker"
:settings-page/auto-updater "Auto updater" :settings-page/auto-updater "Auto updater"
:settings-page/disable-sentry "Send usage data and diagnostics to Logseq" :settings-page/disable-sentry "Send usage data and diagnostics to Logseq"