Parcourir la source

fix: exporting class parent or property class

could sometimes lead to failure. Address by shallow copying
as page export should not be recursively exporting properties and
classes that are not visible on a page
Gabriel Horner il y a 8 mois
Parent
commit
4f25e27d9b

+ 23 - 11
deps/db/src/logseq/db/sqlite/export.cljs

@@ -74,7 +74,7 @@
        (into {})))
 
 (defn- build-export-properties
-  [db user-property-idents {:keys [include-properties? include-uuid?]}]
+  [db user-property-idents {:keys [include-properties? include-uuid? shallow-copy?]}]
   (let [properties-config-by-ent
         (->> user-property-idents
              (map (fn [ident]
@@ -86,7 +86,7 @@
                                                 (conj :block/title)))
                          include-uuid?
                          (assoc :block/uuid (:block/uuid property))
-                         (:logseq.property/classes property)
+                         (and (not shallow-copy?) (:logseq.property/classes property))
                          (assoc :build/property-classes (mapv :db/ident (:logseq.property/classes property)))
                          (seq closed-values)
                          (assoc :build/closed-values
@@ -111,22 +111,24 @@
       properties-config)))
 
 (defn- build-export-class
-  [class-ent {:keys [include-parents? include-uuid?] :or {include-parents? true}}]
+  [class-ent {:keys [include-parents? include-uuid? shallow-copy?]
+              :or {include-parents? true}}]
   (cond-> (select-keys class-ent [:block/title])
     include-uuid?
     (assoc :block/uuid (:block/uuid class-ent))
-    (:logseq.property.class/properties class-ent)
+    (and (:logseq.property.class/properties class-ent) (not shallow-copy?))
     (assoc :build/class-properties
            (mapv :db/ident (:logseq.property.class/properties class-ent)))
     ;; It's caller's responsibility to ensure parent is included in final export
     (and include-parents?
+         (not shallow-copy?)
          (:logseq.property/parent class-ent)
          (not= :logseq.class/Root (:db/ident (:logseq.property/parent class-ent))))
     (assoc :build/class-parent
            (:db/ident (:logseq.property/parent class-ent)))))
 
 (defn- build-node-classes
-  [db build-block block-tags]
+  [db build-block block-tags properties]
   (let [pvalue-class-ents (->> (:build/properties build-block)
                                vals
                                (mapcat (fn [val-or-vals]
@@ -134,11 +136,21 @@
                                                  (if (set? val-or-vals) val-or-vals [val-or-vals]))))
                                (remove db-class/logseq-class?)
                                (map #(d/entity db %)))
+        property-classes (->> (mapcat :build/property-classes (vals properties))
+                              (remove db-class/logseq-class?)
+                              set)
         new-class-ents (concat (remove #(db-class/logseq-class? (:db/ident %)) block-tags)
-                               pvalue-class-ents)]
-    (->> new-class-ents
-         (map #(vector (:db/ident %) (build-export-class % {})))
-         (into {}))))
+                               pvalue-class-ents)
+        shallow-classes (set/difference property-classes (set (map :db/ident new-class-ents)))]
+    (merge
+     (when (seq shallow-classes)
+       (->> shallow-classes
+            (map #(d/entity db %))
+            (map #(vector (:db/ident %) (build-export-class % {:shallow-copy? true})))
+            (into {})))
+     (->> new-class-ents
+          (map #(vector (:db/ident %) (build-export-class % {})))
+          (into {})))))
 
 (defn- build-node-export
   "Given a block/page entity and optional existing properties, build an export map of its
@@ -165,7 +177,7 @@
                      (seq ent-properties)
                      (assoc :build/properties
                             (buildable-properties db ent-properties (merge properties new-properties))))
-        new-classes (build-node-classes db build-node (:block/tags entity))]
+        new-classes (build-node-classes db build-node (:block/tags entity) new-properties)]
     (cond-> {:node build-node}
       (seq new-classes)
       (assoc :classes new-classes)
@@ -234,7 +246,7 @@
              (mapcat :logseq.property.class/properties)
              (map :db/ident)
              (remove db-property/logseq-property?))
-        properties (build-export-properties db class-parent-properties {})]
+        properties (build-export-properties db class-parent-properties {:shallow-copy? true})]
     {:classes classes
      :properties properties}))
 

+ 27 - 11
deps/db/test/logseq/db/sqlite/export_test.cljs

@@ -6,7 +6,8 @@
             [logseq.common.util.page-ref :as page-ref]
             [logseq.db.frontend.validate :as db-validate]
             [logseq.db.sqlite.export :as sqlite-export]
-            [logseq.db.test.helper :as db-test]))
+            [logseq.db.test.helper :as db-test]
+            [logseq.common.util :as common-util]))
 
 (defn- export-block-and-import-to-another-block
   "Exports given block from one graph/conn, imports it to a 2nd block and then
@@ -53,7 +54,7 @@
                  (assoc :block/title (name k)))]))
        (into {})))
 
-(deftest ^:focus import-block-in-same-graph
+(deftest import-block-in-same-graph
   (let [original-data
         {:properties {:user.property/default-many {:logseq.property/type :default :db/cardinality :db.cardinality/many}}
          :classes {:user.class/MyClass
@@ -73,7 +74,7 @@
     (is (= (expand-properties (:properties original-data)) (:properties imported-block)))
     (is (= (expand-classes (:classes original-data)) (:classes imported-block)))))
 
-(deftest ^:focus2 import-block-in-different-graph
+(deftest import-block-in-different-graph
   (let [original-data
         {:properties {:user.property/num-many
                       {:logseq.property/type :number
@@ -238,13 +239,20 @@
 (deftest import-page-with-different-page-and-classes
   (let [original-data
         {:properties {:user.property/p1 {:logseq.property/type :default}
-                      :user.property/p2 {:logseq.property/type :default}
-                      :user.property/p3 {:logseq.property/type :default}}
+                      ;; shallow property b/c it's a property for a class' parent
+                      :user.property/p2 {:logseq.property/type :node
+                                         :build/property-classes [:user.class/NodeClass2]}
+                      :user.property/p3 {:logseq.property/type :node
+                                         :build/property-classes [:user.class/NodeClass]}
+                      :user.property/node-p1 {:logseq.property/type :default}}
          :classes {:user.class/MyClass {:build/class-properties [:user.property/p1 :user.property/p2]}
-                   :user.class/MyClass2 {}
+                   :user.class/MyClass2 {:build/class-properties [:user.property/p2]}
                    :user.class/ChildClass {:build/class-parent :user.class/MyClass
                                            :build/class-properties [:user.property/p3]}
-                   :user.class/ChildClass2 {:build/class-parent :user.class/MyClass2}}
+                   :user.class/ChildClass2 {:build/class-parent :user.class/MyClass2}
+                   ;; shallow class b/c it's a property's class property
+                   :user.class/NodeClass {:build/class-properties [:user.property/node-p1]}
+                   :user.class/NodeClass2 {}}
          :pages-and-blocks
          [{:page {:block/title "page1"
                   :build/properties {:user.property/p1 "woot"}
@@ -255,10 +263,18 @@
         conn2 (db-test/create-conn)
         imported-page (export-page-and-import-to-another-graph conn conn2 "page1")]
 
-    (is (= (expand-properties (:properties original-data)) (:properties imported-page))
-        "Page's properties are imported")
-    (is (= (expand-classes (:classes original-data)) (:classes imported-page))
-        "Page's classes are imported")
+    (is (= (-> (expand-properties (:properties original-data))
+               (dissoc :user.property/node-p1)
+               ;; Shallow property doesn't have class
+               (common-util/dissoc-in [:user.property/p2 :build/property-classes]))
+           (:properties imported-page))
+        "Page's properties are imported except for shallow class' property")
+    (is (= (-> (expand-classes (:classes original-data))
+               ;; Shallow class doesn't have properties
+               (common-util/dissoc-in [:user.class/NodeClass :build/class-properties])
+               (dissoc :user.class/NodeClass2))
+           (:classes imported-page))
+        "Page's classes are imported except for shallow property's class")
     (is (= (:pages-and-blocks original-data) (:pages-and-blocks imported-page))
         "Page's blocks are imported")