Просмотр исходного кода

enhance: export+export refs to classes

Gabriel Horner 1 год назад
Родитель
Сommit
fcdfe518be

+ 56 - 31
deps/db/src/logseq/db/sqlite/export.cljs

@@ -94,8 +94,10 @@
       properties-config)))
 
 (defn- build-export-class
-  [class-ent {:keys [include-parents?]}]
+  [class-ent {:keys [include-parents? include-uuid?]}]
   (cond-> (select-keys class-ent [:block/title])
+    include-uuid?
+    (assoc :block/uuid (:block/uuid class-ent))
     (:logseq.property.class/properties class-ent)
     (assoc :build/class-properties
            (mapv :db/ident (:logseq.property.class/properties class-ent)))
@@ -196,19 +198,46 @@
      :classes @*classes
      :pvalue-uuids @*pvalue-uuids}))
 
-(defn- get-uuid-block-pages [db pvalue-uuids content-ref-ents page-entity]
+(defn- build-uuid-block-export [db pvalue-uuids content-ref-ents page-entity]
   (let [uuid-block-ents-to-export (concat (map #(d/entity db [:block/uuid %]) pvalue-uuids)
-                                          (remove ldb/page? content-ref-ents))]
-    (when (seq uuid-block-ents-to-export)
-      (->> uuid-block-ents-to-export
-           (group-by :block/parent)
-           (map (fn [[parent-page-ent blocks]]
-                  ;; Not a common case but can support later if needed
-                  (when (= parent-page-ent page-entity)
-                    (throw (ex-info "Can't export a uuid block from exported page" {})))
-                  ;; Don't export pvalue-uuids of pvalue blocks as it's too excessive for now
-                  (merge (build-blocks-tree db (sort-by :block/order blocks) {:include-uuid-fn (constantly true)})
-                         {:page (select-keys parent-page-ent [:block/title])})))))))
+                                          (remove ldb/page? content-ref-ents))
+        uuid-block-pages
+        (when (seq uuid-block-ents-to-export)
+          (->> uuid-block-ents-to-export
+               (group-by :block/parent)
+               ;; Remove page-entity because it's already been built for content-ref-ents
+               ;; and it's unlikely and complex to handle for pvalue-uuids
+               ((fn [m] (dissoc m page-entity)))
+               (map (fn [[parent-page-ent blocks]]
+                      ;; Don't export pvalue-uuids of uuid blocks to keep export shallower
+                      (merge (build-blocks-tree db (sort-by :block/order blocks) {:include-uuid-fn (constantly true)})
+                             ;; only shallow copy pages
+                             {:page (select-keys parent-page-ent [:block/title])})))))]
+    {:properties (apply merge (map :properties uuid-block-pages))
+     :classes (apply merge (map :classes uuid-block-pages))
+     :pages-and-blocks (mapv #(select-keys % [:page :blocks]) uuid-block-pages)}))
+
+(defn- build-content-ref-export
+  [db page-blocks]
+  (let [content-ref-uuids (set (mapcat (comp db-content/get-matched-ids :block/title) page-blocks))
+        content-ref-ents (map #(d/entity db [:block/uuid %]) content-ref-uuids)
+        content-ref-pages (filter ldb/internal-page? content-ref-ents)
+        content-ref-properties (when-let [prop-ids (seq (map :db/ident (filter ldb/property? content-ref-ents)))]
+                                 (update-vals (build-export-properties db prop-ids {:include-uuid? true})
+                                              #(merge % {:build/new-property? true})))
+        content-ref-classes (when-let [class-ents (seq (filter ldb/class? content-ref-ents))]
+                              (->> class-ents
+                                   ;; TODO: Export class parents when there's ability to control granularity of export
+                                   (map #(vector (:db/ident %)
+                                                 (assoc (build-export-class % {:include-parents? false :include-uuid? true})
+                                                        :build/new-class? true)))
+                                   (into {})))]
+    {:content-ref-uuids content-ref-uuids
+     :content-ref-ents content-ref-ents
+     :properties content-ref-properties
+     :classes content-ref-classes
+     ;; only shallow copy pages
+     :pages-and-blocks (mapv #(hash-map :page (select-keys % [:block/title :block/uuid])) content-ref-pages)}))
 
 (defn build-page-export [db eid]
   (let [page-entity (d/entity db eid)
@@ -220,16 +249,10 @@
                          (sort-by :block/order)
                          ;; Remove property value blocks as they are included in the block they belong to
                          (remove #(:logseq.property/created-from-property %)))
-        content-ref-uuids (set (mapcat (comp db-content/get-matched-ids :block/title) page-blocks))
-        content-ref-ents (map #(d/entity db [:block/uuid %]) content-ref-uuids)
-        content-ref-pages (filter ldb/internal-page? content-ref-ents)
-        content-ref-properties* (map :db/ident (filter ldb/property? content-ref-ents))
-        content-ref-properties (when content-ref-properties*
-                                 (update-vals (build-export-properties db content-ref-properties* {:include-uuid? true})
-                                              #(merge % {:build/new-property? true})))
+        {:keys [content-ref-uuids content-ref-ents] :as content-ref-export} (build-content-ref-export db page-blocks)
         {:keys [blocks properties classes pvalue-uuids]}
         (build-blocks-tree db page-blocks {:include-uuid-fn content-ref-uuids})
-        uuid-block-pages (get-uuid-block-pages 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)
                     (if (ldb/journal? page-entity)
@@ -237,17 +260,19 @@
                       (select-keys page-entity [:block/title])))
         pages-and-blocks
         (cond-> [{:page page :blocks blocks}]
-          ;; pages from uuid blocks or content-ref-pages are shallow copies e.g. only :block/title
-          (seq uuid-block-pages)
-          (into (map #(select-keys % [:page :blocks]) uuid-block-pages))
-          (seq content-ref-pages)
-          (into (map #(hash-map :page (select-keys % [:block/title :block/uuid])) content-ref-pages)))
+          (seq (:pages-and-blocks uuid-block-export))
+          (into (:pages-and-blocks uuid-block-export))
+          (seq (:pages-and-blocks content-ref-export))
+          (into (:pages-and-blocks content-ref-export)))
         ;; Use merge-with to preserve new-property?
-        properties' (apply merge-with merge properties
-                           (:properties page-ent-export)
-                           content-ref-properties
-                           (map :properties uuid-block-pages))
-        classes' (apply merge classes (:classes page-ent-export) (map :classes uuid-block-pages))
+        properties' (merge-with merge properties
+                                (:properties page-ent-export)
+                                (:properties content-ref-export)
+                                (:properties uuid-block-export))
+        classes' (merge-with merge classes
+                             (:classes page-ent-export)
+                             (:classes content-ref-export)
+                             (:classes uuid-block-export))
         page-export
         (cond-> {:pages-and-blocks pages-and-blocks}
           (seq properties')

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

@@ -164,11 +164,11 @@
 
 (deftest import-page-with-different-ref-types
   (let [block-uuid (random-uuid)
-        ;; class-uuid (random-uuid)
+        class-uuid (random-uuid)
         page-uuid (random-uuid)
         property-uuid (random-uuid)
         original-data
-        {;:classes {:C1 {:block/uuid class-uuid}}
+        {:classes {:user.class/C1 {:block/title "C1" :block/uuid class-uuid :build/new-class? true}}
          :properties {:user.property/p1
                       {:db/cardinality :db.cardinality/one, :logseq.property/type :default
                        :block/uuid property-uuid :block/title "p1" :build/new-property? true}}
@@ -176,8 +176,8 @@
          [{:page {:block/title "page1"}
            :blocks [{:block/title (str "page ref to " (page-ref/->page-ref page-uuid))}
                     {:block/title (str "block ref to " (page-ref/->page-ref block-uuid))}
-                    #_{:block/title (str "class ref to " (page-ref/->page-ref class-uuid))}
-                    #_{:block/title (str "inline class ref to #" (page-ref/->page-ref class-uuid))}
+                    {:block/title (str "class ref to " (page-ref/->page-ref class-uuid))}
+                    {:block/title (str "inline class ref to #" (page-ref/->page-ref class-uuid))}
                     {:block/title (str "property ref to " (page-ref/->page-ref property-uuid))}]}
           {:page {:block/title "page with block ref"}
            :blocks [{:block/title "hi" :block/uuid block-uuid}]}