mirror of https://github.com/logseq/logseq
fix: stuck importing from edn/json
Also, this commit added the progress UI for importing and removed the :file/writes core.async channel.pull/6486/head
parent
6807931ee8
commit
f4aa08fbd3
|
@ -12,8 +12,13 @@
|
|||
(when-let [current-repo (state/get-current-repo)]
|
||||
[:div.export
|
||||
[:h1.title "Export"]
|
||||
|
||||
[:ul.mr-1
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-edn-v2! current-repo)}
|
||||
(t :export-edn)]]
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-json-v2! current-repo)}
|
||||
(t :export-json)]]
|
||||
(when (util/electron?)
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-html! current-repo)}
|
||||
|
@ -25,12 +30,6 @@
|
|||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-opml! current-repo)}
|
||||
(t :export-opml)]])
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-edn-v2! current-repo)}
|
||||
(t :export-edn)]]
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-json-v2! current-repo)}
|
||||
(t :export-json)]]
|
||||
(when-not (mobile-util/native-platform?)
|
||||
[:li.mb-4
|
||||
[:a.font-medium {:on-click #(export/export-repo-as-roam-json! current-repo)}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
;; deprecated by the onboarding import panel frontend.components.onboarding.setups
|
||||
|
||||
(ns frontend.components.external
|
||||
(:require [rum.core :as rum]
|
||||
[goog.object :as gobj]
|
||||
[clojure.string :as string]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.external :as external-handler]
|
||||
[frontend.ui :as ui]
|
||||
[reitit.frontend.easy :as rfe]))
|
||||
|
||||
(defonce *roam-importing? (atom nil))
|
||||
(defonce *opml-importing? (atom nil))
|
||||
(defonce *opml-imported-pages (atom nil))
|
||||
(rum/defc import-cp < rum/reactive
|
||||
[]
|
||||
(let [roam-importing? (rum/react *roam-importing?)
|
||||
opml-importing? (rum/react *opml-importing?)]
|
||||
[:div#import
|
||||
[:h1.title "Import JSON from Roam Research"]
|
||||
|
||||
[:input
|
||||
{:id "import-roam"
|
||||
:type "file"
|
||||
:on-change (fn [e]
|
||||
(let [file (first (array-seq (.-files (.-target e))))
|
||||
file-name (gobj/get file "name")]
|
||||
(if (string/ends-with? file-name ".json")
|
||||
(do
|
||||
(reset! *roam-importing? true)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(external-handler/import-from-roam-json! text
|
||||
#(reset! *roam-importing? false)))))
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose a JSON file."
|
||||
:error))))}]
|
||||
|
||||
[:hr]
|
||||
|
||||
[:div.mt-4
|
||||
(case roam-importing?
|
||||
true (ui/loading "Loading")
|
||||
false [:b "Importing finished!"]
|
||||
nil)]
|
||||
;;
|
||||
[:h1.title "Import OPML"]
|
||||
|
||||
[:input
|
||||
{:id "import-opml"
|
||||
:type "file"
|
||||
:on-change (fn [e]
|
||||
(let [file (first (array-seq (.-files (.-target e))))
|
||||
file-name (gobj/get file "name")]
|
||||
(if (string/ends-with? file-name ".opml")
|
||||
(do
|
||||
(reset! *opml-importing? true)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(external-handler/import-from-opml! text
|
||||
(fn [pages]
|
||||
(reset! *opml-imported-pages pages)
|
||||
(reset! *opml-importing? false))))))
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose a OPML file."
|
||||
:error))))}]
|
||||
[:div.mt-4
|
||||
(case opml-importing?
|
||||
true (ui/loading "Loading")
|
||||
false [:div
|
||||
[:b "Importing finished!"]
|
||||
[:tr
|
||||
(mapv (fn [page-name] [:tb
|
||||
[:a {:href (rfe/href :page {:name page-name})} page-name]])
|
||||
@*opml-imported-pages)]]
|
||||
nil)]]))
|
|
@ -13,8 +13,8 @@
|
|||
[]
|
||||
[:div.help.cp__sidebar-help-docs
|
||||
(let [discourse-with-icon [:div.flex-row.inline-flex.items-center
|
||||
[:span.mr-1 (t :help/forum-community)]
|
||||
(ui/icon "message-circle" {:style {:font-size 20}})]
|
||||
[:span.mr-1 (t :help/forum-community)]
|
||||
(ui/icon "message-circle" {:style {:font-size 20}})]
|
||||
list
|
||||
[{:title "Usage"
|
||||
:children [[[:a
|
||||
|
@ -25,7 +25,7 @@
|
|||
[(t :help/docs) "https://docs.logseq.com/"]
|
||||
[(t :help/start) "https://docs.logseq.com/#/page/tutorial"]
|
||||
["FAQ" "https://docs.logseq.com/#/page/faq"]]}
|
||||
|
||||
|
||||
{:title "Community"
|
||||
:children [[(t :help/awesome-logseq) "https://github.com/logseq/awesome-logseq"]
|
||||
[(t :help/blog) "https://blog.logseq.com"]
|
||||
|
@ -36,7 +36,7 @@
|
|||
[(t :help/bug) "https://github.com/logseq/logseq/issues/new?labels=from:in-app&template=bug_report.yaml"]
|
||||
[(t :help/feature) "https://discuss.logseq.com/c/feature-requests/"]
|
||||
[(t :help/changelog) "https://docs.logseq.com/#/page/changelog"]]}
|
||||
|
||||
|
||||
{:title "About"
|
||||
:children [[(t :help/about) "https://logseq.com/blog/about"]]}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
|||
:children [[(t :help/privacy) "https://logseq.com/blog/privacy-policy"]
|
||||
[(t :help/terms) "https://logseq.com/blog/terms"]]}]]
|
||||
|
||||
|
||||
|
||||
|
||||
(map (fn [sublist]
|
||||
[[:p.mt-4.mb-1 [:b (:title sublist)]]
|
||||
|
|
|
@ -314,7 +314,6 @@ body[data-page=import] {
|
|||
|
||||
small {
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
(:require [frontend.state :as state]
|
||||
[rum.core :as rum]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.context.i18n :refer [t]]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.util :as util]
|
||||
[frontend.handler.web.nfs :as nfs]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
|
@ -126,15 +128,13 @@
|
|||
[:strong.uppercase title]
|
||||
[:small.opacity-50 label]]]))]]])))
|
||||
|
||||
(defonce *roam-importing? (atom nil))
|
||||
(defonce *lsq-importing? (atom nil))
|
||||
(defonce *opml-importing? (atom nil))
|
||||
(defonce *opml-imported-pages (atom nil))
|
||||
|
||||
(defn- finished-cb
|
||||
[]
|
||||
(route-handler/redirect-to-home!)
|
||||
(notification/show! "Import finished!" :success)
|
||||
(route-handler/redirect-to-home!))
|
||||
(ui-handler/re-render-root!))
|
||||
|
||||
(defn- roam-import-handler
|
||||
[e]
|
||||
|
@ -142,13 +142,16 @@
|
|||
file-name (gobj/get file "name")]
|
||||
(if (string/ends-with? file-name ".json")
|
||||
(do
|
||||
(reset! *roam-importing? true)
|
||||
(state/set-state! :graph/importing :roam-json)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(external-handler/import-from-roam-json! text
|
||||
#(do (reset! *roam-importing? false) (finished-cb))))))
|
||||
(external-handler/import-from-roam-json!
|
||||
text
|
||||
#(do
|
||||
(state/set-state! :graph/importing nil)
|
||||
(finished-cb))))))
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose a JSON file."
|
||||
:error))))
|
||||
|
@ -157,32 +160,27 @@
|
|||
[e]
|
||||
(let [file (first (array-seq (.-files (.-target e))))
|
||||
file-name (some-> (gobj/get file "name")
|
||||
(string/lower-case))]
|
||||
(cond (string/ends-with? file-name ".edn")
|
||||
(do
|
||||
(reset! *lsq-importing? true)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(external-handler/import-from-edn! text
|
||||
#(do (reset! *lsq-importing? false) (finished-cb))))))
|
||||
(.readAsText reader file)))
|
||||
|
||||
(string/ends-with? file-name ".json")
|
||||
(do
|
||||
(reset! *lsq-importing? true)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(external-handler/import-from-json! text
|
||||
#(do (reset! *lsq-importing? false) (finished-cb))))))
|
||||
(.readAsText reader file)))
|
||||
|
||||
:else
|
||||
(notification/show! "Please choose an EDN or a JSON file."
|
||||
:error))))
|
||||
(string/lower-case))
|
||||
edn? (string/ends-with? file-name ".edn")
|
||||
json? (string/ends-with? file-name ".json")]
|
||||
(if (or edn? json?)
|
||||
(do
|
||||
(state/set-state! :graph/importing :logseq)
|
||||
(let [reader (js/FileReader.)
|
||||
import-f (if edn?
|
||||
external-handler/import-from-edn!
|
||||
external-handler/import-from-json!)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
(let [text (.. e -target -result)]
|
||||
(import-f
|
||||
text
|
||||
#(do
|
||||
(state/set-state! :graph/importing nil)
|
||||
(finished-cb))))))
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose an EDN or a JSON file."
|
||||
:error))))
|
||||
|
||||
(defn- opml-import-handler
|
||||
[e]
|
||||
|
@ -190,7 +188,7 @@
|
|||
file-name (gobj/get file "name")]
|
||||
(if (string/ends-with? file-name ".opml")
|
||||
(do
|
||||
(reset! *opml-importing? true)
|
||||
(state/set-state! :graph/importing :opml)
|
||||
(let [reader (js/FileReader.)]
|
||||
(set! (.-onload reader)
|
||||
(fn [e]
|
||||
|
@ -198,7 +196,7 @@
|
|||
(external-handler/import-from-opml! text
|
||||
(fn [pages]
|
||||
(reset! *opml-imported-pages pages)
|
||||
(reset! *opml-importing? false)
|
||||
(state/set-state! :graph/importing nil)
|
||||
(finished-cb))))))
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose a OPML file."
|
||||
|
@ -206,11 +204,18 @@
|
|||
|
||||
(rum/defc importer < rum/reactive
|
||||
[{:keys [query-params]}]
|
||||
(let [roam-importing? (rum/react *roam-importing?)
|
||||
lsq-importing? (rum/react *lsq-importing?)
|
||||
opml-importing? (rum/react *opml-importing?)
|
||||
importing? (or roam-importing? lsq-importing? opml-importing?)]
|
||||
|
||||
(if (state/sub :graph/importing)
|
||||
(let [{:keys [total current-idx current-page]} (state/sub :graph/importing-state)
|
||||
left-label [:div.flex.flex-row.font-bold
|
||||
(t :importing)
|
||||
[:div.hidden.md:flex.flex-row
|
||||
[:span.mr-1 ": "]
|
||||
[:div.text-ellipsis-wrapper {:style {:max-width 300}}
|
||||
current-page]]]
|
||||
width (js/Math.round (* (.toFixed (/ current-idx total) 2) 100))
|
||||
process (when (and total current-idx)
|
||||
(str current-idx "/" total))]
|
||||
(ui/progress-bar-with-label width left-label process))
|
||||
(setups-container
|
||||
:importer
|
||||
[:article.flex.flex-col.items-center.importer.py-16.px-8
|
||||
|
@ -219,39 +224,30 @@
|
|||
[:h2 "If they are in a JSON, EDN or Markdown format Logseq can work with them."]]
|
||||
[:section.d.md:flex
|
||||
[:label.action-input.flex.items-center.mx-2.my-2
|
||||
{:disabled importing?}
|
||||
[:span.as-flex-center [:i (svg/roam-research 28)]]
|
||||
[:div.flex.flex-col
|
||||
(if roam-importing?
|
||||
(ui/loading "Importing ...")
|
||||
[[:strong "RoamResearch"]
|
||||
[:small "Import a JSON Export of your Roam graph"]])]
|
||||
[[:strong "RoamResearch"]
|
||||
[:small "Import a JSON Export of your Roam graph"]]]
|
||||
[:input.absolute.hidden
|
||||
{:id "import-roam"
|
||||
:type "file"
|
||||
:on-change roam-import-handler}]]
|
||||
|
||||
[:label.action-input.flex.items-center.mx-2.my-2
|
||||
{:disabled importing?}
|
||||
[:span.as-flex-center [:i (svg/logo 28)]]
|
||||
[:span.flex.flex-col
|
||||
(if lsq-importing?
|
||||
(ui/loading "Importing ...")
|
||||
[[:strong "EDN / JSON"]
|
||||
[:small "Import an EDN or a JSON Export of your Logseq graph"]])]
|
||||
[[:strong "EDN / JSON"]
|
||||
[:small "Import an EDN or a JSON Export of your Logseq graph"]]]
|
||||
[:input.absolute.hidden
|
||||
{:id "import-lsq"
|
||||
:type "file"
|
||||
:on-change lsq-import-handler}]]
|
||||
|
||||
[:label.action-input.flex.items-center.mx-2.my-2
|
||||
{:disabled importing?}
|
||||
[:span.as-flex-center (ui/icon "sitemap" {:style {:fontSize "26px"}})]
|
||||
[:span.flex.flex-col
|
||||
(if opml-importing?
|
||||
(ui/loading "Importing ...")
|
||||
[[:strong "OPML"]
|
||||
[:small " Import OPML files"]])]
|
||||
[[:strong "OPML"]
|
||||
[:small " Import OPML files"]]]
|
||||
|
||||
[:input.absolute.hidden
|
||||
{:id "import-opml"
|
||||
|
|
|
@ -252,6 +252,7 @@
|
|||
:developer-mode-alert "You need to restart the app to enable the plugin system. Do you want to restart it now?"
|
||||
:relaunch-confirm-to-work "Should relaunch app to make it work. Do you want to restart it now?"
|
||||
:import "Import"
|
||||
:importing "Importing"
|
||||
:join-community "Join the community"
|
||||
:sponsor-us "Sponsor Us"
|
||||
:discourse-title "Our forum!"
|
||||
|
|
|
@ -185,15 +185,13 @@
|
|||
repo-dir (config/get-local-dir repo)
|
||||
ext (util/get-file-ext path)
|
||||
db-content (or old-content (db/get-file repo path) "")
|
||||
contents-matched? (contents-matched? disk-content db-content)
|
||||
pending-writes (state/get-write-chan-length)]
|
||||
contents-matched? (contents-matched? disk-content db-content)]
|
||||
(cond
|
||||
(and
|
||||
(not= stat :not-found) ; file on the disk was deleted
|
||||
(not contents-matched?)
|
||||
(not (contains? #{"excalidraw" "edn" "css"} ext))
|
||||
(not (string/includes? path "/.recycle/"))
|
||||
(zero? pending-writes))
|
||||
(not (string/includes? path "/.recycle/")))
|
||||
(p/let [disk-content (encrypt/decrypt disk-content)]
|
||||
(state/pub-event! [:file/not-matched-from-disk path disk-content content]))
|
||||
|
||||
|
|
|
@ -163,7 +163,6 @@
|
|||
(if file-handle
|
||||
(-> (p/let [local-file (.getFile file-handle)
|
||||
local-content (.text local-file)
|
||||
pending-writes (state/get-write-chan-length)
|
||||
ext (string/lower-case (util/get-file-ext path))
|
||||
db-content (db/get-file repo path)
|
||||
contents-matched? (contents-matched? local-content (or db-content ""))]
|
||||
|
@ -173,8 +172,7 @@
|
|||
(not (:skip-compare? opts))
|
||||
(not contents-matched?)
|
||||
(not (contains? #{"excalidraw" "edn" "css"} ext))
|
||||
(not (string/includes? path "/.recycle/"))
|
||||
(zero? pending-writes))
|
||||
(not (string/includes? path "/.recycle/")))
|
||||
(p/let [local-content (encrypt/decrypt local-content)]
|
||||
(state/pub-event! [:file/not-matched-from-disk path local-content content]))
|
||||
(p/let [_ (verify-permission repo file-handle true)
|
||||
|
|
|
@ -53,15 +53,13 @@
|
|||
disk-content (or disk-content "")
|
||||
ext (string/lower-case (util/get-file-ext path))
|
||||
db-content (or old-content (db/get-file repo path) "")
|
||||
contents-matched? (contents-matched? disk-content db-content)
|
||||
pending-writes (state/get-write-chan-length)]
|
||||
contents-matched? (contents-matched? disk-content db-content)]
|
||||
(cond
|
||||
(and
|
||||
(not= stat :not-found) ; file on the disk was deleted
|
||||
(not contents-matched?)
|
||||
(not (contains? #{"excalidraw" "edn" "css"} ext))
|
||||
(not (string/includes? path "/.recycle/"))
|
||||
(zero? pending-writes))
|
||||
(not (string/includes? path "/.recycle/")))
|
||||
(p/let [disk-content (encrypt/decrypt disk-content)]
|
||||
(state/pub-event! [:file/not-matched-from-disk path disk-content content]))
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@
|
|||
(p/do! (mobile-util/hide-splash)))
|
||||
|
||||
(db/run-batch-txs!)
|
||||
(file-handler/run-writes-chan!)
|
||||
|
||||
(when config/dev?
|
||||
(enable-datalog-console))
|
||||
(when (util/electron?)
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
[frontend.handler.page :as page]
|
||||
[frontend.handler.editor :as editor]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.util :as util]))
|
||||
[frontend.util :as util]
|
||||
[clojure.core.async :as async]
|
||||
[medley.core :as medley]))
|
||||
|
||||
(defn index-files!
|
||||
"Create file structure, then parse into DB (client only)"
|
||||
|
@ -42,7 +44,7 @@
|
|||
".md")]
|
||||
{:file/path path
|
||||
:file/content text}))))
|
||||
files)
|
||||
files)
|
||||
files (remove nil? files)]
|
||||
(repo-handler/parse-files-and-load-to-db! repo files nil)
|
||||
(let [files (->> (map (fn [{:file/keys [path content]}] (when path [path content])) files)
|
||||
|
@ -53,13 +55,13 @@
|
|||
:finish-handler finish-handler}))
|
||||
(let [journal-pages-tx (let [titles (filter date/valid-journal-title? titles)]
|
||||
(map
|
||||
(fn [title]
|
||||
(let [day (date/journal-title->int title)
|
||||
page-name (util/page-name-sanity-lc (date-time-util/int->journal-title day (state/get-date-formatter)))]
|
||||
{:block/name page-name
|
||||
:block/journal? true
|
||||
:block/journal-day day}))
|
||||
titles))]
|
||||
(fn [title]
|
||||
(let [day (date/journal-title->int title)
|
||||
page-name (util/page-name-sanity-lc (date-time-util/int->journal-title day (state/get-date-formatter)))]
|
||||
{:block/name page-name
|
||||
:block/journal? true
|
||||
:block/journal-day day}))
|
||||
titles))]
|
||||
(when (seq journal-pages-tx)
|
||||
(db/transact! repo journal-pages-tx)))))
|
||||
|
||||
|
@ -132,27 +134,44 @@
|
|||
"\nSkipped and continue the remaining import.") :error))))))
|
||||
title)
|
||||
|
||||
(defn- pre-transact-uuids
|
||||
(defn- pre-transact-uuids!
|
||||
"Collect all uuids from page trees and write them to the db before hand."
|
||||
[pages]
|
||||
(let [uuids (map (fn [block]
|
||||
{:block/uuid (:uuid block)})
|
||||
(mapcat #(tree-seq map? :children %)
|
||||
pages))]
|
||||
(db/transact! uuids)
|
||||
pages))
|
||||
(let [uuids (mapv (fn [block]
|
||||
{:block/uuid (:uuid block)})
|
||||
(mapcat #(tree-seq map? :children %)
|
||||
pages))]
|
||||
(db/transact! uuids)))
|
||||
|
||||
(defn- import-from-tree!
|
||||
"Not rely on file system - backend compatible.
|
||||
tree-translator-fn: translate exported tree structure to the desired tree for import"
|
||||
[data tree-translator-fn]
|
||||
(try (->> (:blocks data)
|
||||
(map tree-translator-fn)
|
||||
(pre-transact-uuids)
|
||||
(mapv create-page-with-exported-tree!))
|
||||
(editor/set-blocks-id! (db/get-all-referenced-blocks-uuid))
|
||||
(catch js/Error e
|
||||
(notification/show! (str "Error happens when importing:\n" e) :error))))
|
||||
(let [imported-chan (async/promise-chan)
|
||||
blocks (->> (:blocks data)
|
||||
(mapv tree-translator-fn )
|
||||
(sort-by :title)
|
||||
(medley/indexed))
|
||||
job-chan (async/to-chan! blocks)]
|
||||
(try
|
||||
(state/set-state! [:graph/importing-state :total] (count blocks))
|
||||
(pre-transact-uuids! blocks)
|
||||
(async/go-loop []
|
||||
(if-let [[i block] (async/<! job-chan)]
|
||||
(do
|
||||
(state/set-state! [:graph/importing-state :current-idx] (inc i))
|
||||
(state/set-state! [:graph/importing-state :current-page] (:title block))
|
||||
(async/<! (async/timeout 10))
|
||||
(create-page-with-exported-tree! block)
|
||||
(recur))
|
||||
(do
|
||||
(editor/set-blocks-id! (db/get-all-referenced-blocks-uuid))
|
||||
(async/offer! imported-chan true))))
|
||||
(catch :default e
|
||||
(notification/show! (str "Error happens when importing:\n" e) :error)
|
||||
(async/offer! imported-chan true)))
|
||||
|
||||
imported-chan))
|
||||
|
||||
(defn tree-vec-translate-edn
|
||||
"Actions to do for loading edn tree structure.
|
||||
|
@ -177,8 +196,9 @@
|
|||
|
||||
(defn import-from-edn!
|
||||
[raw finished-ok-handler]
|
||||
(import-from-tree! (edn/read-string raw) tree-vec-translate-edn)
|
||||
(finished-ok-handler nil)) ;; it was designed to accept a list of imported page names but now deprecated
|
||||
(async/go
|
||||
(async/<! (import-from-tree! (edn/read-string raw) tree-vec-translate-edn))
|
||||
(finished-ok-handler nil))) ;; it was designed to accept a list of imported page names but now deprecated
|
||||
|
||||
(defn tree-vec-translate-json
|
||||
"Actions to do for loading json tree structure.
|
||||
|
@ -210,5 +230,6 @@
|
|||
[raw finished-ok-handler]
|
||||
(let [json (js/JSON.parse raw)
|
||||
clj-data (js->clj json :keywordize-keys true)]
|
||||
(import-from-tree! clj-data tree-vec-translate-json))
|
||||
(finished-ok-handler nil)) ;; it was designed to accept a list of imported page names but now deprecated
|
||||
(async/go
|
||||
(async/<! (import-from-tree! clj-data tree-vec-translate-json))
|
||||
(finished-ok-handler nil)))) ;; it was designed to accept a list of imported page names but now deprecated
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
(:refer-clojure :exclude [load-file])
|
||||
(:require ["/frontend/utils" :as utils]
|
||||
[borkdude.rewrite-edn :as rewrite]
|
||||
[cljs.core.async.interop :refer [<p!]]
|
||||
[clojure.core.async :as async]
|
||||
[frontend.config :as config]
|
||||
[frontend.db :as db]
|
||||
[frontend.fs :as fs]
|
||||
|
@ -206,30 +204,8 @@
|
|||
(alter-file repo path new-content {:reset? false
|
||||
:re-render-root? false}))
|
||||
|
||||
(defn alter-files
|
||||
[repo files {:keys [reset? update-db?]
|
||||
:or {reset? false
|
||||
update-db? true}
|
||||
:as opts}]
|
||||
;; old file content
|
||||
(let [file->content (let [paths (map first files)]
|
||||
(zipmap paths
|
||||
(map (fn [path] (db/get-file repo path)) paths)))]
|
||||
;; update db
|
||||
(when update-db?
|
||||
(doseq [[path content] files]
|
||||
(if reset?
|
||||
(reset-file! repo path content)
|
||||
(db/set-file-content! repo path content))))
|
||||
|
||||
(when-let [chan (state/get-file-write-chan)]
|
||||
(let [chan-callback (:chan-callback opts)]
|
||||
(async/put! chan [repo files opts file->content])
|
||||
(when chan-callback
|
||||
(chan-callback))))))
|
||||
|
||||
(defn alter-files-handler!
|
||||
[repo files {:keys [finish-handler chan]} file->content]
|
||||
[repo files {:keys [finish-handler]} file->content]
|
||||
(let [write-file-f (fn [[path content]]
|
||||
(when path
|
||||
(let [original-content (get file->content path)]
|
||||
|
@ -254,30 +230,30 @@
|
|||
:error error})))))))
|
||||
finish-handler (fn []
|
||||
(when finish-handler
|
||||
(finish-handler))
|
||||
(ui-handler/re-render-file!))]
|
||||
(finish-handler)))]
|
||||
(-> (p/all (map write-file-f files))
|
||||
(p/then (fn []
|
||||
(finish-handler)
|
||||
(when chan
|
||||
(async/put! chan true))))
|
||||
(finish-handler)))
|
||||
(p/catch (fn [error]
|
||||
(println "Alter files failed:")
|
||||
(js/console.error error)
|
||||
(async/put! chan false))))))
|
||||
(js/console.error error))))))
|
||||
|
||||
(defn run-writes-chan!
|
||||
[]
|
||||
(let [chan (state/get-file-write-chan)]
|
||||
(async/go-loop []
|
||||
(let [args (async/<! chan)]
|
||||
;; return a channel
|
||||
(try
|
||||
(<p! (apply alter-files-handler! args))
|
||||
(catch js/Error e
|
||||
(log/error :file/write-failed e))))
|
||||
(recur))
|
||||
chan))
|
||||
(defn alter-files
|
||||
[repo files {:keys [reset? update-db?]
|
||||
:or {reset? false
|
||||
update-db? true}
|
||||
:as opts}]
|
||||
;; old file content
|
||||
(let [file->content (let [paths (map first files)]
|
||||
(zipmap paths
|
||||
(map (fn [path] (db/get-file repo path)) paths)))]
|
||||
;; update db
|
||||
(when update-db?
|
||||
(doseq [[path content] files]
|
||||
(if reset?
|
||||
(reset-file! repo path content)
|
||||
(db/set-file-content! repo path content))))
|
||||
(alter-files-handler! repo files opts file->content)))
|
||||
|
||||
(defn watch-for-current-graph-dir!
|
||||
[]
|
||||
|
|
|
@ -99,12 +99,6 @@
|
|||
(doseq [component (state/get-custom-query-components)]
|
||||
(rum/request-render component)))))
|
||||
|
||||
(defn re-render-file!
|
||||
[]
|
||||
(when-let [component (state/get-file-component)]
|
||||
(when (= :file (state/get-current-route))
|
||||
(rum/request-render component))))
|
||||
|
||||
(defn highlight-element!
|
||||
[fragment]
|
||||
(let [id (and
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
(ns frontend.modules.file.core
|
||||
(:require [cljs.core.async :as async]
|
||||
[clojure.string :as string]
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.config :as config]
|
||||
[frontend.date :as date]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.property :as property]))
|
||||
[frontend.util.property :as property]
|
||||
[frontend.handler.file :as file-handler]))
|
||||
|
||||
(defn- indented-block-content
|
||||
[content spaces-tabs]
|
||||
|
@ -101,16 +101,6 @@
|
|||
|
||||
(def init-level 1)
|
||||
|
||||
(defn push-to-write-chan
|
||||
[files & opts]
|
||||
(let [repo (state/get-current-repo)
|
||||
chan (state/get-file-write-chan)]
|
||||
(assert (some? chan) "File write chan shouldn't be nil")
|
||||
(let [chan-callback (:chan-callback opts)]
|
||||
(async/put! chan [repo files opts])
|
||||
(when chan-callback
|
||||
(chan-callback)))))
|
||||
|
||||
(defn- transact-file-tx-if-not-exists!
|
||||
[page ok-handler]
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
|
@ -143,8 +133,9 @@
|
|||
file-path (-> (db-utils/entity file-db-id) :file/path)
|
||||
_ (assert (string? file-path) "File path should satisfy string?")
|
||||
;; FIXME: name conflicts between multiple graphs
|
||||
files [[file-path new-content]]]
|
||||
(push-to-write-chan files)))
|
||||
files [[file-path new-content]]
|
||||
repo (state/get-current-repo)]
|
||||
(file-handler/alter-files-handler! repo files {} {})))
|
||||
|
||||
(defn save-tree
|
||||
[page-block tree]
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[lambdaisland.glogi :as log]
|
||||
[frontend.state :as state]))
|
||||
|
||||
(defonce write-chan (async/chan 100))
|
||||
(defonce write-chan-batch-buf (atom []))
|
||||
|
||||
(def batch-write-interval 1000)
|
||||
|
@ -27,8 +26,8 @@
|
|||
page-db-id (:db/id page-block)
|
||||
blocks-count (model/get-page-blocks-count repo page-db-id)]
|
||||
(if (and (> blocks-count 500)
|
||||
(not (state/input-idle? repo :diff 3000))) ; long page
|
||||
(async/put! write-chan [repo page-db-id])
|
||||
(not (state/input-idle? repo :diff 3000))) ; long page
|
||||
(async/put! (state/get-file-write-chan) [repo page-db-id])
|
||||
(let [blocks (model/get-page-blocks-no-cache repo (:block/name page-block))]
|
||||
(when-not (and (= 1 (count blocks))
|
||||
(string/blank? (:block/content (first blocks)))
|
||||
|
@ -59,9 +58,11 @@
|
|||
"Write file failed, can't find the current page!"
|
||||
:error)
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(async/put! write-chan [repo page-db-id]))))
|
||||
(if (:graph/importing @state/state) ; write immediately
|
||||
(write-files! [[repo page-db-id]])
|
||||
(async/put! (state/get-file-write-chan) [repo page-db-id])))))
|
||||
|
||||
(util/batch write-chan
|
||||
(util/batch (state/get-file-write-chan)
|
||||
batch-write-interval
|
||||
write-files!
|
||||
write-chan-batch-buf)
|
||||
|
|
|
@ -70,15 +70,19 @@
|
|||
tx (util/concat-without-nil truncate-refs-tx refs-tx)
|
||||
tx-report' (if (seq tx)
|
||||
(let [refs-tx-data' (:tx-data (db/transact! repo tx {:outliner/transact? true
|
||||
:compute-new-refs? true}))]
|
||||
:compute-new-refs? true}))]
|
||||
;; merge
|
||||
(assoc tx-report :tx-data (concat (:tx-data tx-report) refs-tx-data')))
|
||||
tx-report)]
|
||||
(react/refresh! repo tx-report')
|
||||
tx-report)
|
||||
importing? (:graph/importing @state/state)]
|
||||
|
||||
(when-not importing?
|
||||
(react/refresh! repo tx-report'))
|
||||
|
||||
(doseq [p (seq pages)]
|
||||
(updated-page-hook tx-report p))
|
||||
(when (and state/lsp-enabled? (seq blocks))
|
||||
|
||||
(when (and state/lsp-enabled? (seq blocks) (not importing?))
|
||||
(state/pub-event! [:plugin/hook-db-tx
|
||||
{:blocks blocks
|
||||
:tx-data (:tx-data tx-report)
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
(atom
|
||||
{:route-match nil
|
||||
:today nil
|
||||
:system/events (async/chan 100)
|
||||
:db/batch-txs (async/chan 100)
|
||||
:file/writes (async/chan 100)
|
||||
:system/events (async/chan 1000)
|
||||
:db/batch-txs (async/chan 1000)
|
||||
:file/writes (async/chan 10000)
|
||||
:file/unlinked-dirs #{}
|
||||
:reactive/custom-queries (async/chan 100)
|
||||
:reactive/custom-queries (async/chan 1000)
|
||||
:notification/show? false
|
||||
:notification/content nil
|
||||
:repo/loading-files? {}
|
||||
|
@ -232,7 +232,9 @@
|
|||
|
||||
:encryption/graph-parsing? false
|
||||
|
||||
:ui/find-in-page nil
|
||||
:ui/find-in-page nil
|
||||
:graph/importing nil
|
||||
:graph/importing-state {}
|
||||
})))
|
||||
|
||||
;; block uuid -> {content(String) -> ast}
|
||||
|
@ -1005,10 +1007,6 @@
|
|||
[]
|
||||
(set-state! :ui/file-component nil))
|
||||
|
||||
(defn get-file-component
|
||||
[]
|
||||
(get @state :ui/file-component))
|
||||
|
||||
(defn set-journals-length!
|
||||
[value]
|
||||
(when value
|
||||
|
@ -1158,11 +1156,6 @@
|
|||
[]
|
||||
(:reactive/custom-queries @state))
|
||||
|
||||
(defn get-write-chan-length
|
||||
[]
|
||||
(let [c (get-file-write-chan)]
|
||||
(count (gobj/get c "buf"))))
|
||||
|
||||
(defn get-left-sidebar-open?
|
||||
[]
|
||||
(get-in @state [:ui/left-sidebar-open?]))
|
||||
|
|
Loading…
Reference in New Issue