瀏覽代碼

fix: build and export of property values

for a :many property that has additional attributes
e.g. :build/tags
Another possible fix for https://github.com/logseq/db-test/issues/636
Gabriel Horner 1 周之前
父節點
當前提交
529be0496c

+ 26 - 23
deps/db/src/logseq/db/frontend/property/build.cljs

@@ -97,43 +97,46 @@
   transacted, given a block and a properties map with raw property values. The
   properties map can have keys that are db-idents or they can be maps. If a map,
   it should have :original-property-id and :db/ident keys.  See
-  ->property-value-tx-m for such an example
+  ->property-value-tx-m for such an example. Options:
 
-  :pure? - ensure this fn is a pure function"
-  [block properties & {:keys [pure?]}]
+  * :pure? - ensure this fn is a pure function
+  * :pvalue-map? - When set, property value is passed as a map with keys :value and :attributes. This
+   allows property values to have additional attributes"
+  [block properties & {:keys [pure? pvalue-map?]}]
   ;; Build :db/id out of uuid if block doesn't have one for tx purposes
   (let [block' (if (:db/id block) block (assoc block :db/id [:block/uuid (:block/uuid block)]))]
     (->> properties
-         (map (fn [[k v]]
-                (let [{:keys [property-value-properties] :as property-map} (if (map? k) k {:db/ident k})
+         (map (fn [[k v*]]
+                (let [property-map (if (map? k) k {:db/ident k})
                       gen-uuid-value-prefix (when pure?
-                                              (or (:db/ident block) (:block/uuid block)))]
+                                              (or (:db/ident block) (:block/uuid block)))
+                      ->pvalue #(if pvalue-map? (:value %) %)
+                      v (if (set? v*)
+                          (set (map ->pvalue v*))
+                          (->pvalue v*))
+                      ->value-block-opts
+                      (fn ->value-block-opts [v']
+                        (cond-> {}
+                          (and pvalue-map? (seq (:attributes v')))
+                          (assoc :properties (:attributes v'))
+                          pure?
+                          (assoc :block-uuid
+                                 (common-uuid/gen-uuid :builtin-block-uuid
+                                                       (str gen-uuid-value-prefix "-" (->pvalue v'))))))]
                   (assert (:db/ident property-map) "Key in map must have a :db/ident")
                   (when pure? (assert (some? gen-uuid-value-prefix) block))
                   [(or (:original-property-id property-map) (:db/ident property-map))
                    (cond
                      (and (set? v) (every? uuid? v))
                      (set (map #(vector :block/uuid %) v))
-                     (set? v)
-                     (set (map #(build-property-value-block
-                                 block' property-map %
-                                 (cond-> {}
-                                   property-value-properties
-                                   (assoc :properties property-value-properties)
-                                   pure?
-                                   (assoc :block-uuid
-                                          (common-uuid/gen-uuid :builtin-block-uuid (str gen-uuid-value-prefix "-" %)))))
-                               v))
+                     (set? v*)
+                     (set
+                      (map #(build-property-value-block block' property-map (->pvalue %) (->value-block-opts %))
+                           v*))
                      (uuid? v)
                      [:block/uuid v]
                      :else
-                     (build-property-value-block block' property-map v
-                                                 (cond-> {}
-                                                   property-value-properties
-                                                   (assoc :properties property-value-properties)
-                                                   pure?
-                                                   (assoc :block-uuid
-                                                          (common-uuid/gen-uuid :builtin-block-uuid (str gen-uuid-value-prefix "-" v))))))])))
+                     (build-property-value-block block' property-map v (->value-block-opts v*)))])))
          (into {}))))
 
 (defn- lookup-id?

+ 23 - 19
deps/db/src/logseq/db/sqlite/build.cljs

@@ -132,29 +132,33 @@
   (->> properties
        (keep (fn [[k v]]
                (when-let [property-map (build-property-map-for-pvalue-tx k v new-block properties-config all-idents)]
-                 [(let [pvalue-attrs (when (:build/property-value v)
-                                       (merge (:build/properties v)
-                                              {:block/tags (mapv #(hash-map :db/ident (get-ident all-idents %))
-                                                                 (:build/tags v))}
-                                              (select-keys v [:block/created-at :block/updated-at :block/uuid])))]
-                    (cond-> property-map
-                      (and (:build/property-value v) (seq pvalue-attrs))
-                      (assoc :property-value-properties pvalue-attrs)))
+                 [property-map
                   (let [property (when (keyword? k) (get properties-config k))
                         closed-value-id (when property (some (fn [item]
                                                                (when (= (:value item) v)
                                                                  (:uuid item)))
-                                                             (get property :build/closed-values)))]
-                    (cond
-                      closed-value-id
-                      closed-value-id
-
-                      (:build/property-value v)
-                      (or (:logseq.property/value v) (:block/title v))
-
-                      :else
-                      v))])))
-       (db-property-build/build-property-values-tx-m new-block)))
+                                                             (get property :build/closed-values)))
+                        build-pvalue
+                        (fn build-pvalue [v]
+                          {:attributes
+                           (when (:build/property-value v)
+                             (merge (:build/properties v)
+                                    {:block/tags (mapv #(hash-map :db/ident (get-ident all-idents %))
+                                                       (:build/tags v))}
+                                    (select-keys v [:block/created-at :block/updated-at :block/uuid])))
+                           :value
+                           (cond
+                             closed-value-id
+                             closed-value-id
+
+                             (:build/property-value v)
+                             (or (:logseq.property/value v) (:block/title v))
+
+                             :else
+                             v)})]
+                      (if (set? v) (set (map build-pvalue v)) (build-pvalue v)))])))
+       ((fn [x]
+          (db-property-build/build-property-values-tx-m new-block x {:pvalue-map? true})))))
 
 (defn- extract-basic-content-refs
   "Extracts basic refs from :block/title like `[[foo]]` or `[[UUID]]`. Can't

+ 16 - 6
deps/db/test/logseq/db/sqlite/export_test.cljs

@@ -830,18 +830,28 @@
   (let [pvalue-uuid1 (random-uuid)
         original-data
         {:classes {:user.class/C1 {}}
-         :properties {:user.property/default {:logseq.property/type :default}}
+         :properties
+         {:user.property/default {:logseq.property/type :default}
+          :user.property/default-many {:logseq.property/type :default
+                                       :db/cardinality :db.cardinality/many}}
          :pages-and-blocks
          [{:page {:block/title "page1"}
-           :blocks [{:block/title "block with a pvalue that has :build/tags"
+           :blocks [{:block/title "block with pvalue that has :build/tags"
                      :build/properties {:user.property/default {:build/property-value :block
-                                                                :block/title "property value block"
+                                                                :block/title "tags pvalue"
                                                                 :build/tags [:user.class/C1]}}}
-                    {:block/title "block that has a pvalue with a view"
+                    {:block/title "block with pvalue that has a view"
                      :build/properties {:user.property/default {:build/property-value :block
-                                                                :block/title "property value block2"
+                                                                :block/title "view pvalue"
                                                                 :block/uuid pvalue-uuid1
-                                                                :build/keep-uuid? true}}}]}
+                                                                :build/keep-uuid? true}}}
+                    {:block/title "block with pvalue map in a :many property"
+                     :build/properties
+                     {:user.property/default-many
+                      #{"yep"
+                        {:build/property-value :block
+                         :block/title ":many pvalue"
+                         :build/tags [:user.class/C1]}}}}]}
           {:page {:block/title "$$$views2"}
            :blocks [{:block/title "Unlinked references",
                      :build/properties