From e1def881489c9aa4e646e7a4d8066f1fe14fd4bd Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Tue, 14 Apr 2026 04:11:22 +0800 Subject: [PATCH] fix(property): hide recycled node/page values in property area --- src/main/frontend/components/property.cljs | 86 +++++++++++++++++-- .../components/property/property_test.cljs | 35 ++++++++ 2 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 src/test/frontend/components/property/property_test.cljs diff --git a/src/main/frontend/components/property.cljs b/src/main/frontend/components/property.cljs index 8e5cf30756..76cd38f719 100644 --- a/src/main/frontend/components/property.cljs +++ b/src/main/frontend/components/property.cljs @@ -547,6 +547,7 @@ (let [property-desc (when-not (= (:db/ident property) :logseq.property/description) (:logseq.property/description property))] + (let [block' (assoc block (:db/ident property) v)] [:div.ls-block.property-value-container.flex.flex-row.gap-1 {:class (if (contains? #{:checkbox :date :datetime} type) "items-center" @@ -560,7 +561,67 @@ [:div.property-value.flex.flex-1 (if (:class-schema? opts) (pv/property-value property (db/entity :logseq.property/description) opts) - (pv/property-value block property opts))]]])])))) + (pv/property-value block' property opts))]]]))])))) + +(defn- entity-ref-value? + [value] + (and (map? value) + (or (contains? value :db/id) + (contains? value :block/uuid)))) + +(defn- contains-recycled-entity-value? + [value] + (cond + (entity-ref-value? value) + (ldb/recycled? value) + + (and (coll? value) (not (map? value))) + (some (fn [item] + (and (entity-ref-value? item) + (ldb/recycled? item))) + value) + + :else + false)) + +(defn- filter-recycled-entity-values + [value] + (let [active-entity-value? (fn [item] + (or (not (entity-ref-value? item)) + (not (ldb/recycled? item))))] + (cond + (and (entity-ref-value? value) (ldb/recycled? value)) + nil + + (set? value) + (let [value' (set (filter active-entity-value? value))] + (when (seq value') value')) + + (vector? value) + (let [value' (vec (filter active-entity-value? value))] + (when (seq value') value')) + + (and (coll? value) (not (map? value))) + (let [value' (vec (filter active-entity-value? value))] + (when (seq value') value')) + + :else + value))) + +(defn- sanitize-property-values-for-display + [properties] + (reduce-kv + (fn [{:keys [properties recycled-only-property-ids] :as result} property-id property-value] + (let [property-value' (filter-recycled-entity-values property-value)] + (if (and (nil? property-value') + (contains-recycled-entity-value? property-value)) + (assoc result + :properties (assoc properties property-id nil) + :recycled-only-property-ids (conj recycled-only-property-ids property-id)) + (assoc result :properties (assoc properties property-id property-value'))))) + {:properties {} + :recycled-only-property-ids #{}} + properties)) (rum/defc ordered-properties [block properties* sorted-property-entities opts] @@ -656,11 +717,13 @@ (and show? (or (= mode :global) (and (set? ids) (contains? ids (:block/uuid block)))))) - properties (cond-> (:block/properties block) - (and (ldb/class? block) - (not (ldb/built-in? block))) - (assoc :logseq.property.class/enable-bidirectional? - (:logseq.property.class/enable-bidirectional? block))) + properties* (cond-> (:block/properties block) + (and (ldb/class? block) + (not (ldb/built-in? block))) + (assoc :logseq.property.class/enable-bidirectional? + (:logseq.property.class/enable-bidirectional? block))) + {:keys [properties recycled-only-property-ids]} + (sanitize-property-values-for-display properties*) remove-built-in-or-other-position-properties (fn [properties show-in-hidden-properties?] (remove (fn [property] @@ -686,6 +749,7 @@ {:keys [all-classes classes-properties]} (outliner-property/get-block-classes-properties (db/get-db) (:db/id block)) classes-properties-set (set (map :db/ident classes-properties)) block-own-properties (->> properties + (remove (fn [[id _]] (contains? recycled-only-property-ids id))) (remove (fn [[id _]] (classes-properties-set id)))) state-hide-empty-properties? (:ui/hide-empty-properties? (state/get-config)) ;; This section produces own-properties and full-hidden-properties @@ -696,7 +760,7 @@ show-empty-and-hidden-properties? false state-hide-empty-properties? - (nil? (get block property-id)) + (nil? (get properties property-id)) (and (:logseq.property/hide-empty-value property) (nil? (get properties property-id))) true @@ -732,11 +796,15 @@ (into result cur-properties) result))) result)) + class-property-pairs (->> class-properties + (map (fn [p] [p (get properties p)])) + (remove (fn [[property-id _]] + (contains? recycled-only-property-ids property-id)))) full-properties (-> (concat block-own-properties' - (remove property-hide-f (map (fn [p] [p (get block p)]) class-properties))) + (remove property-hide-f class-property-pairs)) (remove-built-in-or-other-position-properties false)) hidden-properties (-> (concat block-hidden-properties - (filter property-hide-f (map (fn [p] [p (get block p)]) class-properties))) + (filter property-hide-f class-property-pairs)) (remove-built-in-or-other-position-properties true)) root-block? (or (= (str (:block/uuid block)) (state/get-current-page)) diff --git a/src/test/frontend/components/property/property_test.cljs b/src/test/frontend/components/property/property_test.cljs new file mode 100644 index 0000000000..ddc1bee1b5 --- /dev/null +++ b/src/test/frontend/components/property/property_test.cljs @@ -0,0 +1,35 @@ +(ns frontend.components.property.property-test + (:require [cljs.test :refer [deftest is]] + [frontend.components.property :as property])) + +(deftest sanitize-property-values-for-display-filters-recycled-entity-values-test + (let [active-value {:db/id 101 + :block/title "Active"} + recycled-value {:db/id 102 + :block/title "Recycled" + :logseq.property/deleted-at 1} + {:keys [properties recycled-only-property-ids]} + (#'property/sanitize-property-values-for-display + {:user.property/node #{active-value recycled-value} + :user.property/single recycled-value + :user.property/scalar "ok"})] + (is (= #{active-value} + (:user.property/node properties))) + (is (nil? (:user.property/single properties))) + (is (= "ok" (:user.property/scalar properties))) + (is (= #{:user.property/single} + recycled-only-property-ids)))) + +(deftest sanitize-property-values-for-display-marks-all-recycled-coll-as-hidden-test + (let [recycled-a {:db/id 201 + :block/title "Recycled A" + :logseq.property/deleted-at 1} + recycled-b {:db/id 202 + :block/title "Recycled B" + :logseq.property/deleted-at 2} + {:keys [properties recycled-only-property-ids]} + (#'property/sanitize-property-values-for-display + {:user.property/nodes [recycled-a recycled-b]})] + (is (nil? (:user.property/nodes properties))) + (is (= #{:user.property/nodes} + recycled-only-property-ids))))