Browse Source

refactor: use namespaced keyword for block export

instead of confusing :build/block. Also improved related tests,
simplified import steps, added some missing sqlite.build docs,
and fixed :build/uuid not working for some existing journals.
Gabriel Horner 10 months ago
parent
commit
8b8055dd72

+ 2 - 1
deps/db/script/create_graph.cljs

@@ -28,9 +28,10 @@
         sqlite-build-edn (merge {:auto-create-ontology? true}
         sqlite-build-edn (merge {:auto-create-ontology? true}
                                 (-> (resolve-path edn-path) fs/readFileSync str edn/read-string))
                                 (-> (resolve-path edn-path) fs/readFileSync str edn/read-string))
         conn (outliner-cli/init-conn dir db-name {:classpath (cp/get-classpath) :import-type :cli/create-graph})
         conn (outliner-cli/init-conn dir db-name {:classpath (cp/get-classpath) :import-type :cli/create-graph})
-        {:keys [init-tx block-props-tx]} (outliner-cli/build-blocks-tx sqlite-build-edn)]
+        {:keys [init-tx block-props-tx] :as _txs} (outliner-cli/build-blocks-tx sqlite-build-edn)]
     (println "Generating" (count (filter :block/name init-tx)) "pages and"
     (println "Generating" (count (filter :block/name init-tx)) "pages and"
              (count (filter :block/title init-tx)) "blocks ...")
              (count (filter :block/title init-tx)) "blocks ...")
+    ;; (cljs.pprint/pprint _txs)
     (d/transact! conn init-tx)
     (d/transact! conn init-tx)
     (d/transact! conn block-props-tx)
     (d/transact! conn block-props-tx)
     (println "Created graph" (str db-name "!"))))
     (println "Created graph" (str db-name "!"))))

+ 3 - 1
deps/db/src/logseq/db/sqlite/build.cljs

@@ -544,7 +544,7 @@
                                                    :block/uuid
                                                    :block/uuid
                                                    (or (:block/uuid page) (common-uuid/gen-uuid :journal-page-uuid date-int))
                                                    (or (:block/uuid page) (common-uuid/gen-uuid :journal-page-uuid date-int))
                                                    :block/tags :logseq.class/Journal})
                                                    :block/tags :logseq.class/Journal})
-                                           (with-meta {::new-page? true})))))
+                                           (with-meta {::new-page? (not (:block/uuid page))})))))
                            m))]
                            m))]
     ;; Order matters as some steps depend on previous step having prepared blocks or pages in a certain way
     ;; Order matters as some steps depend on previous step having prepared blocks or pages in a certain way
     (->> pages-and-blocks
     (->> pages-and-blocks
@@ -641,12 +641,14 @@
        * :build/journal - Define a journal pages as an integer e.g. 20240101 is Jan 1, 2024. :block/title
        * :build/journal - Define a journal pages as an integer e.g. 20240101 is Jan 1, 2024. :block/title
          is not required if using this since it generates one
          is not required if using this since it generates one
        * :build/properties - Defines properties on a page
        * :build/properties - Defines properties on a page
+       * :build/tags - Defines tags on a page
        * :build/keep-uuid? - Keeps :block/uuid because another block depends on it
        * :build/keep-uuid? - Keeps :block/uuid because another block depends on it
      * :blocks - This is a vec of datascript attribute maps for blocks with
      * :blocks - This is a vec of datascript attribute maps for blocks with
        :block/title required. e.g. `{:block/title \"bar\"}`. Additional keys available:
        :block/title required. e.g. `{:block/title \"bar\"}`. Additional keys available:
        * :build/children - A vec of blocks that are nested (indented) under the current block.
        * :build/children - A vec of blocks that are nested (indented) under the current block.
           Allows for outlines to be expressed to whatever depth
           Allows for outlines to be expressed to whatever depth
        * :build/properties - Defines properties on a block
        * :build/properties - Defines properties on a block
+       * :build/tags - Defines tags on a block
        * :build/keep-uuid? - Keeps :block/uuid because another block depends on it
        * :build/keep-uuid? - Keeps :block/uuid because another block depends on it
    * :properties - This is a map to configure properties where the keys are property name keywords
    * :properties - This is a map to configure properties where the keys are property name keywords
      and the values are maps of datascript attributes e.g. `{:logseq.property/type :checkbox}`.
      and the values are maps of datascript attributes e.g. `{:logseq.property/type :checkbox}`.

+ 39 - 42
deps/db/src/logseq/db/sqlite/export.cljs

@@ -137,8 +137,9 @@
          (map #(vector (:db/ident %) (build-export-class % {:include-parents? false})))
          (map #(vector (:db/ident %) (build-export-class % {:include-parents? false})))
          (into {}))))
          (into {}))))
 
 
-(defn- build-entity-export
-  "Given entity and optional existing properties, build an EDN export map"
+(defn- build-node-export
+  "Given a block/page entity and optional existing properties, build an export map of its
+   tags and properties"
   [db entity {:keys [properties include-uuid-fn keep-uuid?] :or {include-uuid-fn (constantly false)}}]
   [db entity {:keys [properties include-uuid-fn keep-uuid?] :or {include-uuid-fn (constantly false)}}]
   (let [ent-properties (dissoc (db-property/properties entity) :block/tags)
   (let [ent-properties (dissoc (db-property/properties entity) :block/tags)
         new-user-property-ids (->> (keys ent-properties)
         new-user-property-ids (->> (keys ent-properties)
@@ -150,7 +151,7 @@
                                    (remove #(get properties %)))
                                    (remove #(get properties %)))
         new-properties (build-export-properties db new-user-property-ids {})
         new-properties (build-export-properties db new-user-property-ids {})
         build-tags (when (seq (:block/tags entity)) (->build-tags (:block/tags entity)))
         build-tags (when (seq (:block/tags entity)) (->build-tags (:block/tags entity)))
-        build-block (cond-> {:block/title (block-title entity)}
+        build-node (cond-> {:block/title (block-title entity)}
                       (include-uuid-fn (:block/uuid entity))
                       (include-uuid-fn (:block/uuid entity))
                       (assoc :block/uuid (:block/uuid entity))
                       (assoc :block/uuid (:block/uuid entity))
                       keep-uuid?
                       keep-uuid?
@@ -160,8 +161,8 @@
                       (seq ent-properties)
                       (seq ent-properties)
                       (assoc :build/properties
                       (assoc :build/properties
                              (buildable-properties db ent-properties (merge properties new-properties))))
                              (buildable-properties db ent-properties (merge properties new-properties))))
-        new-classes (build-export-block-classes db build-block (:block/tags entity))]
-    (cond-> {:build/block build-block}
+        new-classes (build-export-block-classes db build-node (:block/tags entity))]
+    (cond-> {:node build-node}
       (seq new-classes)
       (seq new-classes)
       (assoc :classes new-classes)
       (assoc :classes new-classes)
       (seq new-properties)
       (seq new-properties)
@@ -219,10 +220,10 @@
   [db eid]
   [db eid]
   (let [block-entity (d/entity db eid)
   (let [block-entity (d/entity db eid)
         {:keys [content-ref-uuids _content-ref-ents] :as content-ref-export} (build-content-ref-export db [block-entity])
         {:keys [content-ref-uuids _content-ref-ents] :as content-ref-export} (build-content-ref-export db [block-entity])
-        block-export* (build-entity-export db block-entity {:include-uuid-fn content-ref-uuids})
-        pvalue-uuids (get-pvalue-uuids (:build/block block-export*))
-        block-export (assoc (merge-export-maps block-export* content-ref-export)
-                            :build/block (:build/block block-export*))]
+        node-export (build-node-export db block-entity {:include-uuid-fn content-ref-uuids})
+        pvalue-uuids (get-pvalue-uuids (:node node-export))
+        block-export (merge {::block (:node node-export)}
+                            (merge-export-maps node-export content-ref-export))]
     ;; Maybe add support for this later
     ;; Maybe add support for this later
     (when (seq pvalue-uuids)
     (when (seq pvalue-uuids)
       (throw (ex-info "Exporting a block with :node block objects is not supported" {})))
       (throw (ex-info "Exporting a block with :node block objects is not supported" {})))
@@ -239,13 +240,13 @@
         children (group-by #(get-in % [:block/parent :db/id]) blocks)
         children (group-by #(get-in % [:block/parent :db/id]) blocks)
         build-block (fn build-block [block*]
         build-block (fn build-block [block*]
                       (let [child-nodes (mapv build-block (get children (:db/id block*) []))
                       (let [child-nodes (mapv build-block (get children (:db/id block*) []))
-                            {:build/keys [block] :keys [properties classes]}
-                            (build-entity-export db block* (assoc opts :properties @*properties))
-                            new-pvalue-uuids (get-pvalue-uuids block)]
+                            {:keys [node properties classes]}
+                            (build-node-export db block* (assoc opts :properties @*properties))
+                            new-pvalue-uuids (get-pvalue-uuids node)]
                         (when (seq properties) (swap! *properties merge properties))
                         (when (seq properties) (swap! *properties merge properties))
                         (when (seq classes) (swap! *classes merge classes))
                         (when (seq classes) (swap! *classes merge classes))
                         (when (seq new-pvalue-uuids) (swap! *pvalue-uuids into new-pvalue-uuids))
                         (when (seq new-pvalue-uuids) (swap! *pvalue-uuids into new-pvalue-uuids))
-                        (cond-> block
+                        (cond-> node
                           (seq child-nodes) (assoc :build/children child-nodes))))
                           (seq child-nodes) (assoc :build/children child-nodes))))
         roots (remove #(contains? id-map (get-in % [:block/parent :db/id])) blocks)
         roots (remove #(contains? id-map (get-in % [:block/parent :db/id])) blocks)
         exported-blocks (mapv build-block roots)]
         exported-blocks (mapv build-block roots)]
@@ -288,8 +289,8 @@
         {:keys [blocks properties classes pvalue-uuids]}
         {:keys [blocks properties classes pvalue-uuids]}
         (build-blocks-tree db page-blocks {:include-uuid-fn content-ref-uuids})
         (build-blocks-tree db page-blocks {:include-uuid-fn content-ref-uuids})
         uuid-block-export (build-uuid-block-export db pvalue-uuids content-ref-ents page-entity)
         uuid-block-export (build-uuid-block-export db pvalue-uuids content-ref-ents page-entity)
-        page-ent-export (build-entity-export db page-entity {:properties properties})
-        page (merge (dissoc (:build/block page-ent-export) :block/title)
+        page-ent-export (build-node-export db page-entity {:properties properties})
+        page (merge (dissoc (:node page-ent-export) :block/title)
                     (shallow-copy-page page-entity))
                     (shallow-copy-page page-entity))
         page-blocks-export {:pages-and-blocks [{:page page :blocks blocks}]
         page-blocks-export {:pages-and-blocks [{:page page :blocks blocks}]
                             :properties properties
                             :properties properties
@@ -327,11 +328,25 @@
 
 
 ;; Import fns
 ;; Import fns
 ;; ==========
 ;; ==========
-(defn- ->sqlite-build-options
+(defn- check-for-existing-entities
+  "Checks export map for existing entities and adds :block/uuid to them if they exist in graph to import.
+   Also checks for property conflicts between existing properties and properties to be imported"
   [db {:keys [pages-and-blocks classes properties]} property-conflicts]
   [db {:keys [pages-and-blocks classes properties]} property-conflicts]
   (cond-> {:build-existing-tx? true}
   (cond-> {:build-existing-tx? true}
     (seq pages-and-blocks)
     (seq pages-and-blocks)
-    (assoc :pages-and-blocks pages-and-blocks)
+    (assoc :pages-and-blocks
+           (mapv (fn [m]
+                   (if-let [ent (some->> (get-in m [:page :build/journal])
+                                         (d/datoms db :avet :block/journal-day)
+                                         first
+                                         :e
+                                         (d/entity db))]
+                     (assoc-in m [:page :block/uuid] (:block/uuid ent))
+                     ;; For now only check page uniqueness by title. Could handle more uniqueness checks later
+                     (if-let [ent (some->> (get-in m [:page :block/title]) (ldb/get-case-page db))]
+                       (assoc-in m [:page :block/uuid] (:block/uuid ent))
+                       m)))
+                 pages-and-blocks))
     (seq classes)
     (seq classes)
     (assoc :classes
     (assoc :classes
            (->> classes
            (->> classes
@@ -359,7 +374,7 @@
 (defn- build-block-import-options
 (defn- build-block-import-options
   "Builds options for sqlite-build to import into current-block"
   "Builds options for sqlite-build to import into current-block"
   [current-block export-map]
   [current-block export-map]
-  (let [block (merge (:build/block export-map)
+  (let [block (merge (::block export-map)
                      {:block/uuid (:block/uuid current-block)
                      {:block/uuid (:block/uuid current-block)
                       :block/page (select-keys (:block/page current-block) [:block/uuid])})
                       :block/page (select-keys (:block/page current-block) [:block/uuid])})
         pages-and-blocks
         pages-and-blocks
@@ -367,35 +382,17 @@
           :blocks [(dissoc block :block/page)]}]]
           :blocks [(dissoc block :block/page)]}]]
     (merge-export-maps export-map {:pages-and-blocks pages-and-blocks})))
     (merge-export-maps export-map {:pages-and-blocks pages-and-blocks})))
 
 
-(defn- build-page-import-options
-  [db export-map]
-  (assert (map? (get-in export-map [:pages-and-blocks 0 :page])) "page export exists")
-  (if-let [ent (some->> (get-in export-map [:pages-and-blocks 0 :page :build/journal])
-                        (d/datoms db :avet :block/journal-day)
-                        first
-                        :e
-                        (d/entity db))]
-    (assoc-in export-map [:pages-and-blocks 0 :page] (select-keys ent [:block/uuid]))
-    ;; FIXME: Find an existing page more reliably than :block/title, :block/uuid?
-    (if-let [ent (some->> (get-in export-map [:pages-and-blocks 0 :page :block/title])
-                          (ldb/get-case-page db))]
-      (assoc-in export-map [:pages-and-blocks 0 :page] (select-keys ent [:block/uuid]))
-      export-map)))
-
 (defn build-import
 (defn build-import
   "Given an entity's export map, build the import tx to create it"
   "Given an entity's export map, build the import tx to create it"
-  [db {:keys [current-block]} export-map*]
-  (let [export-map (cond current-block
-                         (build-block-import-options current-block export-map*)
-                         (:pages-and-blocks export-map*)
-                         (build-page-import-options db export-map*)
-                         :else
-                         export-map*)
+  [export-map* db {:keys [current-block]}]
+  (let [export-map (if (and (::block export-map*) current-block)
+                     (build-block-import-options current-block export-map*)
+                     export-map*)
         property-conflicts (atom [])
         property-conflicts (atom [])
-        opts (->sqlite-build-options db export-map property-conflicts)]
+        export-map' (check-for-existing-entities db export-map property-conflicts)]
     (if (seq @property-conflicts)
     (if (seq @property-conflicts)
       (do
       (do
         (js/console.error :property-conflicts @property-conflicts)
         (js/console.error :property-conflicts @property-conflicts)
         {:error (str "The following imported properties conflict with the current graph: "
         {:error (str "The following imported properties conflict with the current graph: "
                      (pr-str (mapv :property-id @property-conflicts)))})
                      (pr-str (mapv :property-id @property-conflicts)))})
-      (sqlite-build/build-blocks-tx opts))))
+      (sqlite-build/build-blocks-tx export-map'))))

+ 12 - 0
deps/db/src/logseq/db/test/helper.cljs

@@ -43,6 +43,18 @@
        first
        first
        (d/entity db)))
        (d/entity db)))
 
 
+(defn find-journal-by-journal-day
+  [db journal-day]
+  (->> journal-day
+       (d/q
+        '[:find [?page ...]
+          :in $ ?journal-day
+          :where
+          [?page :block/journal-day ?journal-day]]
+        db)
+       first
+       (d/entity db)))
+
 (defn readable-properties
 (defn readable-properties
   "Returns an entity's properties and tags in readable form for assertions.
   "Returns an entity's properties and tags in readable form for assertions.
    tags are included here since they behave like properties on an ent"
    tags are included here since they behave like properties on an ent"

+ 58 - 34
deps/db/test/logseq/db/sqlite/export_test.cljs

@@ -3,7 +3,8 @@
             [datascript.core :as d]
             [datascript.core :as d]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.db.sqlite.export :as sqlite-export]
             [logseq.db.sqlite.export :as sqlite-export]
-            [logseq.db.test.helper :as db-test]))
+            [logseq.db.test.helper :as db-test]
+            [logseq.common.util.date-time :as date-time-util]))
 
 
 (defn- export-block-and-import-to-another-block
 (defn- export-block-and-import-to-another-block
   "Exports given block from one graph/conn, imports it to a 2nd block and then
   "Exports given block from one graph/conn, imports it to a 2nd block and then
@@ -12,8 +13,8 @@
   (let [export-block (db-test/find-block-by-content @export-conn export-block-content)
   (let [export-block (db-test/find-block-by-content @export-conn export-block-content)
         import-block (db-test/find-block-by-content @import-conn import-block-content)
         import-block (db-test/find-block-by-content @import-conn import-block-content)
         {:keys [init-tx block-props-tx] :as _txs}
         {:keys [init-tx block-props-tx] :as _txs}
-        (->> (sqlite-export/build-block-export @export-conn [:block/uuid (:block/uuid export-block)])
-             (sqlite-export/build-import @import-conn {:current-block import-block}))
+        (-> (sqlite-export/build-block-export @export-conn [:block/uuid (:block/uuid export-block)])
+            (sqlite-export/build-import @import-conn {:current-block import-block}))
         ;; _ (cljs.pprint/pprint _txs)
         ;; _ (cljs.pprint/pprint _txs)
         _ (d/transact! import-conn init-tx)
         _ (d/transact! import-conn init-tx)
         _ (d/transact! import-conn block-props-tx)]
         _ (d/transact! import-conn block-props-tx)]
@@ -35,7 +36,7 @@
         imported-block (export-block-and-import-to-another-block conn conn "export" "import")]
         imported-block (export-block-and-import-to-another-block conn conn "export" "import")]
 
 
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
-           (:build/block imported-block))
+           (::sqlite-export/block imported-block))
         "Imported block equals exported block")
         "Imported block equals exported block")
     (is (= (:properties original-data) (:properties imported-block)))
     (is (= (:properties original-data) (:properties imported-block)))
     (is (= (:classes original-data) (:classes imported-block)))))
     (is (= (:classes original-data) (:classes imported-block)))))
@@ -67,7 +68,7 @@
         imported-block (export-block-and-import-to-another-block conn conn2 "export" "import")]
         imported-block (export-block-and-import-to-another-block conn conn2 "export" "import")]
 
 
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
-           (:build/block imported-block))
+           (::sqlite-export/block imported-block))
         "Imported block equals exported block")
         "Imported block equals exported block")
     (is (= (:properties original-data) (:properties imported-block)))
     (is (= (:properties original-data) (:properties imported-block)))
     (is (= (:classes original-data) (:classes imported-block)))
     (is (= (:classes original-data) (:classes imported-block)))
@@ -75,7 +76,7 @@
     (testing "same import in another block"
     (testing "same import in another block"
       (let [imported-block (export-block-and-import-to-another-block conn conn2 "export" "import2")]
       (let [imported-block (export-block-and-import-to-another-block conn conn2 "export" "import2")]
         (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
         (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
-               (:build/block imported-block))
+               (::sqlite-export/block imported-block))
             "Imported block equals exported block")
             "Imported block equals exported block")
         (is (= (:properties original-data) (:properties imported-block)))
         (is (= (:properties original-data) (:properties imported-block)))
         (is (= (:classes original-data) (:classes imported-block)))))))
         (is (= (:classes original-data) (:classes imported-block)))))))
@@ -94,7 +95,7 @@
         imported-block (export-block-and-import-to-another-block conn conn2 #"page ref" "import")]
         imported-block (export-block-and-import-to-another-block conn conn2 #"page ref" "import")]
 
 
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
     (is (= (get-in original-data [:pages-and-blocks 0 :blocks 0])
-           (:build/block imported-block))
+           (::sqlite-export/block imported-block))
         "Imported block equals exported block")
         "Imported block equals exported block")
     (is (= (second (:pages-and-blocks original-data))
     (is (= (second (:pages-and-blocks original-data))
            (first (:pages-and-blocks imported-block)))
            (first (:pages-and-blocks imported-block)))
@@ -106,21 +107,29 @@
   [export-conn import-conn page-title]
   [export-conn import-conn page-title]
   (let [page (db-test/find-page-by-title @export-conn page-title)
   (let [page (db-test/find-page-by-title @export-conn page-title)
         {:keys [init-tx block-props-tx] :as _txs}
         {:keys [init-tx block-props-tx] :as _txs}
-        (->> (sqlite-export/build-page-export @export-conn (:db/id page))
-            ;;  ((fn [x] (cljs.pprint/pprint {:export x}) x))
-             (sqlite-export/build-import @import-conn {}))
+        (-> (sqlite-export/build-page-export @export-conn (:db/id page))
+            ;; ((fn [x] (cljs.pprint/pprint {:export x}) x))
+            (sqlite-export/build-import @import-conn {}))
         ;; _ (cljs.pprint/pprint _txs)
         ;; _ (cljs.pprint/pprint _txs)
         _ (d/transact! import-conn init-tx)
         _ (d/transact! import-conn init-tx)
         _ (d/transact! import-conn block-props-tx)
         _ (d/transact! import-conn block-props-tx)
         page2 (db-test/find-page-by-title @import-conn page-title)]
         page2 (db-test/find-page-by-title @import-conn page-title)]
     (sqlite-export/build-page-export @import-conn (:db/id page2))))
     (sqlite-export/build-page-export @import-conn (:db/id page2))))
 
 
-(defn- import-second-time-appends-blocks [conn conn2 page-title original-data]
-  (let [full-imported-page (export-page-and-import-to-another-graph conn conn2 page-title)
+(defn- import-second-time-assertions [conn conn2 page-title original-data]
+  (let [page (db-test/find-page-by-title @conn2 page-title)
+        imported-page (export-page-and-import-to-another-graph conn conn2 page-title)
+        updated-page (db-test/find-page-by-title @conn2 page-title)
         expected-page-and-blocks
         expected-page-and-blocks
         (update-in (:pages-and-blocks original-data) [0 :blocks]
         (update-in (:pages-and-blocks original-data) [0 :blocks]
                    (fn [blocks] (into blocks blocks)))]
                    (fn [blocks] (into blocks blocks)))]
-    (is (= expected-page-and-blocks (:pages-and-blocks full-imported-page)))))
+
+    (is (= expected-page-and-blocks (:pages-and-blocks imported-page))
+        "Blocks are appended to existing page blocks")
+    (is (= (:block/created-at page) (:block/created-at updated-page))
+        "Existing page didn't get re-created")
+    (is (= (:block/updated-at page) (:block/updated-at updated-page))
+        "Existing page didn't get updated")))
 
 
 ;; Tests a variety of blocks including block children with new properties, blocks with users classes
 ;; Tests a variety of blocks including block children with new properties, blocks with users classes
 ;; and blocks with built-in properties and classes
 ;; and blocks with built-in properties and classes
@@ -150,16 +159,16 @@
                      :build/tags [:logseq.class/Task]}]}]}
                      :build/tags [:logseq.class/Task]}]}]}
         conn (db-test/create-conn-with-blocks original-data)
         conn (db-test/create-conn-with-blocks original-data)
         conn2 (db-test/create-conn)
         conn2 (db-test/create-conn)
-        full-imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
+        imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
 
 
-    (is (= (:properties original-data) (:properties full-imported-page))
+    (is (= (:properties original-data) (:properties imported-page))
         "Page's properties are imported")
         "Page's properties are imported")
-    (is (= (:classes original-data) (:classes full-imported-page))
+    (is (= (:classes original-data) (:classes imported-page))
         "Page's classes are imported")
         "Page's classes are imported")
-    (is (= (:pages-and-blocks original-data) (:pages-and-blocks full-imported-page))
+    (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
         "Page's blocks are imported")
         "Page's blocks are imported")
 
 
-    (import-second-time-appends-blocks conn conn2 "page1" original-data)))
+    (import-second-time-assertions conn conn2 "page1" original-data)))
 
 
 (deftest import-page-with-different-ref-types
 (deftest import-page-with-different-ref-types
   (let [block-uuid (random-uuid)
   (let [block-uuid (random-uuid)
@@ -186,16 +195,16 @@
           {:page {:build/journal 20250207 :block/uuid journal-uuid :build/keep-uuid? true}}]}
           {:page {:build/journal 20250207 :block/uuid journal-uuid :build/keep-uuid? true}}]}
         conn (db-test/create-conn-with-blocks original-data)
         conn (db-test/create-conn-with-blocks original-data)
         conn2 (db-test/create-conn)
         conn2 (db-test/create-conn)
-        full-imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
+        imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
 
 
-    (is (= (:properties original-data) (:properties full-imported-page))
+    (is (= (:properties original-data) (:properties imported-page))
         "Page's properties are imported")
         "Page's properties are imported")
-    (is (= (:classes original-data) (:classes full-imported-page))
+    (is (= (:classes original-data) (:classes imported-page))
         "Page's classes are imported")
         "Page's classes are imported")
-    (is (= (:pages-and-blocks original-data) (:pages-and-blocks full-imported-page))
+    (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
         "Page's blocks are imported")
         "Page's blocks are imported")
 
 
-    (import-second-time-appends-blocks conn conn2 "page1" original-data)))
+    (import-second-time-assertions conn conn2 "page1" original-data)))
 
 
 (deftest import-page-with-different-page-and-classes
 (deftest import-page-with-different-page-and-classes
   (let [original-data
   (let [original-data
@@ -210,16 +219,31 @@
            :blocks []}]}
            :blocks []}]}
         conn (db-test/create-conn-with-blocks original-data)
         conn (db-test/create-conn-with-blocks original-data)
         conn2 (db-test/create-conn)
         conn2 (db-test/create-conn)
-        full-imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
+        imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
 
 
-    (is (= (:properties original-data) (:properties full-imported-page))
+    (is (= (:properties original-data) (:properties imported-page))
         "Page's properties are imported")
         "Page's properties are imported")
-    (is (= (:classes original-data) (:classes full-imported-page))
+    (is (= (:classes original-data) (:classes imported-page))
         "Page's classes are imported")
         "Page's classes are imported")
-    (is (= (:pages-and-blocks original-data) (:pages-and-blocks full-imported-page))
+    (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
+        "Page's blocks are imported")
+
+    (import-second-time-assertions conn conn2 "page1" original-data)))
+
+(deftest import-journal-page
+  (let [original-data
+        {:pages-and-blocks
+         [{:page {:build/journal 20250210 :build/tags [:logseq.class/Journal]}
+           :blocks [{:block/title "b1"} {:block/title "b2"}]}]}
+        conn (db-test/create-conn-with-blocks original-data)
+        conn2 (db-test/create-conn)
+        journal-title (date-time-util/int->journal-title 20250210 "MMM do, yyyy")
+        imported-page (export-page-and-import-to-another-graph conn conn2 journal-title)]
+
+    (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
         "Page's blocks are imported")
         "Page's blocks are imported")
 
 
-    (import-second-time-appends-blocks conn conn2 "page1" original-data)))
+    (import-second-time-assertions conn conn2 journal-title original-data)))
 
 
 (deftest import-page-with-different-property-types
 (deftest import-page-with-different-property-types
   (let [block-object-uuid (random-uuid)
   (let [block-object-uuid (random-uuid)
@@ -257,13 +281,13 @@
                      :build/keep-uuid? true}]}]}
                      :build/keep-uuid? true}]}]}
         conn (db-test/create-conn-with-blocks original-data)
         conn (db-test/create-conn-with-blocks original-data)
         conn2 (db-test/create-conn)
         conn2 (db-test/create-conn)
-        full-imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
+        imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
 
 
-    (is (= (:properties original-data) (:properties full-imported-page))
+    (is (= (:properties original-data) (:properties imported-page))
         "Page's properties are imported")
         "Page's properties are imported")
-    (is (= (:classes original-data) (:classes full-imported-page))
+    (is (= (:classes original-data) (:classes imported-page))
         "Page's classes are imported")
         "Page's classes are imported")
-    (is (= (:pages-and-blocks original-data) (:pages-and-blocks full-imported-page))
+    (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
         "Page's blocks are imported")))
         "Page's blocks are imported")))
 
 
 (deftest import-graph-ontology
 (deftest import-graph-ontology
@@ -292,8 +316,8 @@
         conn (db-test/create-conn-with-blocks original-data)
         conn (db-test/create-conn-with-blocks original-data)
         conn2 (db-test/create-conn)
         conn2 (db-test/create-conn)
         {:keys [init-tx block-props-tx] :as _txs}
         {:keys [init-tx block-props-tx] :as _txs}
-        (->> (sqlite-export/build-graph-ontology-export @conn)
-             (sqlite-export/build-import @conn2 {}))
+        (-> (sqlite-export/build-graph-ontology-export @conn)
+            (sqlite-export/build-import @conn2 {}))
         ;; _ (cljs.pprint/pprint _txs)
         ;; _ (cljs.pprint/pprint _txs)
         _ (d/transact! conn2 init-tx)
         _ (d/transact! conn2 init-tx)
         _ (d/transact! conn2 block-props-tx)
         _ (d/transact! conn2 block-props-tx)

+ 4 - 4
src/main/frontend/handler/common/developer.cljs

@@ -69,7 +69,7 @@
 
 
 (defn- import-submit [import-inputs _e]
 (defn- import-submit [import-inputs _e]
   (let [export-map (try (edn/read-string (:import-data @import-inputs)) (catch :default _err ::invalid-import))
   (let [export-map (try (edn/read-string (:import-data @import-inputs)) (catch :default _err ::invalid-import))
-        import-block? (:build/block export-map)
+        import-block? (::sqlite-export/block export-map)
         block (when import-block?
         block (when import-block?
                 (if-let [eid (:block-id (first (state/get-editor-args)))]
                 (if-let [eid (:block-id (first (state/get-editor-args)))]
                   (db/entity [:block/uuid eid])
                   (db/entity [:block/uuid eid])
@@ -77,9 +77,9 @@
     (if (= ::invalid-import export-map)
     (if (= ::invalid-import export-map)
       (notification/show! "The submitted EDN data is invalid! Fix and try again." :warning)
       (notification/show! "The submitted EDN data is invalid! Fix and try again." :warning)
       (let [{:keys [init-tx block-props-tx error] :as txs}
       (let [{:keys [init-tx block-props-tx error] :as txs}
-            (sqlite-export/build-import (db/get-db)
-                                        (when block {:current-block block})
-                                        export-map)]
+            (sqlite-export/build-import export-map
+                                        (db/get-db)
+                                        (when block {:current-block block}))]
         (pprint/pprint txs)
         (pprint/pprint txs)
         (if error
         (if error
           (notification/show! error :error)
           (notification/show! error :error)