Browse Source

enhance: Allow built-in properties to use most properties

without hardcoded configuration. For example
:logseq.property/description can be added to any built-in property that is below
it in built-in-properties. Added descriptions to scheduled and deadline
since it's not obvious from their ux how they differ
Gabriel Horner 10 months ago
parent
commit
a2609f4d9d

+ 10 - 13
deps/db/src/logseq/db/frontend/property.cljs

@@ -159,6 +159,10 @@
                                                   :hide? true
                                                   :view-context :block}
                                          :queryable? true}
+     :logseq.property/description {:title "Description"
+                                   :schema
+                                   {:type :default
+                                    :public? true}}
      :logseq.property.code/lang {:title "Code Mode"
                                  :schema {:type :string
                                           :public? false
@@ -348,27 +352,24 @@
       :schema {:type :datetime
                :public? true
                :position :block-below}
-      :properties {:logseq.property/hide-empty-value true}
+      :properties {:logseq.property/hide-empty-value true
+                   :logseq.property/description "Use it to finish something at a specific date(time)."}
       :queryable? true}
      :logseq.task/scheduled
      {:title "Scheduled"
       :schema {:type :datetime
                :public? true
                :position :block-below}
-      :properties {:logseq.property/hide-empty-value true}
+      :properties {:logseq.property/hide-empty-value true
+                   :logseq.property/description "Use it to plan something to start at a specific date(time)."}
       :queryable? true}
      :logseq.task/recur-frequency
      (let [schema {:type :number
                    :public? false}]
        {:title "Recur frequency"
         :schema schema
-        :properties (let [block {:db/ident :logseq.task/recur-frequency
-                                 :block/schema schema}
-                          property {:db/ident :logseq.property/default-value
-                                    :block/schema {:type :entity}}
-                          default-value (assoc (build-property-value-block block property 1) :db/id -1)]
-                      {:logseq.property/hide-empty-value true
-                       :logseq.property/default-value default-value})
+        :properties {:logseq.property/hide-empty-value true
+                     :logseq.property/default-value 1}
         :queryable? true})
      :logseq.task/recur-unit
      {:title "Recur unit"
@@ -417,10 +418,6 @@
                                                 :hide? true
                                                 :view-context :page
                                                 :public? true}}
-     :logseq.property/description {:title "Description"
-                                   :schema
-                                   {:type :default
-                                    :public? true}}
 
      :logseq.property.view/type
      {:title "View Type"

+ 2 - 1
deps/db/src/logseq/db/sqlite/build.cljs

@@ -78,7 +78,8 @@
 
 (defn- ->property-value-tx-m
   "Given a new block and its properties, creates a map of properties which have values of property value tx.
-   This map is used for both creating the new property values and then adding them to a block"
+   This map is used for both creating the new property values and then adding them to a block.
+   This fn is similar to sqlite-create-graph/->property-value-tx-m and we may want to reuse it from here later."
   [new-block properties properties-config all-idents]
   (->> properties
        (keep (fn [[k v]]

+ 50 - 12
deps/db/src/logseq/db/sqlite/create_graph.cljs

@@ -9,13 +9,34 @@
             [logseq.db.frontend.entity-util :as entity-util]
             [logseq.db.frontend.order :as db-order]
             [logseq.db.frontend.property :as db-property]
+            [logseq.db.frontend.property.type :as db-property-type]
             [logseq.db.frontend.property.build :as db-property-build]
             [logseq.db.frontend.schema :as db-schema]
-            [logseq.db.sqlite.util :as sqlite-util]))
+            [logseq.db.sqlite.util :as sqlite-util]
+            [logseq.db.frontend.malli-schema :as db-malli-schema]))
 
 (defn- mark-block-as-built-in [block]
   (assoc block :logseq.property/built-in? true))
 
+(defn- ->property-value-tx-m
+  "Given a new block and its properties, creates a map of properties which have values of property value tx.
+   This map is used for both creating the new property values and then adding them to a block"
+  [new-block properties]
+  (->> properties
+       (keep (fn [[k v]]
+               (when-let [built-in-type (get-in db-property/built-in-properties [k :schema :type])]
+                 (if (and (db-property-type/value-ref-property-types built-in-type)
+                          ;; closed values are referenced by their :db/ident so no need to create values
+                          (not (get-in db-property/built-in-properties [k :closed-values])))
+                   (let [property-map {:db/ident k
+                                       :block/schema {:type built-in-type}}]
+                     [property-map v])
+                   (when-let [built-in-type' (get (:build/properties-ref-types new-block) built-in-type)]
+                     (let [property-map {:db/ident k
+                                         :block/schema {:type built-in-type'}}]
+                       [property-map v]))))))
+       (db-property-build/build-property-values-tx-m new-block)))
+
 (defn build-initial-properties*
   [built-in-properties]
   (mapcat
@@ -26,20 +47,37 @@
                                   db-ident
                                   prop-name
                                   {:db/ident db-ident :block/schema schema :closed-values closed-values}
-                                  {:properties properties})
+                                  {})
                                  [(sqlite-util/build-new-property
                                    db-ident
                                    schema
-                                   {:title prop-name
-                                    :properties properties})])]
-       (->> (concat
-             [(dissoc property :logseq.property/default-value)]
-             others
-             (when-let [default-value (:logseq.property/default-value property)]
-               (when-let [id (:block/uuid property)]
-                 [{:block/uuid id
-                   :logseq.property/default-value default-value}])))
-            (remove nil?))))
+                                   {:title prop-name})])
+           pvalue-tx-m (->property-value-tx-m
+                        (merge property
+                               ;; This config is for :logseq.property/default-value and may need to
+                               ;; move to built-in-properties
+                               {:build/properties-ref-types {:entity :number}})
+                        (->> properties
+                             ;; No need to create property value if it's an internal ident
+                             (remove (fn [[_k v]]
+                                       (and (keyword? v) (db-malli-schema/internal-ident? v))))
+                             (into {})))
+           ;; _ (when (seq pvalue-tx-m) (prn :pvalue-tx-m db-ident pvalue-tx-m))
+
+           ;; The order of tx matters. property and others must come first as
+           ;; they may contain idents and uuids that are referenced by properties
+           tx
+           (cond-> [property]
+             (seq others)
+             (into others)
+             (seq pvalue-tx-m)
+             (into (mapcat #(if (set? %) % [%]) (vals pvalue-tx-m)))
+             (seq properties)
+             (conj
+              (merge {:block/uuid (:block/uuid property)}
+                     properties
+                     (db-property-build/build-properties-with-ref-values pvalue-tx-m))))]
+       tx))
    (dissoc built-in-properties :logseq.property/built-in?)))
 
 (defn- build-initial-properties

+ 29 - 1
deps/db/test/logseq/db/sqlite/create_graph_test.cljs

@@ -77,7 +77,7 @@
 (deftest new-graph-initializes-default-classes-correctly
   (let [conn (db-test/create-conn)]
     (is (= (count db-class/built-in-classes) (count (d/datoms @conn :avet :block/tags :logseq.class/Tag)))
-        "All built-in classes have a :logseq.class/Tag")
+        "Number of built-in classes equals number of ents with :logseq.class/Tag")
 
     (is (= (count (dissoc db-class/built-in-classes :logseq.class/Root))
            (count (->> (d/datoms @conn :avet :block/tags :logseq.class/Tag)
@@ -86,6 +86,34 @@
                        set)))
         "Reverse lookup of :logseq.property/parent correctly fetches number of child classes")))
 
+(deftest new-graph-initializes-default-properties-correctly
+  (let [conn (db-test/create-conn)]
+    (is (= (count db-property/built-in-properties) (count (d/datoms @conn :avet :block/tags :logseq.class/Property)))
+        "Number of built-in properties equals number of ents with :logseq.class/Property")
+
+    ;; testing :properties config
+    (testing "A built-in property that has"
+      (is (= :logseq.task/status.todo
+             (-> (d/entity @conn :logseq.task/status)
+                 :logseq.property/default-value
+                 :db/ident))
+          "A property with a :db/ident property value is created correctly")
+      (is (-> (d/entity @conn :logseq.task/deadline)
+              :logseq.property/description
+              db-property/property-value-content
+              str
+              (string/includes? "finish something"))
+          "A :default property is created correctly")
+      (is (= true
+             (-> (d/entity @conn :logseq.task/status)
+                 :logseq.property/enable-history?))
+          "A :checkbox property is created correctly")
+      (is (= 1
+             (-> (d/entity @conn :logseq.task/recur-frequency)
+                 :logseq.property/default-value
+                 db-property/property-value-content))
+          "A numeric property is created correctly"))))
+
 (deftest new-graph-is-valid
   (let [conn (db-test/create-conn)
         validation (db-validate/validate-db! @conn)]