Browse Source

fix: property path-refs

1. :block/refs support to page properties
2. don't add built-in properties to refs
3. don't add current block or parents' other properties to :default blocks
Tienson Qin 1 năm trước cách đây
mục cha
commit
f218732b17

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

@@ -510,7 +510,9 @@
 (defn class?
 (defn class?
   [entity]
   [entity]
   (contains? (:block/type entity) "class"))
   (contains? (:block/type entity) "class"))
-
+(defn property?
+  [entity]
+  (contains? (:block/type entity) "property"))
 (defn closed-value?
 (defn closed-value?
   [entity]
   [entity]
   (contains? (:block/type entity) "closed value"))
   (contains? (:block/type entity) "closed value"))

+ 12 - 8
deps/outliner/src/logseq/outliner/core.cljs

@@ -19,7 +19,8 @@
             [logseq.db.frontend.content :as db-content]
             [logseq.db.frontend.content :as db-content]
             [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [logseq.db.sqlite.create-graph :as sqlite-create-graph]
             [frontend.worker.batch-tx :include-macros true :as batch-tx]
             [frontend.worker.batch-tx :include-macros true :as batch-tx]
-            [logseq.db.frontend.order :as db-order]))
+            [logseq.db.frontend.order :as db-order]
+            [logseq.db.frontend.property :as db-porperty]))
 
 
 (def ^:private block-map
 (def ^:private block-map
   (mu/optional-keys
   (mu/optional-keys
@@ -193,7 +194,10 @@
 (defn ^:api db-rebuild-block-refs
 (defn ^:api db-rebuild-block-refs
   "Rebuild block refs for DB graphs"
   "Rebuild block refs for DB graphs"
   [db block]
   [db block]
-  (let [properties (:block/properties (d/entity db (:db/id block)))
+  (let [built-in-props (set (keys db-porperty/built-in-properties))
+        properties (->> (:block/properties (d/entity db (:db/id block)))
+                        (remove (fn [[k _v]] (built-in-props k)))
+                        (into {}))
         property-key-refs (keys properties)
         property-key-refs (keys properties)
         page-or-object? (fn [block] (and (de/entity? block)
         page-or-object? (fn [block] (and (de/entity? block)
                                          (or (ldb/page? block)
                                          (or (ldb/page? block)
@@ -708,8 +712,8 @@
               (ldb/sort-page-random-blocks db blocks))
               (ldb/sort-page-random-blocks db blocks))
             page-blocks)))
             page-blocks)))
 
 
-(defn ^:api delete-block
-  [conn txs-state node {:keys [_date-formatter]}]
+(defn- delete-block
+  [conn txs-state node]
   (otree/-del node txs-state conn)
   (otree/-del node txs-state conn)
   @txs-state)
   @txs-state)
 
 
@@ -725,7 +729,7 @@
 (defn ^:api ^:large-vars/cleanup-todo delete-blocks
 (defn ^:api ^:large-vars/cleanup-todo delete-blocks
   "Delete blocks from the tree.
   "Delete blocks from the tree.
   `blocks` need to be sorted by left&parent(from top to bottom)"
   `blocks` need to be sorted by left&parent(from top to bottom)"
-  [_repo conn date-formatter blocks delete-opts]
+  [conn blocks]
   [:pre [(seq blocks)]]
   [:pre [(seq blocks)]]
   (let [top-level-blocks (filter-top-level-blocks @conn blocks)
   (let [top-level-blocks (filter-top-level-blocks @conn blocks)
         non-consecutive? (and (> (count top-level-blocks) 1) (seq (ldb/get-non-consecutive-blocks @conn top-level-blocks)))
         non-consecutive? (and (> (count top-level-blocks) 1) (seq (ldb/get-non-consecutive-blocks @conn top-level-blocks)))
@@ -737,7 +741,7 @@
     (if (or
     (if (or
          (= 1 (count top-level-blocks))
          (= 1 (count top-level-blocks))
          (= start-block end-block))
          (= start-block end-block))
-      (delete-block conn txs-state start-block (assoc delete-opts :date-formatter date-formatter))
+      (delete-block conn txs-state start-block)
       (doseq [id block-ids]
       (doseq [id block-ids]
         (let [node (d/entity @conn id)]
         (let [node (d/entity @conn id)]
           (otree/-del node txs-state conn))))
           (otree/-del node txs-state conn))))
@@ -959,8 +963,8 @@
   (op-transact! #'insert-blocks repo conn blocks target-block (assoc opts :outliner-op :insert-blocks)))
   (op-transact! #'insert-blocks repo conn blocks target-block (assoc opts :outliner-op :insert-blocks)))
 
 
 (defn delete-blocks!
 (defn delete-blocks!
-  [repo conn date-formatter blocks opts]
-  (op-transact! #'delete-blocks repo conn date-formatter blocks (assoc opts :outliner-op :delete-blocks)))
+  [_repo conn _date-formatter blocks _opts]
+  (op-transact! #'delete-blocks conn blocks))
 
 
 (defn move-blocks!
 (defn move-blocks!
   [repo conn blocks target-block sibling?]
   [repo conn blocks target-block sibling?]

+ 63 - 46
deps/outliner/src/logseq/outliner/pipeline.cljs

@@ -24,61 +24,78 @@
 ;; 2. Its children' block/path-refs might need to be updated too.
 ;; 2. Its children' block/path-refs might need to be updated too.
 (defn- compute-block-path-refs
 (defn- compute-block-path-refs
   [{:keys [db-before db-after]} blocks*]
   [{:keys [db-before db-after]} blocks*]
-  (let [blocks (remove :block/name blocks*)
-        *computed-ids (atom #{})]
-    (mapcat (fn [block]
-              (when (and (not (@*computed-ids (:block/uuid block))) ; not computed yet
-                         (not (:block/name block)))
-                (let [parents (ldb/get-block-parents db-after (:block/uuid block) {})
-                      parents-refs (->> (mapcat :block/path-refs parents)
-                                        (map :db/id))
-                      old-refs (if db-before
-                                 (set (map :db/id (:block/path-refs (d/entity db-before (:db/id block)))))
-                                 #{})
-                      new-refs (set (concat
-                                     (some-> (:db/id (:block/page block)) vector)
-                                     (map :db/id (:block/refs block))
-                                     parents-refs))
-                      refs-changed? (not= old-refs new-refs)
-                      children (ldb/get-block-children-ids db-after (:block/uuid block))
-                            ;; Builds map of children ids to their parent id and :block/refs ids
-                      children-maps (into {}
-                                          (map (fn [id]
-                                                 (let [entity (d/entity db-after [:block/uuid id])]
-                                                   [(:db/id entity)
-                                                    {:parent-id (get-in entity [:block/parent :db/id])
-                                                     :block-ref-ids (map :db/id (:block/refs entity))}]))
-                                               children))
-                      children-refs (map (fn [[id {:keys [block-ref-ids] :as child-map}]]
-                                           {:db/id id
+  (let [*computed-ids (atom #{})
+        blocks (remove (fn [block]
+                         (let [from-property (:logseq.property/created-from-property block)
+                               default? (= :default (get-in from-property [:block/schema :type]))]
+                           (and from-property (not default?))))
+                blocks*)]
+    (->>
+     (mapcat (fn [block]
+               (when-not (@*computed-ids (:block/uuid block))
+                 (let [page? (ldb/page? block)
+                       from-property (:logseq.property/created-from-property block)
+                       parents (when-not page?
+                                 (ldb/get-block-parents db-after (:block/uuid block) {}))
+                       parents-refs (->> (cond->>
+                                          (mapcat :block/path-refs parents)
+                                           from-property
+                                           (remove (fn [parent] (and (ldb/property? parent) (not= (:db/id parent) (:db/id from-property))))))
+                                         (map :db/id))
+                       old-refs (if db-before
+                                  (set (map :db/id (:block/path-refs (d/entity db-before (:db/id block)))))
+                                  #{})
+                       new-refs (set (concat
+                                      (some-> (:db/id (:block/page block)) vector)
+                                      (map :db/id (:block/refs block))
+                                      parents-refs))
+                       refs-changed? (not= old-refs new-refs)
+                       children (when refs-changed?
+                                  (when-not page?
+                                    (ldb/get-block-children-ids db-after (:block/uuid block))))
+                       ;; Builds map of children ids to their parent id and :block/refs ids
+                       children-maps (into {}
+                                           (keep (fn [id]
+                                                   (when-let [entity (d/entity db-after [:block/uuid id])]
+                                                     (let [from-property (:logseq.property/created-from-property entity)
+                                                           default? (= :default (get-in from-property [:block/schema :type]))
+                                                           page? (ldb/page? entity)]
+                                                       (when-not (or page? (and from-property (not default?)))
+                                                         [(:db/id entity)
+                                                          {:parent-id (get-in entity [:block/parent :db/id])
+                                                           :block-ref-ids (map :db/id (:block/refs entity))}]))))
+                                                 children))
+                       children-refs (map (fn [[id {:keys [block-ref-ids] :as child-map}]]
+                                            {:db/id id
                                                   ;; Recalculate :block/path-refs as db contains stale data for this attribute
                                                   ;; Recalculate :block/path-refs as db contains stale data for this attribute
-                                            :block/path-refs
-                                            (set/union
+                                             :block/path-refs
+                                             (set/union
                                                    ;; Refs from top-level parent
                                                    ;; Refs from top-level parent
-                                             new-refs
+                                              new-refs
                                                    ;; Refs from current block
                                                    ;; Refs from current block
-                                             block-ref-ids
+                                              block-ref-ids
                                                    ;; Refs from parents in between top-level
                                                    ;; Refs from parents in between top-level
                                                    ;; parent and current block
                                                    ;; parent and current block
-                                             (loop [parent-refs #{}
-                                                    parent-id (:parent-id child-map)]
-                                               (if-let [parent (children-maps parent-id)]
-                                                 (recur (into parent-refs (:block-ref-ids parent))
-                                                        (:parent-id parent))
+                                              (loop [parent-refs #{}
+                                                     parent-id (:parent-id child-map)]
+                                                (if-let [parent (children-maps parent-id)]
+                                                  (recur (into parent-refs (:block-ref-ids parent))
+                                                         (:parent-id parent))
                                                        ;; exits when top-level parent is reached
                                                        ;; exits when top-level parent is reached
-                                                 parent-refs)))})
-                                         children-maps)]
-                  (swap! *computed-ids set/union (set (cons (:block/uuid block) children)))
-                  (concat
-                   (when (and (seq new-refs) refs-changed?)
-                     [{:db/id (:db/id block)
-                       :block/path-refs new-refs}])
-                   children-refs))))
-            blocks)))
+                                                  parent-refs)))})
+                                          children-maps)]
+                   (swap! *computed-ids set/union (set (cons (:block/uuid block) children)))
+                   (concat
+                    (when (and (seq new-refs) refs-changed? (d/entity db-after (:db/id block)))
+                      [{:db/id (:db/id block)
+                        :block/path-refs new-refs}])
+                    children-refs))))
+             blocks)
+     distinct)))
 
 
 (defn compute-block-path-refs-tx
 (defn compute-block-path-refs-tx
   "Main fn for computing path-refs"
   "Main fn for computing path-refs"
   [tx-report blocks]
   [tx-report blocks]
   (let [refs-tx (compute-block-path-refs tx-report blocks)
   (let [refs-tx (compute-block-path-refs tx-report blocks)
         truncate-refs-tx (map (fn [m] [:db/retract (:db/id m) :block/path-refs]) refs-tx)]
         truncate-refs-tx (map (fn [m] [:db/retract (:db/id m) :block/path-refs]) refs-tx)]
-    (concat truncate-refs-tx refs-tx)))
+    (concat truncate-refs-tx refs-tx)))

+ 22 - 15
deps/outliner/src/logseq/outliner/property.cljs

@@ -2,6 +2,7 @@
   "Property related operations"
   "Property related operations"
   (:require [clojure.string :as string]
   (:require [clojure.string :as string]
             [datascript.core :as d]
             [datascript.core :as d]
+            [datascript.impl.entity :as de]
             [logseq.common.util :as common-util]
             [logseq.common.util :as common-util]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.common.util.page-ref :as page-ref]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
@@ -333,18 +334,20 @@
         (let [txs (mapcat
         (let [txs (mapcat
                    (fn [block]
                    (fn [block]
                      (let [value (get block property-id)
                      (let [value (get block property-id)
-                           block-value? (= :default (get-in property [:block/schema :type] :default))
-                           property-block (when block-value? (d/entity @conn (:db/id value)))
-                           blocks-with-this-value (and block-value?
-                                                       (set (map :e (d/datoms @conn :avet (:db/ident property) (:db/id value)))))
-                           ;; Delete property value block if it's not a closed value and it's no longer used by other blocks
-                           retract-blocks-tx (when (and property-block
-                                                        (some? (get property-block :logseq.property/created-from-property))
-                                                        (not (contains? (:block/type value) "closed value"))
-                                                        (empty? (set/difference blocks-with-this-value block-id-set)))
-                                               (let [txs-state (atom [])]
-                                                 (outliner-core/delete-block conn txs-state property-block {:children? true})
-                                                 @txs-state))]
+                           entities (cond
+                                      (de/entity? value) [value]
+                                      (every? de/entity? value) value
+                                      :else nil)
+                           deleting-entities (filter
+                                              (fn [value]
+                                                (and
+                                                 (:logseq.property/created-from-property value)
+                                                 (not (or (ldb/page? value) (ldb/closed-value? value)))
+                                                 (empty? (set/difference (set (map :e (d/datoms @conn :avet (:db/ident property) (:db/id value)))) block-id-set))))
+                                              entities)
+                           ;; Delete property value block if it's no longer used by other blocks
+                           retract-blocks-tx (when (seq deleting-entities)
+                                               (:tx-data (outliner-core/delete-blocks conn deleting-entities)))]
                        (concat
                        (concat
                         [[:db/retract (:db/id block) (:db/ident property)]]
                         [[:db/retract (:db/id block) (:db/ident property)]]
                         retract-blocks-tx)))
                         retract-blocks-tx)))
@@ -368,9 +371,13 @@
   (when-let [property (d/entity @conn property-id)]
   (when-let [property (d/entity @conn property-id)]
     (let [block (d/entity @conn block-eid)]
     (let [block (d/entity @conn block-eid)]
       (when (and block (not= property-id (:db/ident block)) (db-property/many? property))
       (when (and block (not= property-id (:db/ident block)) (db-property/many? property))
-        (ldb/transact! conn
-                     [[:db/retract (:db/id block) property-id property-value]]
-                     {:outliner-op :save-block})))))
+        (let [current-val (get block property-id)
+              fv (first current-val)]
+          (if (and (= 1 (count current-val)) (or (= property-value fv) (= property-value (:db/id fv))))
+            (remove-block-property! conn (:db/id block) property-id)
+            (ldb/transact! conn
+                           [[:db/retract (:db/id block) property-id property-value]]
+                           {:outliner-op :save-block})))))))
 
 
 (defn collapse-expand-block-property!
 (defn collapse-expand-block-property!
   "Notice this works only if the value itself if a block (property type should be either :default or :template)"
   "Notice this works only if the value itself if a block (property type should be either :default or :template)"

+ 1 - 3
src/main/frontend/components/property/value.cljs

@@ -109,9 +109,7 @@
     (if selected?
     (if selected?
       (<add-property! block (:db/ident property) value {:exit-edit? (not many?)})
       (<add-property! block (:db/ident property) value {:exit-edit? (not many?)})
       (p/do!
       (p/do!
-       (db/transact! (state/get-current-repo)
-                     [[:db/retract (:db/id block) (:db/ident property) value]]
-                     {:outliner-op :save-block})
+       (db-property-handler/delete-property-value! (:db/id block) (:db/ident property) value)
        (when (or (not many?)
        (when (or (not many?)
                  ;; values will be cleared
                  ;; values will be cleared
                  (and many? (<= (count (get block (:db/ident property))) 1)))
                  (and many? (<= (count (get block (:db/ident property))) 1)))

+ 9 - 7
src/main/frontend/db/async.cljs

@@ -79,13 +79,15 @@
 
 
 (defn <get-block-property-values
 (defn <get-block-property-values
   [graph property-id]
   [graph property-id]
-  (<q graph {:transact-db? false}
-      '[:find [?v ...]
-        :in $ ?property-id
-        :where
-        [?b ?property-id ?v]
-        [(not= ?v :logseq.property/empty-placeholder)]]
-      property-id))
+  (let [empty-id (:db/id (db/entity :logseq.property/empty-placeholder))]
+    (<q graph {:transact-db? false}
+        '[:find [?v ...]
+          :in $ ?property-id ?empty-id
+          :where
+          [?b ?property-id ?v]
+          [(not= ?v ?empty-id)]]
+        property-id
+        empty-id)))
 
 
 (comment
 (comment
   (defn <get-block-property-value-entity
   (defn <get-block-property-value-entity

+ 2 - 2
src/main/frontend/worker/pipeline.cljs

@@ -96,8 +96,8 @@
                           ;; block path refs
                           ;; block path refs
                           (when (seq blocks')
                           (when (seq blocks')
                             (let [db-after (or (:db-after refs-tx-report) (:db-after tx-report))
                             (let [db-after (or (:db-after refs-tx-report) (:db-after tx-report))
-                                  blocks' (map (fn [b] (or (d/entity db-after (:db/id b)) b)) blocks')]
-                              (set (compute-block-path-refs-tx tx-report blocks'))))
+                                  blocks' (keep (fn [b] (d/entity db-after (:db/id b))) blocks')]
+                              (compute-block-path-refs-tx tx-report blocks')))
 
 
                           ;; update block/tx-id
                           ;; update block/tx-id
                           (let [updated-blocks (remove (fn [b] (contains? (set deleted-block-uuids) (:block/uuid b)))
                           (let [updated-blocks (remove (fn [b] (contains? (set deleted-block-uuids) (:block/uuid b)))