Browse Source

fix: some built-in tags such as #Journal shouldn't be extended

related to https://github.com/logseq/db-test/issues/555
Tienson Qin 3 months ago
parent
commit
d8b1feb395

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

@@ -185,6 +185,7 @@
 (def get-entity-types entity-util/get-entity-types)
 (def get-entity-types entity-util/get-entity-types)
 (def internal-tags db-class/internal-tags)
 (def internal-tags db-class/internal-tags)
 (def private-tags db-class/private-tags)
 (def private-tags db-class/private-tags)
+(def extends-hidden-tags db-class/extends-hidden-tags)
 (def hidden-tags db-class/hidden-tags)
 (def hidden-tags db-class/hidden-tags)
 
 
 (defn sort-by-order
 (defn sort-by-order

+ 8 - 0
deps/db/src/logseq/db/frontend/class.cljs

@@ -116,6 +116,14 @@
   (set/union (disj internal-tags :logseq.class/Root)
   (set/union (disj internal-tags :logseq.class/Root)
              #{:logseq.class/Journal :logseq.class/Whiteboard}))
              #{:logseq.class/Journal :logseq.class/Whiteboard}))
 
 
+(def extends-hidden-tags
+  "Built-in classes that are hidden when choosing extends"
+  (set/union
+   private-tags
+   #{:logseq.class/Cards :logseq.class/Code-block
+     :logseq.class/Math-block :logseq.class/Pdf-annotation
+     :logseq.class/Query :logseq.class/Quote-block
+     :logseq.class/Template}))
 (def hidden-tags
 (def hidden-tags
   "Built-in classes that are hidden in a few contexts like property values"
   "Built-in classes that are hidden in a few contexts like property values"
   #{:logseq.class/Page :logseq.class/Root :logseq.class/Asset})
   #{:logseq.class/Page :logseq.class/Root :logseq.class/Asset})

+ 3 - 3
deps/outliner/src/logseq/outliner/validate.cljs

@@ -155,9 +155,9 @@
 (defn- disallow-built-in-class-extends-change
 (defn- disallow-built-in-class-extends-change
   [_parent-ent child-ents]
   [_parent-ent child-ents]
   (when (some #(get db-class/built-in-classes (:db/ident %)) child-ents)
   (when (some #(get db-class/built-in-classes (:db/ident %)) child-ents)
-    (throw (ex-info "Can't change the parent of a built-in tag"
+    (throw (ex-info "Can't change the extends of a built-in tag"
                     {:type :notification
                     {:type :notification
-                     :payload {:message "Can't change the parent of a built-in tag"
+                     :payload {:message "Can't change the extends of a built-in tag"
                                :type :error}}))))
                                :type :error}}))))
 
 
 (defn- disallow-extends-cycle
 (defn- disallow-extends-cycle
@@ -177,8 +177,8 @@
   (let [parent-ent (if (integer? parent-ent*)
   (let [parent-ent (if (integer? parent-ent*)
                      (d/entity db parent-ent*)
                      (d/entity db parent-ent*)
                      parent-ent*)]
                      parent-ent*)]
-    (disallow-extends-cycle db parent-ent child-ents)
     (when built-in? (disallow-built-in-class-extends-change parent-ent child-ents))
     (when built-in? (disallow-built-in-class-extends-change parent-ent child-ents))
+    (disallow-extends-cycle db parent-ent child-ents)
     (validate-extends-property-have-correct-type parent-ent child-ents)))
     (validate-extends-property-have-correct-type parent-ent child-ents)))
 
 
 (defn- disallow-node-cant-tag-with-built-in-non-tags
 (defn- disallow-node-cant-tag-with-built-in-non-tags

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

@@ -669,7 +669,8 @@
   [property
   [property
    {:keys [block multiple-choices? dropdown? input-opts on-input add-new-choice! target] :as opts}
    {:keys [block multiple-choices? dropdown? input-opts on-input add-new-choice! target] :as opts}
    result]
    result]
-  (let [repo (state/get-current-repo)
+  (let [[*input set-input!] (hooks/use-state nil)
+        repo (state/get-current-repo)
         classes (:logseq.property/classes property)
         classes (:logseq.property/classes property)
         tags? (= :block/tags (:db/ident property))
         tags? (= :block/tags (:db/ident property))
         alias? (= :block/alias (:db/ident property))
         alias? (= :block/alias (:db/ident property))
@@ -693,7 +694,7 @@
                                       ;; hide parent extends for existing values
                                       ;; hide parent extends for existing values
                                       (set/union (set (map :block/uuid extends))))
                                       (set/union (set (map :block/uuid extends))))
                       options (if (ldb/class? block)
                       options (if (ldb/class? block)
-                                (model/get-all-classes repo)
+                                (model/get-all-classes repo {:except-extends-hidden-tags? true})
                                 result)
                                 result)
 
 
                       excluded-options (->> options
                       excluded-options (->> options
@@ -785,6 +786,7 @@
                (merge
                (merge
                 opts
                 opts
                 {:multiple-choices? multiple-choices?
                 {:multiple-choices? multiple-choices?
+                 :tap-*input-val set-input!
                  :items options
                  :items options
                  :selected-choices selected-choices
                  :selected-choices selected-choices
                  :dropdown? dropdown?
                  :dropdown? dropdown?
@@ -796,7 +798,12 @@
                                               :else
                                               :else
                                               (str "Set " (:block/title property)))
                                               (str "Set " (:block/title property)))
                  :show-new-when-not-exact-match? (not
                  :show-new-when-not-exact-match? (not
-                                                  (or (and extends-property? (contains? (set children-pages) (:db/id block)))
+                                                  (or (and extends-property?
+                                                           (or (contains? (set children-pages) (:db/id block))
+                                                               (when-let [input (when *input @*input)]
+                                                                 (when-not (string/blank? input)
+                                                                   (some (fn [ident]
+                                                                           (= input (:block/title (db/entity ident)))) ldb/extends-hidden-tags)))))
                                                       ;; Don't allow creating private tags
                                                       ;; Don't allow creating private tags
                                                       (and (= :block/tags (:db/ident property))
                                                       (and (= :block/tags (:db/ident property))
                                                            (seq (set/intersection (set (map :db/ident classes'))
                                                            (seq (set/intersection (set (map :db/ident classes'))

+ 8 - 3
src/main/frontend/db/model.cljs

@@ -464,16 +464,21 @@ independent of format as format specific heading characters are stripped"
                     :nonce (:nonce shape)}))))))
                     :nonce (:nonce shape)}))))))
 
 
 (defn get-all-classes
 (defn get-all-classes
-  [repo & {:keys [except-root-class? except-private-tags?]
+  [repo & {:keys [except-root-class? except-private-tags?
+                  except-extends-hidden-tags?]
            :or {except-root-class? false
            :or {except-root-class? false
-                except-private-tags? true}}]
+                except-private-tags? true
+                except-extends-hidden-tags? false}}]
   (let [db (conn/get-db repo)
   (let [db (conn/get-db repo)
         classes (->> (d/datoms db :avet :block/tags :logseq.class/Tag)
         classes (->> (d/datoms db :avet :block/tags :logseq.class/Tag)
                      (map (fn [d]
                      (map (fn [d]
                             (db-utils/entity db (:e d))))
                             (db-utils/entity db (:e d))))
                      (remove (fn [d]
                      (remove (fn [d]
                                (and except-private-tags?
                                (and except-private-tags?
-                                    (contains? ldb/private-tags (:db/ident d))))))]
+                                    (contains? ldb/private-tags (:db/ident d)))))
+                     (remove (fn [d]
+                               (and except-extends-hidden-tags?
+                                    (contains? ldb/extends-hidden-tags (:db/ident d))))))]
     (if except-root-class?
     (if except-root-class?
       (keep (fn [e] (when-not (= :logseq.class/Root (:db/ident e)) e)) classes)
       (keep (fn [e] (when-not (= :logseq.class/Root (:db/ident e)) e)) classes)
       classes)))
       classes)))

+ 41 - 22
src/main/frontend/worker/pipeline.cljs

@@ -334,31 +334,50 @@
                                              (:block/title block))
                                              (:block/title block))
                                   (ldb/built-in? block))))
                                   (ldb/built-in? block))))
           tx-data' (mapcat
           tx-data' (mapcat
-                    (fn [[e a v _t added]]
-                      (when added
-                        (cond
+                    (fn [datom]
+                      (let [[e a v _t added] datom]
+                        (when added
+                          (cond
                           ;; using built-in pages as tags
                           ;; using built-in pages as tags
-                          (and (= a :block/tags) (built-in-page? v))
-                          [[:db/retract v :db/ident]
-                           [:db/retract v :logseq.property.class/extends]
-                           [:db/retract v :block/tags :logseq.class/Tag]
-                           [:db/add v :block/tags :logseq.class/Page]
-                           [:db/retract e a v]]
+                            (and (= a :block/tags) (built-in-page? v))
+                            [[:db/retract v :db/ident]
+                             [:db/retract v :logseq.property.class/extends]
+                             [:db/retract v :block/tags :logseq.class/Tag]
+                             [:db/add v :block/tags :logseq.class/Page]
+                             [:db/retract e a v]]
 
 
-                          ;; built-in block protected attributes/properties updated
-                          (and (contains? #{:db/ident :block/title :block/name :block/uuid
-                                            :logseq.property/type :db/cardinality
-                                            :logseq.property/built-in? :logseq.property.class/extends} a)
-                               (some? (d/entity db-before e))
-                               (let [block (d/entity db-after e)]
-                                 (and (ldb/built-in? block)
-                                      (not= (get block a) (get (d/entity db-before e) a)))))
-                          (if-some [prev-v (get (d/entity db-before e) a)]
-                            [[:db/add e a prev-v]]
-                            [[:db/retract e a v]])
+                            ;; built-in block protected properties updated
+                            (and (contains? #{:db/ident :block/title :block/name :block/uuid
+                                              :logseq.property/type :db/cardinality
+                                              :logseq.property/built-in? :logseq.property.class/extends} a)
+                                 (some? (d/entity db-before e))
+                                 (let [block (d/entity db-after e)]
+                                   (and (ldb/built-in? block)
+                                        (not= (get block a) (get (d/entity db-before e) a)))))
+                            (if-some [prev-v (get (d/entity db-before e) a)]
+                              (if (= a :logseq.property.class/extends)
+                                [[:db/retract e a]
+                                 {:db/id e
+                                  a (map :db/id prev-v)}]
+                                [[:db/add e a prev-v]])
+                              [[:db/retract e a v]])
 
 
-                          :else
-                          nil)))
+                            ;; user class extends unexpected built-in classes
+                            (and (= a :logseq.property.class/extends)
+                                 (let [block (d/entity db-after v)]
+                                   (and (ldb/built-in? block)
+                                        (not (contains? #{:logseq.class/Root :logseq.class/Page :logseq.class/Property
+                                                          :logseq.class/Task :logseq.class/Card}
+                                                        (:db/ident block))))))
+                            (let [prev-v (get (d/entity db-before e) a)]
+                              [[:db/retract e a v]
+                               (if (seq prev-v)
+                                 {:db/id e
+                                  a (map :db/id prev-v)}
+                                 [:db/add e a :logseq.class/Root])])
+
+                            :else
+                            nil))))
                     tx-data)]
                     tx-data)]
       (when (seq tx-data')
       (when (seq tx-data')
         (prn :debug ::revert-built-in-block-updates :tx-data (distinct tx-data')))
         (prn :debug ::revert-built-in-block-updates :tx-data (distinct tx-data')))

+ 16 - 2
src/test/frontend/worker/pipeline_test.cljs

@@ -45,7 +45,8 @@
   (let [graph test-helper/test-db-name-db-version
   (let [graph test-helper/test-db-name-db-version
         conn (db-test/create-conn-with-blocks
         conn (db-test/create-conn-with-blocks
               [{:page {:block/title "page1"}
               [{:page {:block/title "page1"}
-                :blocks [{:block/title "b1"}]}])
+                :blocks [{:block/title "b1"}
+                         {:block/title "b2" :build/tags [:tag1]}]}])
         library (ldb/get-built-in-page @conn "Library")]
         library (ldb/get-built-in-page @conn "Library")]
 
 
     (ldb/register-transact-pipeline-fn!
     (ldb/register-transact-pipeline-fn!
@@ -76,6 +77,19 @@
                               :block/title "task"}])
                               :block/title "task"}])
         (let [task (d/entity @conn (:db/id task))]
         (let [task (d/entity @conn (:db/id task))]
           (is (= :logseq.class/Task (:db/ident task)))
           (is (= :logseq.class/Task (:db/ident task)))
-          (is (= "Task" (:block/title task))))))
+          (is (= "Task" (:block/title task))))
+
+        (ldb/transact! conn [{:db/id (:db/id task)
+                              :logseq.property.class/extends :logseq.class/Journal}])
+        (let [task (d/entity @conn (:db/id task))]
+          (is (= [:logseq.class/Root] (map :db/ident (:logseq.property.class/extends task)))))))
+
+    (testing "User class extends unexpected built-in classes"
+      (let [t1 (ldb/get-page @conn "tag1")]
+        (ldb/transact! conn [{:db/id (:db/id t1)
+                              :logseq.property.class/extends :logseq.class/Journal}])
+        (let [t1 (d/entity @conn (:db/id t1))]
+          (is (= [:logseq.class/Root] (map :db/ident (:logseq.property.class/extends t1)))))))
+
     ;; return global fn back to previous behavior
     ;; return global fn back to previous behavior
     (ldb/register-transact-pipeline-fn! identity)))
     (ldb/register-transact-pipeline-fn! identity)))