Browse Source

fix: import of existing pages preserves properties and tags

with :build-existing-tx? option. Makes behavior consistent with blocks.
This also fixes built-in pages that weren't re-importing correctly
w/ modified properties
Gabriel Horner 3 months ago
parent
commit
3219b827e6

+ 16 - 13
deps/db/src/logseq/db/sqlite/build.cljs

@@ -450,7 +450,7 @@
             "Class and property db-idents are unique and do not overlap")
     all-idents))
 
-(defn- build-page-tx [page all-idents page-uuids properties options]
+(defn- build-page-tx [page all-idents page-uuids properties {:keys [build-existing-tx?] :as options}]
   (let [page' (dissoc page :build/tags :build/properties :build/keep-uuid?)
         pvalue-tx-m (->property-value-tx-m page' (:build/properties page) properties all-idents)]
     (cond-> []
@@ -458,16 +458,18 @@
       (into (mapcat #(if (set? %) % [%]) (vals pvalue-tx-m)))
       true
       (conj
-       (block-with-timestamps
-        (merge
-         page'
-         (when (seq (:build/properties page))
-           (->block-properties (merge (:build/properties page) (db-property-build/build-properties-with-ref-values pvalue-tx-m))
-                               page-uuids all-idents options))
-         (when-let [tag-idents (->> (:build/tags page) (map #(get-ident all-idents %)) seq)]
-           {:block/tags (cond-> (mapv #(hash-map :db/ident %) tag-idents)
-                          (empty? (set/intersection (set tag-idents) db-class/page-classes))
-                          (conj :logseq.class/Page))})))))))
+       (merge
+        (if build-existing-tx?
+          {:block/updated-at (common-util/time-ms)}
+          (select-keys (block-with-timestamps page') [:block/created-at :block/updated-at]))
+        page'
+        (when (seq (:build/properties page))
+          (->block-properties (merge (:build/properties page) (db-property-build/build-properties-with-ref-values pvalue-tx-m))
+                              page-uuids all-idents options))
+        (when-let [tag-idents (->> (:build/tags page) (map #(get-ident all-idents %)) seq)]
+          {:block/tags (cond-> (mapv #(hash-map :db/ident %) tag-idents)
+                         (empty? (set/intersection (set tag-idents) db-class/page-classes))
+                         (conj :logseq.class/Page))}))))))
 
 (defn- build-pages-and-blocks-tx
   [pages-and-blocks all-idents page-uuids {:keys [page-id-fn properties build-existing-tx?]
@@ -491,9 +493,10 @@
                           page-id-fn)]
         (into
          ;; page tx
-         (if build-existing-tx?'
+         (if (and build-existing-tx?' (not (:build/properties page')) (not (:build/tags page')))
+           ;; Minimally update existing unless there is useful data to update e.g. properties and tags
            [(select-keys page [:block/uuid :block/created-at :block/updated-at])]
-           (build-page-tx page' all-idents page-uuids properties options))
+           (build-page-tx page' all-idents page-uuids properties (assoc options :build-existing-tx? build-existing-tx?')))
          ;; blocks tx
          (reduce (fn [acc m]
                    (into acc

+ 19 - 2
deps/db/test/logseq/db/sqlite/build_test.cljs

@@ -100,9 +100,17 @@
                        {:block/title "block 2"}]}]})
         block (db-test/find-block-by-content @conn "block 1")
         block2 (db-test/find-block-by-content @conn "block 2")
+        page1 (db-test/find-page-by-title @conn "page1")
+        built-in-page (db-test/find-page-by-title @conn "Quick add")
         {:keys [init-tx block-props-tx]}
         (sqlite-build/build-blocks-tx
-         {:pages-and-blocks [{:page (select-keys (:block/page block) [:block/uuid])
+         {:pages-and-blocks [{:page
+                              {:block/uuid (:block/uuid built-in-page)
+                               :build/keep-uuid? true
+                               :build/properties {:logseq.property/description "foo"}
+                               :block/title "Quick add"}
+                              :blocks []}
+                             {:page (select-keys (:block/page block) [:block/uuid])
                               :blocks [(merge {:block/title "imported task" :block/uuid (:block/uuid block)}
                                               {:build/properties {:logseq.property/status :logseq.property/status.todo}
                                                :build/tags [:logseq.class/Task]})]}]
@@ -123,9 +131,18 @@
         _ (d/transact! conn block-props-tx2)
         updated-block2 (d/entity @conn [:block/uuid (:block/uuid block2)])]
 ;;     (cljs.pprint/pprint _tx)
+    (testing "existing page cases"
+      (is (= (:block/updated-at page1)
+             (:block/updated-at (db-test/find-page-by-title @conn "page1")))
+          "Existing page with no property changes didn't get updated")
+      (is (not= (:block/updated-at built-in-page)
+                (:block/updated-at (db-test/find-page-by-title @conn "Quick add")))
+          "Existing page with property changes does get updated"))
+
     (testing "block with built-in properties and tags"
       (is (= []
-             (filter #(or (:db/id %) (:db/ident %))
+             (filter #(and (not= (:block/uuid %) (:block/uuid built-in-page))
+                           (or (:db/id %) (:db/ident %)))
                      (concat init-tx block-props-tx)))
           "Tx doesn't try to create new blocks or modify existing idents")
       (is (= "imported task" (:block/title updated-block)))

+ 5 - 4
deps/db/test/logseq/db/sqlite/export_test.cljs

@@ -55,7 +55,7 @@
     (sqlite-export/build-export @import-conn {:export-type :page :page-id (:db/id page2)})))
 
 (defn- import-second-time-assertions [conn conn2 page-title original-data
-                                      & {:keys [transform-expected-blocks build-journal]
+                                      & {:keys [transform-expected-blocks build-journal skip-updated-at?]
                                          :or {transform-expected-blocks (fn [bs] (into bs bs))}}]
   (let [page (db-test/find-page-by-title @conn2 page-title)
         imported-page (export-page-and-import-to-another-graph conn conn2 page-title)
@@ -73,8 +73,9 @@
         "Blocks are appended to existing page")
     (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")))
+    (when-not skip-updated-at?
+      (is (= (:block/updated-at page) (:block/updated-at updated-page))
+          "Existing page didn't get updated"))))
 
 (defn- export-graph-and-import-to-another-graph
   "Exports graph and imports it to a 2nd graph, validates it and then exports the 2nd graph"
@@ -398,7 +399,7 @@
     (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)))
+    (import-second-time-assertions conn conn2 "page1" original-data {:skip-updated-at? true})))
 
 (deftest import-journal-page
   (let [original-data