mirror of https://github.com/logseq/logseq
Merge branch 'feat/db' into refactor/single-block-type
commit
9c60742519
|
@ -4,7 +4,7 @@
|
|||
{logseq/bb-tasks
|
||||
#_{:local/root "../../../bb-tasks"}
|
||||
{:git/url "https://github.com/logseq/bb-tasks"
|
||||
:git/sha "70d3edeb287f5cec7192e642549a401f7d6d4263"}}
|
||||
:git/sha "1d429e223baeade426d30a4ed1c8a110173a2402"}}
|
||||
|
||||
:pods
|
||||
{clj-kondo/clj-kondo {:version "2023.05.26"}}
|
||||
|
|
|
@ -89,9 +89,14 @@
|
|||
(let [datoms (d/datoms db :eavt)
|
||||
ent-maps* (db-malli-schema/datoms->entities datoms)
|
||||
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)]
|
||||
(cond-> {:datom-count (count datoms)
|
||||
:entities ent-maps}
|
||||
(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))))))
|
||||
|
|
|
@ -294,12 +294,19 @@
|
|||
[(:name v) k]))
|
||||
(into {})))
|
||||
|
||||
(def built-in-property-names
|
||||
"Set of all built-in property names as keywords. Using in-memory property
|
||||
names because these are legacy names already in a user's file graph"
|
||||
;; Should this move to logseq.db.frontend.property to be better maintained?
|
||||
(def db-only-built-in-property-names
|
||||
"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
|
||||
;; :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
|
||||
[props {:keys [ignored-properties all-idents]} {:block/keys [title name]} options]
|
||||
|
@ -433,7 +440,7 @@
|
|||
{:keys [import-state] :as options}]
|
||||
(let [{:keys [all-idents property-schemas]} import-state
|
||||
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)
|
||||
(swap! (:block-properties-text-values import-state)
|
||||
assoc
|
||||
|
@ -444,7 +451,7 @@
|
|||
(if (contains? props :template)
|
||||
{}
|
||||
(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 block [:block/name :block/title])
|
||||
(select-keys options [:property-classes]))
|
||||
|
@ -479,7 +486,7 @@
|
|||
class-related-properties)]
|
||||
(->> (apply dissoc properties dissoced-props)
|
||||
(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
|
||||
(if (string? val)
|
||||
;; Ignore blank values as they were usually generated by templates
|
||||
|
@ -508,7 +515,7 @@
|
|||
properties-to-infer (if (:template properties')
|
||||
;; 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
|
||||
(->> properties-to-infer
|
||||
(keep (fn [[prop val]]
|
||||
|
@ -676,9 +683,22 @@
|
|||
(not (:block/file %))))
|
||||
;; remove file path relative
|
||||
(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))
|
||||
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
|
||||
(into {} (map (juxt :block/name :block/uuid) new-pages)))
|
||||
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)
|
||||
(:block/tags m)
|
||||
(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))]
|
||||
{:pages-tx pages-tx
|
||||
:page-properties-tx (mapcat :properties-tx all-pages-m)
|
||||
|
@ -791,10 +815,10 @@
|
|||
:tag-classes (set (map string/lower-case (:tag-classes user-options)))
|
||||
:property-classes (set/difference
|
||||
(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
|
||||
(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
|
||||
"Separates new pages from new properties tx in preparation for properties to
|
||||
|
|
|
@ -900,6 +900,7 @@
|
|||
granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
|
||||
theme (state/sub :ui/theme)
|
||||
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?)
|
||||
light? (= "light" (state/sub :ui/theme))
|
||||
sidebar-open? (state/sub :ui/sidebar-open?)
|
||||
|
@ -929,6 +930,7 @@
|
|||
{:t t
|
||||
:theme theme
|
||||
:accent-color accent-color
|
||||
:editor-font editor-font
|
||||
:route route-match
|
||||
:current-repo current-repo
|
||||
:edit? edit?
|
||||
|
|
|
@ -277,7 +277,7 @@
|
|||
(do
|
||||
(log/error :import-errors {:msg (str "Import detected " (count errors) " invalid block(s):")
|
||||
: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.")
|
||||
:warning false))
|
||||
(log/info :import-valid {:msg "Valid import!"
|
||||
|
@ -413,7 +413,7 @@
|
|||
(shui/dialog-open!
|
||||
#(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
|
||||
[:span.as-flex-center [:i (svg/logo 28)]]
|
||||
[:span.flex.flex-col
|
||||
|
|
|
@ -94,56 +94,56 @@
|
|||
(shui/tabler-icon "folder-pin") [:span.pl-1 root]])
|
||||
|
||||
(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?))
|
||||
(ui/tippy {:html [:div.text-sm.max-w-xs
|
||||
(cond
|
||||
only-cloud?
|
||||
"Deletes this remote graph. Note this can't be recovered."
|
||||
[:a.text-gray-400.ml-4.font-medium.text-sm.whitespace-nowrap
|
||||
{:title title
|
||||
:on-click (fn []
|
||||
(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?
|
||||
"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.")]
|
||||
: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)")])))]]]))
|
||||
(if has-prompt?
|
||||
(confirm-fn!)
|
||||
(unlink-or-remote-fn!))))}
|
||||
(if only-cloud? "Remove (server)" "Unlink (local)")]))]]]))
|
||||
|
||||
(rum/defc repos < rum/reactive
|
||||
[]
|
||||
|
|
|
@ -220,6 +220,38 @@
|
|||
[:div {:style {:text-align "right"}}
|
||||
(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
|
||||
[state t]
|
||||
(let [enabled? (state/sub [:electron/user-cfgs :spell-check])]
|
||||
|
@ -719,6 +751,8 @@
|
|||
enable-tooltip? (state/enable-tooltip?)
|
||||
enable-shortcut-tooltip? (state/sub :ui/shortcut-tooltip?)
|
||||
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)
|
||||
db-graph? (config/db-based-graph? (state/get-current-repo))]
|
||||
|
||||
|
@ -728,7 +762,9 @@
|
|||
(date-format-row t preferred-date-format)
|
||||
(when-not db-graph?
|
||||
(workflow-row t preferred-workflow))
|
||||
(editor-font-family-row t editor-font)
|
||||
(show-brackets-row t show-brackets?)
|
||||
(toggle-wide-mode-row t wide-mode?)
|
||||
|
||||
(when (util/electron?) (switch-spell-check-row t))
|
||||
(outdenting-row t logical-outdenting?)
|
||||
|
|
|
@ -183,14 +183,18 @@
|
|||
}
|
||||
|
||||
.sidebar-item .cp__shortcut-page-x {
|
||||
padding: 12px 0 0 0;
|
||||
background-color: var(--color-level-2);
|
||||
padding: 12px 0 0 0;
|
||||
background-color: var(--color-level-2);
|
||||
}
|
||||
|
||||
.sidebar-item article {
|
||||
max-height: unset;
|
||||
max-height: unset;
|
||||
}
|
||||
|
||||
.keyboard-shortcut {
|
||||
@apply inline-flex;
|
||||
@apply inline-flex;
|
||||
|
||||
.ui__button {
|
||||
@apply cursor-default;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
|
||||
(defonce *once-theme-loaded? (volatile! false))
|
||||
|
||||
(rum/defc ^:large-vars/cleanup-todo container
|
||||
[{:keys [route theme accent-color on-click current-repo nfs-granted? db-restoring?
|
||||
(rum/defc ^:large-vars/cleanup-todo container < rum/static
|
||||
[{: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]
|
||||
(let [mounted-fn (use-mounted)
|
||||
[restored-sidebar? set-restored-sidebar?] (rum/use-state false)]
|
||||
|
@ -60,6 +60,11 @@
|
|||
(or accent-color "logseq")))
|
||||
[accent-color])
|
||||
|
||||
(rum/use-effect!
|
||||
#(some-> js/document.documentElement
|
||||
(.setAttribute "data-font" (or editor-font "default")))
|
||||
[editor-font])
|
||||
|
||||
(rum/use-effect!
|
||||
#(let [doc js/document.documentElement]
|
||||
(.setAttribute doc "lang" preferred-language)))
|
||||
|
|
|
@ -153,4 +153,12 @@ main.ls-fold-button-on-right {
|
|||
|
||||
main.theme-container-inner {
|
||||
--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;
|
||||
}
|
|
@ -139,8 +139,8 @@
|
|||
(if (false? bindings)
|
||||
[]
|
||||
(-> bindings
|
||||
first
|
||||
(str/split #" |\+")))))
|
||||
last
|
||||
(str/split #" |\+")))))
|
||||
|
||||
(defn binding-for-display [k binding]
|
||||
(let [tmp (cond
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
:ui/custom-theme (or (storage/get :ui/custom-theme) {:light {:mode "light"} :dark {:mode "dark"}})
|
||||
:ui/wide-mode? (storage/get :ui/wide-mode)
|
||||
: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:
|
||||
;; 1. right sidebar
|
||||
|
@ -2385,6 +2386,11 @@ Similar to re-frame subscriptions"
|
|||
(storage/remove :ui/radix-color)
|
||||
(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?
|
||||
[]
|
||||
(:ui/handbooks-open? @state))
|
||||
|
|
|
@ -270,6 +270,8 @@
|
|||
:settings-page/custom-theme "Custom theme"
|
||||
:settings-page/export-theme "Export theme"
|
||||
: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/auto-updater "Auto updater"
|
||||
:settings-page/disable-sentry "Send usage data and diagnostics to Logseq"
|
||||
|
|
Loading…
Reference in New Issue