浏览代码

Merge branch 'feat/db' into refactor/single-block-type

Tienson Qin 1 年之前
父节点
当前提交
4cb9cb63a6
共有 56 个文件被更改,包括 497 次插入514 次删除
  1. 3 7
      deps/db/src/logseq/db/frontend/malli_schema.cljs
  2. 9 5
      deps/db/src/logseq/db/frontend/property.cljs
  3. 3 6
      deps/db/src/logseq/db/frontend/property/build.cljs
  4. 2 4
      deps/db/src/logseq/db/frontend/rules.cljc
  5. 1 1
      deps/db/src/logseq/db/frontend/schema.cljs
  6. 3 3
      deps/db/src/logseq/db/sqlite/build.cljs
  7. 26 28
      deps/db/src/logseq/db/sqlite/common_db.cljs
  8. 1 1
      deps/db/src/logseq/db/sqlite/util.cljs
  9. 1 1
      deps/db/test/logseq/db/frontend/rules_test.cljs
  10. 1 1
      deps/graph-parser/package.json
  11. 3 1
      deps/graph-parser/src/logseq/graph_parser/mldoc.cljc
  12. 6 6
      deps/graph-parser/test/logseq/graph_parser/block_test.cljs
  13. 1 1
      deps/graph-parser/test/logseq/graph_parser/cli_test.cljs
  14. 4 4
      deps/graph-parser/yarn.lock
  15. 1 1
      deps/outliner/package.json
  16. 31 26
      deps/outliner/src/logseq/outliner/property.cljs
  17. 1 1
      deps/outliner/test/logseq/outliner/property_test.cljs
  18. 4 4
      deps/outliner/yarn.lock
  19. 1 1
      deps/publishing/package.json
  20. 4 4
      deps/publishing/yarn.lock
  21. 1 1
      package.json
  22. 1 1
      scripts/package.json
  23. 25 17
      scripts/src/logseq/tasks/db_graph/create_graph_with_schema_org.cljs
  24. 3 1
      scripts/src/logseq/tasks/dev/db_and_file_graphs.clj
  25. 4 4
      scripts/yarn.lock
  26. 1 1
      src/main/frontend/common.css
  27. 1 1
      src/main/frontend/components/block.cljs
  28. 18 0
      src/main/frontend/components/block.css
  29. 4 4
      src/main/frontend/components/container.cljs
  30. 80 250
      src/main/frontend/components/editor.cljs
  31. 3 3
      src/main/frontend/components/editor.css
  32. 1 1
      src/main/frontend/components/file_based/block.cljs
  33. 91 12
      src/main/frontend/components/objects.cljs
  34. 7 3
      src/main/frontend/components/page.cljs
  35. 16 4
      src/main/frontend/components/property.cljs
  36. 1 1
      src/main/frontend/components/property/closed_value.cljs
  37. 16 8
      src/main/frontend/components/property/value.cljs
  38. 4 17
      src/main/frontend/components/repo.css
  39. 9 9
      src/main/frontend/components/views.cljs
  40. 9 0
      src/main/frontend/db/async.cljs
  41. 9 0
      src/main/frontend/db/model.cljs
  42. 1 1
      src/main/frontend/db/query_dsl.cljs
  43. 1 1
      src/main/frontend/handler/editor.cljs
  44. 0 14
      src/main/frontend/handler/events.cljs
  45. 4 2
      src/main/frontend/handler/page.cljs
  46. 1 1
      src/main/frontend/handler/paste.cljs
  47. 9 1
      src/main/frontend/handler/plugin.cljs
  48. 0 5
      src/main/frontend/search.cljs
  49. 22 1
      src/main/frontend/worker/db/migrate.cljs
  50. 7 6
      src/main/frontend/worker/rtc/client.cljs
  51. 1 1
      src/main/frontend/worker/rtc/client_op.cljs
  52. 2 2
      src/test/frontend/db/db_based_model_test.cljs
  53. 12 12
      src/test/frontend/db/query_dsl_test.cljs
  54. 1 1
      src/test/frontend/handler/paste_test.cljs
  55. 22 18
      src/test/logseq/api_test.cljs
  56. 4 4
      yarn.lock

+ 3 - 7
deps/db/src/logseq/db/frontend/malli_schema.cljs

@@ -79,7 +79,7 @@
   validate-fn varies by property type"
   validate-fn varies by property type"
   [db validate-fn [{:block/keys [schema] :as property} property-val] & {:keys [new-closed-value?]}]
   [db validate-fn [{:block/keys [schema] :as property} property-val] & {:keys [new-closed-value?]}]
   ;; For debugging
   ;; For debugging
-  ;; (when (not= "logseq.property" (namespace (:db/ident property))) (prn :validate-val (dissoc property :property/closed-values) property-val))
+  ;; (when (not (string/starts-with? (namespace (:db/ident property)) "logseq.")) (prn :validate-val (dissoc property :property/closed-values) property-val))
   (let [validate-fn' (if (db-property-type/property-types-with-db (:type schema))
   (let [validate-fn' (if (db-property-type/property-types-with-db (:type schema))
                        (fn [value]
                        (fn [value]
                          (validate-fn db value {:new-closed-value? new-closed-value?}))
                          (validate-fn db value {:new-closed-value? new-closed-value?}))
@@ -264,8 +264,7 @@
 
 
 (def property-common-schema-attrs
 (def property-common-schema-attrs
   "Property :schema attributes common to all properties"
   "Property :schema attributes common to all properties"
-  [[:hide? {:optional true} :boolean]
-   [:description {:optional true} :string]])
+  [[:hide? {:optional true} :boolean]])
 
 
 (def internal-property
 (def internal-property
   (vec
   (vec
@@ -371,10 +370,7 @@
      [:db/ident {:optional true} logseq-property-ident]
      [:db/ident {:optional true} logseq-property-ident]
      [:block/title {:optional true} :string]
      [:block/title {:optional true} :string]
      [:property.value/content {:optional true} [:or :string :double]]
      [:property.value/content {:optional true} [:or :string :double]]
-     [:block/closed-value-property {:optional true} [:set :int]]
-     [:block/schema {:optional true}
-      [:map
-       [:description {:optional true} :string]]]]
+     [:block/closed-value-property {:optional true} [:set :int]] ]
     (remove #(#{:block/title} (first %)) block-attrs)
     (remove #(#{:block/title} (first %)) block-attrs)
     page-or-block-attrs)))
     page-or-block-attrs)))
 
 

+ 9 - 5
deps/db/src/logseq/db/frontend/property.cljs

@@ -150,23 +150,27 @@
                                               :hide? true
                                               :hide? true
                                               :view-context :page
                                               :view-context :page
                                               :public? true}}
                                               :public? true}}
-   :logseq.property/table-sorting {:schema
+   :logseq.property/description {:schema
+                                 {:type :default
+                                  :public? true}}
+
+   :logseq.property.table/sorting {:schema
                                    {:type :coll
                                    {:type :coll
                                     :hide? true
                                     :hide? true
                                     :public? false}}
                                     :public? false}}
 
 
-   :logseq.property/table-filters {:schema
+   :logseq.property.table/filters {:schema
                                    {:type :coll
                                    {:type :coll
                                     :hide? true
                                     :hide? true
                                     :public? false}}
                                     :public? false}}
 
 
-   :logseq.property/table-hidden-columns {:schema
+   :logseq.property.table/hidden-columns {:schema
                                           {:type :keyword
                                           {:type :keyword
                                            :cardinality :many
                                            :cardinality :many
                                            :hide? true
                                            :hide? true
                                            :public? false}}
                                            :public? false}}
 
 
-   :logseq.property/table-ordered-columns {:schema
+   :logseq.property.table/ordered-columns {:schema
                                            {:type :coll
                                            {:type :coll
                                             :hide? true
                                             :hide? true
                                             :public? false}}
                                             :public? false}}
@@ -201,7 +205,7 @@
 
 
 (def logseq-property-namespaces
 (def logseq-property-namespaces
   #{"logseq.property" "logseq.property.tldraw" "logseq.property.pdf" "logseq.task"
   #{"logseq.property" "logseq.property.tldraw" "logseq.property.pdf" "logseq.task"
-    "logseq.property.linked-references" "logseq.property.asset"})
+    "logseq.property.linked-references" "logseq.property.asset" "logseq.property.table"})
 
 
 (defn logseq-property?
 (defn logseq-property?
   "Determines if keyword is a logseq property"
   "Determines if keyword is a logseq property"

+ 3 - 6
deps/db/src/logseq/db/frontend/property/build.cljs

@@ -21,7 +21,7 @@
 
 
 (defn build-closed-value-block
 (defn build-closed-value-block
   "Builds a closed value block to be transacted"
   "Builds a closed value block to be transacted"
-  [block-uuid block-value property {:keys [db-ident icon description]}]
+  [block-uuid block-value property {:keys [db-ident icon]}]
   (assert block-uuid (uuid? block-uuid))
   (assert block-uuid (uuid? block-uuid))
   (cond->
   (cond->
    (closed-value-new-block block-uuid block-value property)
    (closed-value-new-block block-uuid block-value property)
@@ -31,9 +31,6 @@
     icon
     icon
     (assoc :logseq.property/icon icon)
     (assoc :logseq.property/icon icon)
 
 
-    description
-    (update :block/schema assoc :description description)
-
     true
     true
     sqlite-util/block-with-timestamps))
     sqlite-util/block-with-timestamps))
 
 
@@ -46,13 +43,13 @@
                                                                                      :ref-type? true})
                                                                                      :ref-type? true})
                            property-attributes)]
                            property-attributes)]
     (into [property-tx]
     (into [property-tx]
-          (map (fn [{:keys [db-ident value icon description uuid]}]
+          (map (fn [{:keys [db-ident value icon uuid]}]
                  (cond->
                  (cond->
                   (build-closed-value-block
                   (build-closed-value-block
                    uuid
                    uuid
                    value
                    value
                    property
                    property
-                   {:db-ident db-ident :icon icon :description description})
+                   {:db-ident db-ident :icon icon})
                    true
                    true
                    (assoc :block/order (db-order/gen-key))))
                    (assoc :block/order (db-order/gen-key))))
                (:closed-values property)))))
                (:closed-values property)))))

+ 2 - 4
deps/db/src/logseq/db/frontend/rules.cljc

@@ -172,8 +172,7 @@
       [?p :block/name]
       [?p :block/name]
       [?p ?prop ?pv]
       [?p ?prop ?pv]
       (or [?pv :block/title ?val]
       (or [?pv :block/title ?val]
-          [?pv :property.value/content ?val]
-          [?pv :block/title ?val])
+          [?pv :property.value/content ?val])
       [?prop-e :db/ident ?prop]
       [?prop-e :db/ident ?prop]
       [?prop-e :block/type "property"]]
       [?prop-e :block/type "property"]]
 
 
@@ -188,8 +187,7 @@
     '[(property ?b ?prop ?val)
     '[(property ?b ?prop ?val)
       [?b ?prop ?pv]
       [?b ?prop ?pv]
       (or [?pv :block/title ?val]
       (or [?pv :block/title ?val]
-          [?pv :property.value/content ?val]
-          [?pv :block/title ?val])
+          [?pv :property.value/content ?val])
       [(missing? $ ?b :block/name)]
       [(missing? $ ?b :block/name)]
       [?prop-e :db/ident ?prop]
       [?prop-e :db/ident ?prop]
       [?prop-e :block/type "property"]]
       [?prop-e :block/type "property"]]

+ 1 - 1
deps/db/src/logseq/db/frontend/schema.cljs

@@ -2,7 +2,7 @@
   "Main datascript schemas for the Logseq app"
   "Main datascript schemas for the Logseq app"
   (:require [clojure.set :as set]))
   (:require [clojure.set :as set]))
 
 
-(def version 9)
+(def version 10)
 ;; A page is a special block, a page can corresponds to multiple files with the same ":block/name".
 ;; A page is a special block, a page can corresponds to multiple files with the same ":block/name".
 (def ^:large-vars/data-var schema
 (def ^:large-vars/data-var schema
   {:db/ident        {:db/unique :db.unique/identity}
   {:db/ident        {:db/unique :db.unique/identity}

+ 3 - 3
deps/db/src/logseq/db/sqlite/build.cljs

@@ -484,7 +484,7 @@
         prop-value' (if (coll? prop-value) (first prop-value) prop-value)
         prop-value' (if (coll? prop-value) (first prop-value) prop-value)
         prop-type (if prop-value'
         prop-type (if prop-value'
                     (if (page-prop-value? prop-value')
                     (if (page-prop-value? prop-value')
-                      :page
+                      :node
                       (db-property-type/infer-property-type-from-value prop-value'))
                       (db-property-type/infer-property-type-from-value prop-value'))
                     :default)]
                     :default)]
     (cond-> {:block/schema {:type prop-type}}
     (cond-> {:block/schema {:type prop-type}}
@@ -585,8 +585,8 @@
    The :build/properties in :pages-and-blocks, :properties and :classes is a map of
    The :build/properties in :pages-and-blocks, :properties and :classes is a map of
    property name keywords to property values.  Multiple property values for a many
    property name keywords to property values.  Multiple property values for a many
    cardinality property are defined as a set. The following property types are
    cardinality property are defined as a set. The following property types are
-   supported: :default, :url, :checkbox, :number, :page and :date. :checkbox and
-   :number values are written as booleans and integers/floats. :page references
+   supported: :default, :url, :checkbox, :number, :node and :date. :checkbox and
+   :number values are written as booleans and integers/floats. :node references
    are written as vectors e.g. `[:page \"PAGE NAME\"]`"
    are written as vectors e.g. `[:page \"PAGE NAME\"]`"
   [options]
   [options]
   (validate-options options)
   (validate-options options)

+ 26 - 28
deps/db/src/logseq/db/sqlite/common_db.cljs

@@ -82,34 +82,32 @@
 (defn- property-with-values
 (defn- property-with-values
   [db block]
   [db block]
   (when (entity-plus/db-based-graph? db)
   (when (entity-plus/db-based-graph? db)
-    (let [block (d/entity db (:db/id block))
-          block-properties (when (seq (:block/properties block))
-                             (mapcat
-                              (fn [[_property-id property-values]]
-                                (let [values (if (and (coll? property-values)
-                                                      (map? (first property-values)))
-                                               property-values
-                                               #{property-values})
-                                      value-ids (when (every? map? values)
-                                                  (->> (map :db/id values)
-                                                       (filter (fn [id] (or (int? id) (keyword? id))))))
-                                      value-blocks (->>
-                                                    (when (seq value-ids)
-                                                      (map
-                                                       (fn [id] (d/pull db '[*] id))
-                                                       value-ids))
-                                                    ;; FIXME: why d/pull returns {:db/id db-ident} instead of {:db/id number-eid}?
-                                                    (map (fn [block]
-                                                           (let [from-property-id (get-in block [:logseq.property/created-from-property :db/id])]
-                                                             (if (keyword? from-property-id)
-                                                               (assoc-in block [:logseq.property/created-from-property :db/id] (:db/id (d/entity db from-property-id)))
-                                                               block)))))
-                                      page (when (seq values)
-                                             (when-let [page-id (:db/id (:block/page (d/entity db (:db/id (first values)))))]
-                                               (d/pull db '[*] page-id)))]
-                                  (remove nil? (concat [page] value-blocks))))
-                              (:block/properties block)))]
-      block-properties)))
+    (let [block (d/entity db (:db/id block))]
+      (->> (:block/properties block)
+           vals
+           (mapcat
+            (fn [property-values]
+              (let [values (->>
+                            (if (and (coll? property-values)
+                                     (map? (first property-values)))
+                              property-values
+                              #{property-values})
+                            (remove sqlite-util/page?))
+                    value-ids (when (every? map? values)
+                                (->> (map :db/id values)
+                                     (filter (fn [id] (or (int? id) (keyword? id))))))
+                    value-blocks (->>
+                                  (when (seq value-ids)
+                                    (map
+                                     (fn [id] (d/pull db '[*] id))
+                                     value-ids))
+                             ;; FIXME: why d/pull returns {:db/id db-ident} instead of {:db/id number-eid}?
+                                  (keep (fn [block]
+                                          (let [from-property-id (get-in block [:logseq.property/created-from-property :db/id])]
+                                            (if (keyword? from-property-id)
+                                              (assoc-in block [:logseq.property/created-from-property :db/id] (:db/id (d/entity db from-property-id)))
+                                              block)))))]
+                value-blocks)))))))
 
 
 (defn get-block-children-ids
 (defn get-block-children-ids
   "Returns children UUIDs"
   "Returns children UUIDs"

+ 1 - 1
deps/db/src/logseq/db/sqlite/util.cljs

@@ -107,7 +107,7 @@
         (assoc :db/valueType :db.type/ref))))))
         (assoc :db/valueType :db.type/ref))))))
 
 
 (defn build-new-class
 (defn build-new-class
-  "Build a standard new class so that it is is consistent across contexts"
+  "Build a standard new class so that it is consistent across contexts"
   [block]
   [block]
   {:pre [(qualified-keyword? (:db/ident block))]}
   {:pre [(qualified-keyword? (:db/ident block))]}
   (block-with-timestamps
   (block-with-timestamps

+ 1 - 1
deps/db/test/logseq/db/frontend/rules_test.cljs

@@ -50,7 +50,7 @@
            {:properties {:foo {:block/schema {:type :default}}
            {:properties {:foo {:block/schema {:type :default}}
                          :foo2 {:block/schema {:type :default}}
                          :foo2 {:block/schema {:type :default}}
                          :number-many {:block/schema {:type :number :cardinality :many}}
                          :number-many {:block/schema {:type :number :cardinality :many}}
-                         :page-many {:block/schema {:type :page :cardinality :many}}}
+                         :page-many {:block/schema {:type :node :cardinality :many}}}
             :pages-and-blocks
             :pages-and-blocks
             [{:page {:block/title "Page"
             [{:page {:block/title "Page"
                      :build/properties {:foo "bar" :number-many #{5 10} :page-many #{[:page "Page A"]}}}}
                      :build/properties {:foo "bar" :number-many #{5 10} :page-many #{[:page "Page A"]}}}}

+ 1 - 1
deps/graph-parser/package.json

@@ -7,7 +7,7 @@
     "better-sqlite3": "9.3.0"
     "better-sqlite3": "9.3.0"
   },
   },
   "dependencies": {
   "dependencies": {
-    "mldoc": "^1.5.8"
+    "mldoc": "^1.5.9"
   },
   },
   "scripts": {
   "scripts": {
     "test": "nbb-logseq -cp test:../outliner/src -m nextjournal.test-runner"
     "test": "nbb-logseq -cp test:../outliner/src -m nextjournal.test-runner"

+ 3 - 1
deps/graph-parser/src/logseq/graph_parser/mldoc.cljc

@@ -145,7 +145,9 @@
     (->>
     (->>
      (cond-> (default-config-map format)
      (cond-> (default-config-map format)
        db-based?
        db-based?
-       (assoc :enable_drawers false))
+       (assoc :enable_drawers false
+              :parse_marker false
+              :parse_priority false))
      bean/->js
      bean/->js
      js/JSON.stringify)))
      js/JSON.stringify)))
 
 

+ 6 - 6
deps/graph-parser/test/logseq/graph_parser/block_test.cljs

@@ -24,21 +24,21 @@
              (not= (:uuid x) (:block/uuid result))
              (not= (:uuid x) (:block/uuid result))
              (= (select-keys result
              (= (select-keys result
                              [:block/properties :block/title :block/properties-text-values :block/properties-order]) (gp-block/block-keywordize y))))
                              [:block/properties :block/title :block/properties-text-values :block/properties-order]) (gp-block/block-keywordize y))))
-    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :markdown, :meta {:start_pos 51, :end_pos 101}, :macros [], :content "bar\nid:: 63f199bc-c737-459f-983d-84acfcda14fe", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
+    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :markdown, :meta {:start_pos 51, :end_pos 101}, :macros [], :title "bar\nid:: 63f199bc-c737-459f-983d-84acfcda14fe", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
     {:properties {},
     {:properties {},
-     :content "bar",
+     :title "bar",
      :properties-text-values {},
      :properties-text-values {},
      :properties-order []}
      :properties-order []}
 
 
-    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :org, :meta {:start_pos 51, :end_pos 101}, :macros [], :content "bar\n:id: 63f199bc-c737-459f-983d-84acfcda14fe", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
+    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :org, :meta {:start_pos 51, :end_pos 101}, :macros [], :title "bar\n:id: 63f199bc-c737-459f-983d-84acfcda14fe", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
     {:properties {},
     {:properties {},
-     :content "bar",
+     :title "bar",
      :properties-text-values {},
      :properties-text-values {},
      :properties-order []}
      :properties-order []}
 
 
-    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :markdown, :meta {:start_pos 51, :end_pos 101}, :macros [], :content "bar\n  \n  id:: 63f199bc-c737-459f-983d-84acfcda14fe\nblock body", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
+    {:properties {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :tags [], :format :markdown, :meta {:start_pos 51, :end_pos 101}, :macros [], :title "bar\n  \n  id:: 63f199bc-c737-459f-983d-84acfcda14fe\nblock body", :properties-text-values {:id "63f199bc-c737-459f-983d-84acfcda14fe"}, :level 1, :uuid #uuid "63f199bc-c737-459f-983d-84acfcda14fe", :properties-order [:id]}
     {:properties {},
     {:properties {},
-     :content "bar\nblock body",
+     :title "bar\nblock body",
      :properties-text-values {},
      :properties-text-values {},
      :properties-order []}))
      :properties-order []}))
 
 

+ 1 - 1
deps/graph-parser/test/logseq/graph_parser/cli_test.cljs

@@ -14,7 +14,7 @@
     (docs-graph-helper/docs-graph-assertions @conn graph-dir files)
     (docs-graph-helper/docs-graph-assertions @conn graph-dir files)
 
 
     (testing "Additional counts"
     (testing "Additional counts"
-      (is (= 58051 (count (d/datoms @conn :eavt))) "Correct datoms count"))
+      (is (= 58054 (count (d/datoms @conn :eavt))) "Correct datoms count"))
 
 
     (testing "Asts"
     (testing "Asts"
       (is (seq asts) "Asts returned are non-zero")
       (is (seq asts) "Asts returned are non-zero")

+ 4 - 4
deps/graph-parser/yarn.lock

@@ -276,10 +276,10 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
 
 
-mldoc@^1.5.8:
-  version "1.5.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.8.tgz#5433950c9124f8917075bafa4f1ed886959504c5"
-  integrity sha512-wNUGgwdgB/5c3GTp2qRPzWD8CpeTmA/HDlGJjTJUo2WXJttiBaz8cHQh2OdAshiLdVxteqIaSTXSPFRf7z1YRw==
+mldoc@^1.5.9:
+  version "1.5.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc"
+  integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ==
   dependencies:
   dependencies:
     yargs "^12.0.2"
     yargs "^12.0.2"
 
 

+ 1 - 1
deps/outliner/package.json

@@ -7,7 +7,7 @@
   },
   },
   "dependencies": {
   "dependencies": {
     "better-sqlite3": "9.3.0",
     "better-sqlite3": "9.3.0",
-    "mldoc": "^1.5.8"
+    "mldoc": "^1.5.9"
   },
   },
   "scripts": {
   "scripts": {
     "test": "yarn nbb-logseq -cp test -m nextjournal.test-runner"
     "test": "yarn nbb-logseq -cp test -m nextjournal.test-runner"

+ 31 - 26
deps/outliner/src/logseq/outliner/property.cljs

@@ -221,8 +221,10 @@
   [conn property-id v property-type]
   [conn property-id v property-type]
   (if (and (integer? v)
   (if (and (integer? v)
            (or (not= property-type :number)
            (or (not= property-type :number)
-               ;; Allows :number property to use number as a ref (for closed value) or value. Number value maybe only used in tests
-               (and (= property-type :number) (= property-id (:db/ident (:logseq.property/created-from-property (d/entity @conn v)))))))
+               ;; Allows :number property to use number as a ref (for closed value) or value
+               (and (= property-type :number)
+                    (or (= property-id (:db/ident (:logseq.property/created-from-property (d/entity @conn v))))
+                        (= :logseq.property/empty-placeholder (:db/ident (d/entity @conn v)))))))
     v
     v
     ;; only value-ref-property types should call this
     ;; only value-ref-property types should call this
     (find-or-create-property-value conn property-id v)))
     (find-or-create-property-value conn property-id v)))
@@ -395,32 +397,24 @@
      (seq properties))))
      (seq properties))))
 
 
 (defn- build-closed-value-tx
 (defn- build-closed-value-tx
-  [db property resolved-value {:keys [id icon description]
-                               :or {description ""}}]
+  [db property resolved-value {:keys [id icon]}]
   (let [block (when id (d/entity db [:block/uuid id]))
   (let [block (when id (d/entity db [:block/uuid id]))
         block-id (or id (ldb/new-block-id))
         block-id (or id (ldb/new-block-id))
         icon (when-not (and (string? icon) (string/blank? icon)) icon)
         icon (when-not (and (string? icon) (string/blank? icon)) icon)
-        description (string/trim description)
-        description (when-not (string/blank? description) description)
         tx-data (if block
         tx-data (if block
-                  [(let [schema (:block/schema block)]
-                     (cond->
-                      (outliner-core/block-with-updated-at
-                       (merge
-                        {:block/uuid id
-                         :block/closed-value-property (:db/id property)
-                         :block/schema (if description
-                                         (assoc schema :description description)
-                                         (dissoc schema :description))}
-                        (if (db-property-type/original-value-ref-property-types (get-in property [:block/schema :type]))
-                          {:property.value/content resolved-value}
-                          {:block/title resolved-value})))
-                       icon
-                       (assoc :logseq.property/icon icon)))]
+                  [(cond->
+                    (outliner-core/block-with-updated-at
+                     (merge
+                      {:block/uuid id
+                       :block/closed-value-property (:db/id property)}
+                      (if (db-property-type/original-value-ref-property-types (get-in property [:block/schema :type]))
+                        {:property.value/content resolved-value}
+                        {:block/title resolved-value})))
+                     icon
+                     (assoc :logseq.property/icon icon))]
                   (let [max-order (:block/order (last (:property/closed-values property)))
                   (let [max-order (:block/order (last (:property/closed-values property)))
                         new-block (-> (db-property-build/build-closed-value-block block-id resolved-value
                         new-block (-> (db-property-build/build-closed-value-block block-id resolved-value
-                                                                                  property {:icon icon
-                                                                                            :description description})
+                                                                                  property {:icon icon})
                                       (assoc :block/order (db-order/gen-key max-order nil)))]
                                       (assoc :block/order (db-order/gen-key max-order nil)))]
                     [new-block
                     [new-block
                      (outliner-core/block-with-updated-at
                      (outliner-core/block-with-updated-at
@@ -432,7 +426,7 @@
 
 
 (defn upsert-closed-value!
 (defn upsert-closed-value!
   "id should be a block UUID or nil"
   "id should be a block UUID or nil"
-  [conn property-id {:keys [id value] :as opts}]
+  [conn property-id {:keys [id value description] :as opts}]
   (assert (or (nil? id) (uuid? id)))
   (assert (or (nil? id) (uuid? id)))
   (let [db @conn
   (let [db @conn
         property (d/entity db property-id)
         property (d/entity db property-id)
@@ -470,9 +464,20 @@
           nil
           nil
 
 
           :else
           :else
-          (ldb/transact! conn
-                         (build-closed-value-tx @conn property resolved-value opts)
-                         {:outliner-op :save-block}))))))
+          (let [tx-data (build-closed-value-tx @conn property resolved-value opts)]
+            (ldb/transact! conn tx-data {:outliner-op :save-block})
+
+            (when (seq description)
+              (if-let [desc-ent (and id (:logseq.property/description (d/entity db [:block/uuid id])))]
+                (ldb/transact! conn
+                               [(outliner-core/block-with-updated-at {:db/id (:db/id desc-ent)
+                                                                      :block/title description})]
+                               {:outliner-op :save-block})
+                (set-block-property! conn
+                                     ;; new closed value is first in tx-data
+                                     [:block/uuid (or id (:block/uuid (first tx-data)))]
+                                     :logseq.property/description
+                                     description)))))))))
 
 
 (defn add-existing-values-to-closed-values!
 (defn add-existing-values-to-closed-values!
   "Adds existing values as closed values and returns their new block uuids"
   "Adds existing values as closed values and returns their new block uuids"

+ 1 - 1
deps/outliner/test/logseq/outliner/property_test.cljs

@@ -256,7 +256,7 @@
                                                                                :description "choice 4"})
                                                                                :description "choice 4"})
             updated-b (d/entity @conn [:block/uuid (:block/uuid b)])]
             updated-b (d/entity @conn [:block/uuid (:block/uuid b)])]
         (is (= 4 (db-property/closed-value-content updated-b)))
         (is (= 4 (db-property/closed-value-content updated-b)))
-        (is (= "choice 4" (:description (:block/schema updated-b))))))))
+        (is (= "choice 4" (db-property/property-value-content (:logseq.property/description updated-b))))))))
 
 
 (deftest delete-closed-value!
 (deftest delete-closed-value!
   (let [closed-value-uuid (random-uuid)
   (let [closed-value-uuid (random-uuid)

+ 4 - 4
deps/outliner/yarn.lock

@@ -276,10 +276,10 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
 
 
-mldoc@^1.5.8:
-  version "1.5.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.8.tgz#5433950c9124f8917075bafa4f1ed886959504c5"
-  integrity sha512-wNUGgwdgB/5c3GTp2qRPzWD8CpeTmA/HDlGJjTJUo2WXJttiBaz8cHQh2OdAshiLdVxteqIaSTXSPFRf7z1YRw==
+mldoc@^1.5.9:
+  version "1.5.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc"
+  integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ==
   dependencies:
   dependencies:
     yargs "^12.0.2"
     yargs "^12.0.2"
 
 

+ 1 - 1
deps/publishing/package.json

@@ -4,7 +4,7 @@
   "private": true,
   "private": true,
   "devDependencies": {
   "devDependencies": {
     "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v15",
     "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v15",
-    "mldoc": "^1.5.8"
+    "mldoc": "^1.5.9"
   },
   },
   "dependencies": {
   "dependencies": {
     "fs-extra": "9.1.0"
     "fs-extra": "9.1.0"

+ 4 - 4
deps/publishing/yarn.lock

@@ -189,10 +189,10 @@ mimic-fn@^2.0.0:
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
 
-mldoc@^1.5.8:
-  version "1.5.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.8.tgz#5433950c9124f8917075bafa4f1ed886959504c5"
-  integrity sha512-wNUGgwdgB/5c3GTp2qRPzWD8CpeTmA/HDlGJjTJUo2WXJttiBaz8cHQh2OdAshiLdVxteqIaSTXSPFRf7z1YRw==
+mldoc@^1.5.9:
+  version "1.5.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc"
+  integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ==
   dependencies:
   dependencies:
     yargs "^12.0.2"
     yargs "^12.0.2"
 
 

+ 1 - 1
package.json

@@ -135,7 +135,7 @@
         "jszip": "3.8.0",
         "jszip": "3.8.0",
         "katex": "^0.16.10",
         "katex": "^0.16.10",
         "marked": "^5.1.2",
         "marked": "^5.1.2",
-        "mldoc": "^1.5.8",
+        "mldoc": "^1.5.9",
         "path": "0.12.7",
         "path": "0.12.7",
         "path-complete-extname": "1.0.0",
         "path-complete-extname": "1.0.0",
         "pdfjs-dist": "^3.9.179",
         "pdfjs-dist": "^3.9.179",

+ 1 - 1
scripts/package.json

@@ -8,6 +8,6 @@
   "dependencies": {
   "dependencies": {
     "better-sqlite3": "9.3.0",
     "better-sqlite3": "9.3.0",
     "fs-extra": "9.1.0",
     "fs-extra": "9.1.0",
-    "mldoc": "^1.5.8"
+    "mldoc": "^1.5.9"
   }
   }
 }
 }

+ 25 - 17
scripts/src/logseq/tasks/db_graph/create_graph_with_schema_org.cljs

@@ -11,7 +11,6 @@
        type logseq doesnt' support yet
        type logseq doesnt' support yet
      * schema.org assumes no cardinality. For now, only :node properties are given a :cardinality :many"
      * schema.org assumes no cardinality. For now, only :node properties are given a :cardinality :many"
   (:require [logseq.outliner.cli :as outliner-cli]
   (:require [logseq.outliner.cli :as outliner-cli]
-            [logseq.common.util :as common-util]
             [logseq.db.frontend.property :as db-property]
             [logseq.db.frontend.property :as db-property]
             [clojure.string :as string]
             [clojure.string :as string]
             [clojure.edn :as edn]
             [clojure.edn :as edn]
@@ -66,7 +65,7 @@
     (cond-> {:block/title class-name
     (cond-> {:block/title class-name
              :build/properties (cond-> {:url url}
              :build/properties (cond-> {:url url}
                                  (class-m "rdfs:comment")
                                  (class-m "rdfs:comment")
-                                 (assoc :description (get-comment-string (class-m "rdfs:comment") renamed-pages)))}
+                                 (assoc :logseq.property/description (get-comment-string (class-m "rdfs:comment") renamed-pages)))}
       parent-class'
       parent-class'
       (assoc :build/class-parent (keyword (strip-schema-prefix parent-class')))
       (assoc :build/class-parent (keyword (strip-schema-prefix parent-class')))
       (seq properties)
       (seq properties)
@@ -77,8 +76,8 @@
   {"schema:Integer" :number
   {"schema:Integer" :number
    "schema:Float" :number
    "schema:Float" :number
    "schema:Number" :number
    "schema:Number" :number
-   "schema:Text_Class" :default
-   "schema:URL_Class" :url
+   "schema:Text" :default
+   "schema:URL" :url
    "schema:Boolean" :checkbox
    "schema:Boolean" :checkbox
    "schema:Date" :date})
    "schema:Date" :date})
 
 
@@ -118,12 +117,12 @@
         schema (cond-> {:type schema-type}
         schema (cond-> {:type schema-type}
                  ;; This cardinality rule should be adjusted as we use schema.org more
                  ;; This cardinality rule should be adjusted as we use schema.org more
                  (= schema-type :node)
                  (= schema-type :node)
-                 (assoc :cardinality :many)
-                 (property-m "rdfs:comment")
-                 (assoc :description (get-comment-string (property-m "rdfs:comment") renamed-pages)))]
+                 (assoc :cardinality :many))]
     {(keyword (strip-schema-prefix (property-m "@id")))
     {(keyword (strip-schema-prefix (property-m "@id")))
      (cond-> {:block/schema schema
      (cond-> {:block/schema schema
-              :build/properties {:url url}}
+              :build/properties (cond-> {:url url}
+                                  (property-m "rdfs:comment")
+                                  (assoc :logseq.property/description (get-comment-string (property-m "rdfs:comment") renamed-pages)))}
        (= schema-type :node)
        (= schema-type :node)
        (assoc :build/schema-classes (mapv (comp keyword strip-schema-prefix) range-includes)))}))
        (assoc :build/schema-classes (mapv (comp keyword strip-schema-prefix) range-includes)))}))
 
 
@@ -158,11 +157,11 @@
 
 
 (defn- get-vector-conflicts
 (defn- get-vector-conflicts
   "Given a seq of tuples returns a seq of tuples that conflict i.e. their first element
   "Given a seq of tuples returns a seq of tuples that conflict i.e. their first element
-   has a case insensitive conflict/duplicate with another. An example conflict:
-   [[\"schema:businessFunction\" :property] [\"schema:BusinessFunction\" :class]]"
+   has a case sensitive conflict/duplicate with another. An example conflict:
+   [[\"schema:status\" :property] [\"schema:status\" :node]]"
   [tuples-seq]
   [tuples-seq]
   (->> tuples-seq
   (->> tuples-seq
-       (group-by (comp common-util/page-name-sanity-lc first))
+       (group-by first)
        (filter #(> (count (val %)) 1))
        (filter #(> (count (val %)) 1))
        vals))
        vals))
 
 
@@ -190,7 +189,8 @@
     (if verbose
     (if verbose
       (println "Renaming the following properties because they have names that conflict with Logseq's built in pages"
       (println "Renaming the following properties because they have names that conflict with Logseq's built in pages"
                (keys renamed-properties) "\n")
                (keys renamed-properties) "\n")
-      (println "Renaming" (count renamed-properties) "properties due to page name conflicts"))
+      (when (pos? (count renamed-properties))
+        (println "Renaming" (count renamed-properties) "properties due to page name conflicts")))
     renamed-properties))
     renamed-properties))
 
 
 (defn- detect-id-conflicts-and-get-renamed-classes
 (defn- detect-id-conflicts-and-get-renamed-classes
@@ -219,7 +219,8 @@
     (if verbose
     (if verbose
       (println "Renaming the following classes because they have property names that conflict with Logseq's case insensitive :block/name:"
       (println "Renaming the following classes because they have property names that conflict with Logseq's case insensitive :block/name:"
                (keys renamed-classes) "\n")
                (keys renamed-classes) "\n")
-      (println "Renaming" (count renamed-classes) "classes due to page name conflicts"))
+      (when (pos? (count renamed-classes))
+        (println "Renaming" (count renamed-classes) "classes due to page name conflicts")))
     renamed-classes))
     renamed-classes))
 
 
 (defn- get-all-properties [schema-data {:keys [verbose]}]
 (defn- get-all-properties [schema-data {:keys [verbose]}]
@@ -255,8 +256,13 @@
                           (get-schema-type (get-range-includes property-m) class-map)))
                           (get-schema-type (get-range-includes property-m) class-map)))
                   frequencies)
                   frequencies)
              "\n"))
              "\n"))
-  (apply merge
-         (mapv #(->property-page % class-map options) select-properties)))
+  (assoc
+   (apply merge
+          (mapv #(->property-page % class-map options) select-properties))
+   ;; Have to update schema for now as validation doesn't take into account existing properties
+   :logseq.property/description {:block/schema {:public? true :type :default}
+                                 :build/properties {:url "https://schema.org/description"
+                                                    :logseq.property/description "A description of the item."}}))
 
 
 (defn- get-all-classes-and-properties
 (defn- get-all-classes-and-properties
   "Get all classes and properties from raw json file"
   "Get all classes and properties from raw json file"
@@ -266,7 +272,8 @@
                                                 (if (string? type') [type'] type')))
                                                 (if (string? type') [type'] type')))
                                          "rdfs:Class")
                                          "rdfs:Class")
                              schema-data)
                              schema-data)
-        all-properties* (get-all-properties schema-data options)
+        ;; Use built-in description
+        all-properties* (remove #(= "schema:description" (% "@id")) (get-all-properties schema-data options))
         property-tuples (map #(vector (% "@id") :property) all-properties*)
         property-tuples (map #(vector (% "@id") :property) all-properties*)
         class-tuples (map #(vector (% "@id") :class) all-classes*)
         class-tuples (map #(vector (% "@id") :class) all-classes*)
         page-tuples (map #(vector (str "schema:" %) :node) existing-pages)
         page-tuples (map #(vector (str "schema:" %) :node) existing-pages)
@@ -275,6 +282,7 @@
         renamed-properties (detect-property-conflicts-and-get-renamed-properties
         renamed-properties (detect-property-conflicts-and-get-renamed-properties
                             property-tuples page-tuples options)
                             property-tuples page-tuples options)
         renamed-pages (merge renamed-classes renamed-properties)
         renamed-pages (merge renamed-classes renamed-properties)
+        ;; Note: schema:description refs don't get renamed but they aren't used
         ;; Updates keys like @id, @subClassOf
         ;; Updates keys like @id, @subClassOf
         rename-page-ids (fn [m]
         rename-page-ids (fn [m]
                           (w/postwalk (fn [x]
                           (w/postwalk (fn [x]
@@ -308,7 +316,7 @@
         select-class-ids
         select-class-ids
         (if (:subset options)
         (if (:subset options)
           ["schema:Person" "schema:CreativeWorkSeries" "schema:Organization"
           ["schema:Person" "schema:CreativeWorkSeries" "schema:Organization"
-           "schema:Movie" "schema:CreativeWork" "schema:Thing"]
+           "schema:Movie" "schema:CreativeWork" "schema:Thing" "schema:Comment"]
           (keys class-map))
           (keys class-map))
         class-to-properties (get-class-to-properties select-class-ids all-properties)
         class-to-properties (get-class-to-properties select-class-ids all-properties)
         select-properties (set (mapcat val class-to-properties))
         select-properties (set (mapcat val class-to-properties))

+ 3 - 1
scripts/src/logseq/tasks/dev/db_and_file_graphs.clj

@@ -16,7 +16,8 @@
          "electron.db"
          "electron.db"
          "frontend.handler.db-based."
          "frontend.handler.db-based."
          "frontend.worker.handler.page.db-based"
          "frontend.worker.handler.page.db-based"
-         "frontend.components.property" "frontend.components.class" "frontend.components.db-based"]))
+         "frontend.components.property" "frontend.components.class" "frontend.components.db-based"
+         "frontend.components.objects"]))
 
 
 (def file-graph-ns
 (def file-graph-ns
   "Namespaces or parent namespaces _only_ for file graphs"
   "Namespaces or parent namespaces _only_ for file graphs"
@@ -38,6 +39,7 @@
    "src/main/frontend/components/class.cljs"
    "src/main/frontend/components/class.cljs"
    "src/main/frontend/components/property.cljs"
    "src/main/frontend/components/property.cljs"
    "src/main/frontend/components/property"
    "src/main/frontend/components/property"
+   "src/main/frontend/components/objects.cljs"
    "src/main/frontend/components/db_based"
    "src/main/frontend/components/db_based"
    "src/electron/electron/db.cljs"])
    "src/electron/electron/db.cljs"])
 
 

+ 4 - 4
scripts/yarn.lock

@@ -305,10 +305,10 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
 
 
-mldoc@^1.5.8:
-  version "1.5.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.8.tgz#5433950c9124f8917075bafa4f1ed886959504c5"
-  integrity sha512-wNUGgwdgB/5c3GTp2qRPzWD8CpeTmA/HDlGJjTJUo2WXJttiBaz8cHQh2OdAshiLdVxteqIaSTXSPFRf7z1YRw==
+mldoc@^1.5.9:
+  version "1.5.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc"
+  integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ==
   dependencies:
   dependencies:
     yargs "^12.0.2"
     yargs "^12.0.2"
 
 

+ 1 - 1
src/main/frontend/common.css

@@ -384,7 +384,7 @@ button.menu:focus {
 
 
 .menu-link {
 .menu-link {
   @apply text-popover-foreground/75 select-none hover:text-popover-foreground/100;
   @apply text-popover-foreground/75 select-none hover:text-popover-foreground/100;
-  @apply text-sm px-2 py-1.5 mx-1 hover:rounded transition-opacity duration-150;
+  @apply text-sm px-2 py-1.5 hover:rounded transition-opacity duration-150;
 }
 }
 
 
 .menu-separator {
 .menu-separator {

+ 1 - 1
src/main/frontend/components/block.cljs

@@ -2479,7 +2479,7 @@
        (when-not plugin-slotted?
        (when-not plugin-slotted?
          [:div.block-head-wrap
          [:div.block-head-wrap
           (cond
           (cond
-            (ldb/page? block)
+            (or (ldb/page? block) (and (:table? config) (seq (:block/tags block))))
             [:div.flex.flex-row.items-center.gap-1
             [:div.flex.flex-row.items-center.gap-1
              (page-cp config block)]
              (page-cp config block)]
 
 

+ 18 - 0
src/main/frontend/components/block.css

@@ -204,6 +204,24 @@
 
 
   &.as-heading {
   &.as-heading {
     @apply flex flex-1;
     @apply flex flex-1;
+
+    h1& {
+      .ui__icon.ti svg {
+        @apply w-8 h-7;
+      }
+    }
+
+    h2& {
+      .ui__icon.ti svg {
+        @apply w-7 h-6;
+      }
+    }
+
+    h3& {
+      .ui__icon.ti svg {
+        @apply w-5 h-5;
+      }
+    }
   }
   }
 
 
   &:has(.dsl-query), &:has(.embed-page) {
   &:has(.dsl-query), &:has(.embed-page) {

+ 4 - 4
src/main/frontend/components/container.cljs

@@ -545,7 +545,7 @@
                    {:drop (fn [_e files]
                    {:drop (fn [_e files]
                             (when-let [id (state/get-edit-input-id)]
                             (when-let [id (state/get-edit-input-id)]
                               (let [format (:block/format (state/get-edit-block))]
                               (let [format (:block/format (state/get-edit-block))]
-                                (editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))})
+                                (editor-handler/upload-asset! id files format editor-handler/*asset-uploading? true))))})
                   (common-handler/listen-to-scroll! element)
                   (common-handler/listen-to-scroll! element)
                   (when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar
                   (when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar
                     (set! (.. element -scrollTop) 0)))
                     (set! (.. element -scrollTop) 0)))
@@ -555,10 +555,10 @@
                      (dnd/unsubscribe! el :upload-files))
                      (dnd/unsubscribe! el :upload-files))
                    state)}
                    state)}
   [{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
   [{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
-  (let [left-sidebar-open?   (state/sub :ui/left-sidebar-open?)
+  (let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
         onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
         onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
-                                  (not config/publishing?)
-                                  (= :home route-name))
+                               (not config/publishing?)
+                               (= :home route-name))
         margin-less-pages?   (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)]
         margin-less-pages?   (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)]
     [:div#main-container.cp__sidebar-main-layout.flex-1.flex
     [:div#main-container.cp__sidebar-main-layout.flex-1.flex
      {:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}
      {:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}

+ 80 - 250
src/main/frontend/components/editor.cljs

@@ -482,124 +482,6 @@
                (util/stop e)
                (util/stop e)
                (on-submit command @input-value pos)))])))))
                (on-submit command @input-value pos)))])))))
 
 
-(rum/defc absolute-modal < rum/static
-  [cp modal-name set-default-width? {:keys [top left rect]}]
-  (let [MAX-HEIGHT 700
-        MAX-HEIGHT' 600
-        MAX-WIDTH 600
-        SM-MAX-WIDTH 300
-        Y-BOUNDARY-HEIGHT 150
-        vw-width js/window.innerWidth
-        vw-height js/window.innerHeight
-        vw-max-width (- vw-width (:left rect))
-        vw-max-height (- vw-height (:top rect))
-        vw-max-height' (:top rect)
-        sm? (< vw-width 415)
-        max-height (min (- vw-max-height 20) MAX-HEIGHT)
-        max-height' (min (- vw-max-height' 70) MAX-HEIGHT')
-        max-width (if sm? SM-MAX-WIDTH (min (max 400 (/ vw-max-width 2)) MAX-WIDTH))
-        offset-top 24
-        to-max-height (cond-> (if (and (seq rect) (> vw-height max-height))
-                                (let [delta-height (- vw-height (+ (:top rect) top offset-top))]
-                                  (if (< delta-height max-height)
-                                    (- (max (* 2 offset-top) delta-height) 16)
-                                    max-height))
-                                max-height)
-
-                        (= modal-name "commands")
-                        (min 500))
-        right-sidebar? (:ui/sidebar-open? @state/state)
-        editing-key    (state/get-edit-input-id)
-        *el (rum/use-ref nil)
-        y-overflow-vh? (or (< to-max-height Y-BOUNDARY-HEIGHT)
-                           (> (- max-height' to-max-height) Y-BOUNDARY-HEIGHT))
-        to-max-height (if y-overflow-vh? max-height' to-max-height)
-        pos-rect (when (and (seq rect) editing-key)
-                   (:rect (cursor/get-caret-pos (state/get-input))))
-        y-diff (when pos-rect (- (:height pos-rect) (:height rect)))
-        style (merge
-               {:top        (+ top offset-top (if (int? y-diff) y-diff 0))
-                :max-height to-max-height
-                :max-width  700
-                ;; TODO: auto responsive fixed size
-                :width      "fit-content"
-                :z-index    11}
-               (when set-default-width?
-                 {:width max-width})
-               (if (<= vw-max-width (+ left (if set-default-width? max-width 500)))
-                 {:right 0}
-                 {:left 0}))]
-
-    (rum/use-effect!
-     (fn []
-       (when-let [^js/HTMLElement cnt
-                  (and right-sidebar? editing-key
-                       (js/document.querySelector "#main-content-container"))]
-         (when (.contains cnt (js/document.querySelector (str "#" editing-key)))
-           (let [el  (rum/deref *el)
-                 ofx (- (.-scrollWidth cnt) (.-clientWidth cnt))]
-             (when (> ofx 0)
-               (set! (.-transform (.-style el))
-                     (util/format "translate(-%spx, %s)" (+ ofx 20) (if y-overflow-vh? "calc(-100% - 2rem)" 0))))))))
-     [right-sidebar? editing-key y-overflow-vh?])
-
-    ;; HACK: close when click outside for classic editing models (popup)
-    (rum/use-effect!
-      (fn []
-        (let [^js cnt js/document.body
-              handle (fn [^js e]
-                       (when-not (some->> (.-target e) (.contains (rum/deref *el)))
-                         (state/clear-editor-action!)))]
-          (.addEventListener cnt "click" handle false)
-          #(.removeEventListener cnt "click" handle)))
-      [])
-
-    [:div.absolute.rounded-md.shadow-lg.absolute-modal
-     {:ref             *el
-      :data-modal-name modal-name
-      :class           (if y-overflow-vh? "is-overflow-vh-y" "")
-      :on-pointer-down   (fn [e]
-                         (.stopPropagation e))
-      :on-key-down     (fn [^js e]
-                         (case (.-key e)
-                           "Escape"
-                           (do (state/clear-editor-action!)
-                               (some-> (state/get-input)
-                                 (.focus)))
-                           :dune)
-                         (util/stop-propagation e))
-      :style style}
-     cp]))
-
-(rum/defc transition-cp < rum/reactive
-  [cp modal-name set-default-width?]
-  (when-let [pos (:pos (state/sub :editor/action-data))]
-    (ui/css-transition
-      {:class-names "fade"
-       :timeout {:enter 500
-                 :exit 300}}
-      (absolute-modal cp modal-name set-default-width? pos))))
-
-(rum/defc image-uploader < rum/reactive
-  [id format]
-  [:div.image-uploader
-   [:input
-    {:id        "upload-file"
-     :type      "file"
-     :on-change (fn [e]
-                  (let [files (.-files (.-target e))]
-                    (editor-handler/upload-asset id files format editor-handler/*asset-uploading? false)))
-     :hidden    true}]
-   #_:clj-kondo/ignore
-   (when-let [uploading? (util/react editor-handler/*asset-uploading?)]
-     (let [processing (util/react editor-handler/*asset-uploading-process)]
-       (transition-cp
-        [:div.flex.flex-row.align-center.rounded-md.shadow-sm.bg-base-2.px-1.py-1
-         (ui/loading
-          (util/format "Uploading %s%" (util/format "%2d" processing)))]
-        "upload-file"
-        false)))])
-
 (defn- set-up-key-down!
 (defn- set-up-key-down!
   [state format]
   [state format]
   (mixins/on-key-down
   (mixins/on-key-down
@@ -694,146 +576,98 @@
          [:span {:id (str "mock-text_" idx)
          [:span {:id (str "mock-text_" idx)
                  :key idx} c])))])
                  :key idx} c])))])
 
 
-(rum/defc animated-modal < rum/reactive
-  [modal-name component set-default-width?]
-  (when-let [pos (:pos (state/get-editor-action-data))]
-    (ui/css-transition
-     {:key modal-name
-      :class-names {:enter "origin-top-left opacity-0 transform scale-95"
-                    :enter-done "origin-top-left transition opacity-100 transform scale-100"
-                    :exit "origin-top-left transition opacity-0 transform scale-95"}
-      :timeout {:enter 0
-                :exit 150}}
-     (fn [_]
-       (absolute-modal
-        component
-        modal-name
-        set-default-width?
-        pos)))))
-
 (defn- exist-editor-commands-popup?
 (defn- exist-editor-commands-popup?
   []
   []
   (some->> (shui-popup/get-popups)
   (some->> (shui-popup/get-popups)
     (some #(some-> % (:id) (str) (string/starts-with? ":editor.commands")))))
     (some #(some-> % (:id) (str) (string/starts-with? ":editor.commands")))))
 
 
-;; TODO: [WIP]
-(rum/defc shui-modals
+(defn- open-editor-popup!
+  [id content opts]
+  (let [{:keys [left top rect]} (cursor/get-caret-pos (state/get-input))
+        pos [(+ left (:left rect) -20) (+ top (:top rect) 20)]
+        {:keys [root-props content-props]} opts]
+    (shui/popup-show!
+      pos content
+      (merge
+        {:id (keyword :editor.commands id)
+         :align :start
+         :root-props (merge {:onOpenChange #(when-not % (state/clear-editor-action!))} root-props)
+         :content-props (merge {:onOpenAutoFocus #(.preventDefault %)
+                                :onCloseAutoFocus #(.preventDefault %)
+                                :data-editor-popup-ref (name id)} content-props)
+         :force-popover? true}
+        (dissoc opts :root-props :content-props)))))
+
+(rum/defc shui-editor-popups
   [id format action _data]
   [id format action _data]
   (rum/use-effect!
   (rum/use-effect!
     (fn []
     (fn []
-      (let [{:keys [left top rect]} (cursor/get-caret-pos (state/get-input))
-            pos [(+ left (:left rect) -20) (+ top (:top rect) 20)]]
-        (let [pid (case action
-                    :commands
-                    (shui/popup-show! pos
-                      (commands id format)
-                      {:id :editor.commands/commands
-                       :align :start
-                       :root-props {:onOpenChange
-                                    #(when-not %
-                                       (when (= :commands (state/get-editor-action))
-                                         (state/clear-editor-action!)))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :onCloseAutoFocus #(.preventDefault %)
-                                       :withoutAnimation true
-                                       :data-editor-popup-ref "commands"}
-                       :force-popover? true})
-
-                    :block-commands
-                    (shui/popup-show! pos
-                      (block-commands id format)
-                      {:id :editor.commands/block-commands
-                       :align :start
-                       :root-props {:onOpenChange
-                                    #(when-not %
-                                       (when (= :block-commands (state/get-editor-action))
-                                         (state/clear-editor-action!)))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :onCloseAutoFocus #(.preventDefault %)
-                                       :withoutAnimation true
-                                       :data-editor-popup-ref "commands"}
-                       :force-popover? true})
-
-                    (:block-search :page-search :page-search-hashtag)
-                    (shui/popup-show!
-                      pos (if (= :block-search action)
-                            (block-search id format)
-                            (page-search id format))
-                      {:id :editor.commands/block-search
-                       :align :start
-                       :root-props {:onOpenChange
-                                    #(when-not %
-                                       (when (contains?
-                                               #{:block-search :page-search :page-search-hashtag}
-                                               (state/get-editor-action))
-                                         (state/clear-editor-action!)))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :onCloseAutoFocus #(.preventDefault %)
-                                       :data-editor-popup-ref (name action)}
-                       :force-popover? true})
-
-                    :datepicker
-                    (shui/popup-show!
-                      pos (datetime-comp/date-picker id format nil)
-                      {:id :editor.commands/datepicker
-                       :align :start
-                       :root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :data-editor-popup-ref "datepicker"}
-                       :force-popover? true})
-
-                    :input
-                    (shui/popup-show!
-                      pos (input id
-                            (fn [command m]
-                              (editor-handler/handle-command-input command id format m))
-                            (fn []
-                              (editor-handler/handle-command-input-close id)))
-                      {:id :editor.commands/input
-                       :align :start
-                       :root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :onCloseAutoFocus #(.preventDefault %)
-                                       :data-editor-popup-ref "input"}})
-
-                    :select-code-block-mode
-                    (shui/popup-show!
-                      pos (code-block-mode-picker id format)
-                      {:id :editor.commands/code-block-mode-picker
-                       :align :start
-                       :root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
-                       :content-props {:onOpenAutoFocus #(.preventDefault %)
-                                       :data-editor-popup-ref "code-block-mode-picker"}
-                       :force-popover? true})
-
-                    ;; TODO: try remove local model state
-                    false)]
-          #(when pid
-             (shui/popup-hide! pid)))))
+      (let [pid (case action
+                  :commands
+                  (open-editor-popup! :commands
+                    (commands id format)
+                    {:content-props {:withoutAnimation false}})
+
+                  :block-commands
+                  (open-editor-popup! :block-commands
+                    (block-commands id format)
+                    {:content-props {:withoutAnimation true}})
+
+                  (:block-search :page-search :page-search-hashtag)
+                  (open-editor-popup! action
+                    (if (= :block-search action)
+                      (block-search id format)
+                      (page-search id format))
+                    {:root-props {:onOpenChange
+                                  #(when-not %
+                                     (when (contains?
+                                             #{:block-search :page-search :page-search-hashtag}
+                                             (state/get-editor-action))
+                                       (state/clear-editor-action!)))}})
+
+                  :datepicker
+                  (open-editor-popup! :datepicker
+                    (datetime-comp/date-picker id format nil) {})
+
+                  :input
+                  (open-editor-popup! :input
+                    (input id
+                      (fn [command m]
+                        (editor-handler/handle-command-input command id format m))
+                      (fn []
+                        (editor-handler/handle-command-input-close id))) {})
+
+                  :select-code-block-mode
+                  (open-editor-popup! :code-block-mode-picker
+                    (code-block-mode-picker id format) {})
+
+                  :template-search
+                  (open-editor-popup! :template-search
+                    (template-search id format) {})
+
+                  (:property-search :property-value-search)
+                  (open-editor-popup! action
+                    (if (= :property-search action)
+                      (property-search id) (property-value-search id))
+                    {})
+
+                  :zotero
+                  (open-editor-popup! :zotero
+                    (zotero/zotero-search id) {})
+
+                  ;; TODO: try remove local model state
+                  false)]
+        #(when pid
+           (shui/popup-hide! pid))))
     [action])
     [action])
   [:<>])
   [:<>])
 
 
-(rum/defc modals < rum/reactive
-  "React to atom changes, find and render the correct modal"
+(rum/defc command-popups <
+  rum/reactive
+  "React to atom changes, find and render the correct popup"
   [id format]
   [id format]
   (let [action (state/sub :editor/action)]
   (let [action (state/sub :editor/action)]
-    [:<>
-     (shui-modals id format action nil)
-     (cond
-       (= :template-search action)
-       (animated-modal "template-search" (template-search id format) true)
-
-       (= :property-search action)
-       (animated-modal "property-search" (property-search id) true)
-
-       (= :property-value-search action)
-       (animated-modal "property-value-search" (property-value-search id) true)
-
-       (= :zotero action)
-       (animated-modal "zotero-search" (zotero/zotero-search id) false)
-
-       :else
-       nil)]))
+    (shui-editor-popups id format action nil)))
 
 
 (defn- editor-on-hide
 (defn- editor-on-hide
   [state value* type e]
   [state value* type e]
@@ -916,9 +750,5 @@
     [:div.editor-inner.flex.flex-1 {:class (if block "block-editor" "non-block-editor")}
     [:div.editor-inner.flex.flex-1 {:class (if block "block-editor" "non-block-editor")}
 
 
      (ui/ls-textarea opts)
      (ui/ls-textarea opts)
-
      (mock-textarea content)
      (mock-textarea content)
-     (modals id format)
-
-     (when format
-       (image-uploader id format))]))
+     (command-popups id format)]))

+ 3 - 3
src/main/frontend/components/editor.css

@@ -73,7 +73,7 @@ pre {
 
 
 .ui__popover-content, .ui__dropdown-menu-content {
 .ui__popover-content, .ui__dropdown-menu-content {
   &[data-editor-popup-ref] {
   &[data-editor-popup-ref] {
-    @apply p-1 w-72;
+    @apply p-1.5 w-72;
 
 
     &[data-side=top] {
     &[data-side=top] {
       position: relative;
       position: relative;
@@ -82,7 +82,7 @@ pre {
   }
   }
 
 
   &[data-editor-popup-ref=commands] {
   &[data-editor-popup-ref=commands] {
-    @apply px-1 py-1 w-72;
+    @apply w-72;
 
 
     &[data-side=top] {
     &[data-side=top] {
       max-height: min(calc(var(--radix-popover-content-available-height) - 60px), 460px);
       max-height: min(calc(var(--radix-popover-content-available-height) - 60px), 460px);
@@ -96,7 +96,7 @@ pre {
   &[data-editor-popup-ref=page-search],
   &[data-editor-popup-ref=page-search],
   &[data-editor-popup-ref=block-search],
   &[data-editor-popup-ref=block-search],
   &[data-editor-popup-ref=page-search-hashtag] {
   &[data-editor-popup-ref=page-search-hashtag] {
-    @apply px-1 py-1 w-full sm:w-128;
+    @apply w-full sm:w-128;
   }
   }
 
 
   &[data-editor-popup-ref=datepicker] {
   &[data-editor-popup-ref=datepicker] {

+ 1 - 1
src/main/frontend/components/file_based/block.cljs

@@ -40,7 +40,7 @@
     (when class
     (when class
       (ui/checkbox {:class class
       (ui/checkbox {:class class
                     :style {:margin-right 5}
                     :style {:margin-right 5}
-                    :value checked?
+                    :checked checked?
                     :on-pointer-down (fn [e]
                     :on-pointer-down (fn [e]
                                        (util/stop-propagation e))
                                        (util/stop-propagation e))
                     :on-change (fn [_e]
                     :on-change (fn [_e]

+ 91 - 12
src/main/frontend/components/objects.cljs

@@ -1,5 +1,5 @@
 (ns frontend.components.objects
 (ns frontend.components.objects
-  "Tagged objects"
+  "Provides table views for class objects and property related objects"
   (:require [frontend.components.views :as views]
   (:require [frontend.components.views :as views]
             [frontend.db :as db]
             [frontend.db :as db]
             [logseq.db :as ldb]
             [logseq.db :as ldb]
@@ -15,29 +15,29 @@
             [frontend.modules.outliner.ui :as ui-outliner-tx]
             [frontend.modules.outliner.ui :as ui-outliner-tx]
             [frontend.modules.outliner.op :as outliner-op]))
             [frontend.modules.outliner.op :as outliner-op]))
 
 
-(defn- get-all-objects
+(defn- get-class-objects
   [class]
   [class]
   (->> (db-model/get-class-objects (state/get-current-repo) (:db/id class))
   (->> (db-model/get-class-objects (state/get-current-repo) (:db/id class))
        (map (fn [row] (assoc row :id (:db/id row))))))
        (map (fn [row] (assoc row :id (:db/id row))))))
 
 
-(defn- add-new-object!
+(defn- add-new-class-object!
   [class set-data!]
   [class set-data!]
   (p/let [block (editor-handler/api-insert-new-block! ""
   (p/let [block (editor-handler/api-insert-new-block! ""
                                                       {:page (:block/uuid class)
                                                       {:page (:block/uuid class)
                                                        :properties {:block/tags (:db/id class)}
                                                        :properties {:block/tags (:db/id class)}
                                                        :edit-block? false})
                                                        :edit-block? false})
-          _ (set-data! (get-all-objects class))]
+          _ (set-data! (get-class-objects class))]
     (editor-handler/edit-block! (db/entity [:block/uuid (:block/uuid block)]) 0 :unknown-container)))
     (editor-handler/edit-block! (db/entity [:block/uuid (:block/uuid block)]) 0 :unknown-container)))
 
 
 (defn- get-views
 (defn- get-views
-  [class]
-  (let [class (db/entity (:db/id class))]
+  [ent]
+  (let [class (db/entity (:db/id ent))]
     (-> (filter (fn [b]
     (-> (filter (fn [b]
                  (= (:db/ident class) (:logseq.property/view-for b)))
                  (= (:db/ident class) (:logseq.property/view-for b)))
                (:block/_parent class))
                (:block/_parent class))
        (ldb/sort-by-order))))
        (ldb/sort-by-order))))
 
 
-(rum/defc objects-inner < rum/static
+(rum/defc class-objects-inner < rum/static
   [config class objects properties]
   [config class objects properties]
   (let [[loading? set-loading?] (rum/use-state nil)
   (let [[loading? set-loading?] (rum/use-state nil)
         [view-entity set-view-entity!] (rum/use-state nil)
         [view-entity set-view-entity!] (rum/use-state nil)
@@ -57,7 +57,7 @@
          (when-let [view (first views)]
          (when-let [view (first views)]
            (set-view-entity! view))
            (set-view-entity! view))
          (p/let [_result (db-async/<get-tag-objects (state/get-current-repo) (:db/id class))]
          (p/let [_result (db-async/<get-tag-objects (state/get-current-repo) (:db/id class))]
-           (set-data! (get-all-objects class))
+           (set-data! (get-class-objects class))
            (set-loading? false))))
            (set-loading? false))))
      [])
      [])
 
 
@@ -65,7 +65,7 @@
       (views/view view-entity {:data data
       (views/view view-entity {:data data
                                :set-data! set-data!
                                :set-data! set-data!
                                :columns columns
                                :columns columns
-                               :add-new-object! #(add-new-object! class set-data!)
+                               :add-new-object! #(add-new-class-object! class set-data!)
                                :create-view! (fn []
                                :create-view! (fn []
                                                (p/let [result (editor-handler/api-insert-new-block! "" {:page (:block/uuid class)
                                                (p/let [result (editor-handler/api-insert-new-block! "" {:page (:block/uuid class)
                                                                                                         :properties {:logseq.property/view-for (:db/ident class)}})]
                                                                                                         :properties {:logseq.property/view-for (:db/ident class)}})]
@@ -89,11 +89,11 @@
                                                            tx-data (map (fn [pid] [:db/retract pid :block/tags (:db/id class)]) page-ids)]
                                                            tx-data (map (fn [pid] [:db/retract pid :block/tags (:db/id class)]) page-ids)]
                                                        (when (seq tx-data)
                                                        (when (seq tx-data)
                                                          (outliner-op/transact! tx-data {:outliner-op :save-block}))))
                                                          (outliner-op/transact! tx-data {:outliner-op :save-block}))))
-                                                    (set-data! (get-all-objects class))
+                                                    (set-data! (get-class-objects class))
                                                     (when-let [f (get-in table [:data-fns :set-row-selection!])]
                                                     (when-let [f (get-in table [:data-fns :set-row-selection!])]
                                                       (f {})))))}))))
                                                       (f {})))))}))))
 
 
-(rum/defcs objects < rum/reactive db-mixins/query mixins/container-id
+(rum/defcs class-objects < rum/reactive db-mixins/query mixins/container-id
   [state class]
   [state class]
   (when class
   (when class
     (let [class (db/sub-block (:db/id class))
     (let [class (db/sub-block (:db/id class))
@@ -105,4 +105,83 @@
           objects (->> (db-model/sub-class-objects repo (:db/id class))
           objects (->> (db-model/sub-class-objects repo (:db/id class))
                        (map (fn [row] (assoc row :id (:db/id row)))))]
                        (map (fn [row] (assoc row :id (:db/id row)))))]
       [:div.ml-2
       [:div.ml-2
-       (objects-inner config class objects properties)])))
+       (class-objects-inner config class objects properties)])))
+
+(defn- get-property-related-objects [repo property]
+  (->> (db-model/get-property-related-objects repo (:db/id property))
+       (map (fn [row] (assoc row :id (:db/id row))))))
+
+(defn- add-new-property-object!
+  [property set-data!]
+  (p/let [block (editor-handler/api-insert-new-block! ""
+                                                      {:page (:block/uuid property)
+                                                       :properties {(:db/ident property) (:db/id (db/entity :logseq.property/empty-placeholder))}
+                                                       :edit-block? false})
+          _ (set-data! (get-property-related-objects (state/get-current-repo) property))]
+    (editor-handler/edit-block! (db/entity [:block/uuid (:block/uuid block)]) 0 :unknown-container)))
+
+(rum/defc property-related-objects-inner < rum/static
+  [config property objects properties]
+  (let [[loading? set-loading?] (rum/use-state nil)
+        [view-entity set-view-entity!] (rum/use-state nil)
+        [data set-data!] (rum/use-state objects)
+        columns (views/build-columns config properties)]
+
+    (rum/use-effect!
+     (fn []
+       (set-data! objects))
+     [objects])
+
+    (rum/use-effect!
+     (fn []
+       (set-loading? true)
+       (p/let [_result (db-async/<get-views (state/get-current-repo) (:db/id property))
+               views (get-views property)]
+         (when-let [view (first views)]
+           (set-view-entity! view))
+         (p/let [result (db-async/<get-property-objects (state/get-current-repo) (:db/ident property))]
+           (set-data! (mapv #(assoc % :id (:db/id %)) result))
+           (set-loading? false))))
+     [])
+
+    (when (false? loading?)
+      (views/view view-entity {:data data
+                               :set-data! set-data!
+                               :columns columns
+                               :add-new-object! #(add-new-property-object! property set-data!)
+                               :create-view! (fn []
+                                               (p/let [result (editor-handler/api-insert-new-block! "" {:page (:block/uuid property)
+                                                                                                        :properties {:logseq.property/view-for (:db/ident property)}})]
+                                                 (let [view (db/entity [:block/uuid (:block/uuid result)])]
+                                                   (set-view-entity! view)
+                                                   view)))
+                               ;; TODO: Add support for adding column
+                               :show-add-property? false
+                               :on-delete-rows (fn [table selected-rows]
+                                                 (let [pages (filter ldb/page? selected-rows)
+                                                       blocks (remove ldb/page? selected-rows)]
+                                                   (p/do!
+                                                    (ui-outliner-tx/transact!
+                                                     {:outliner-op :delete-blocks}
+                                                     (when (seq blocks)
+                                                       (outliner-op/delete-blocks! blocks nil))
+                                                     (let [page-ids (map :db/id pages)
+                                                           tx-data (map (fn [pid] [:db/retract pid (:db/ident property)]) page-ids)]
+                                                       (when (seq tx-data)
+                                                         (outliner-op/transact! tx-data {:outliner-op :save-block}))))
+                                                    (set-data! (get-property-related-objects (state/get-current-repo) property))
+                                                    (when-let [f (get-in table [:data-fns :set-row-selection!])]
+                                                      (f {})))))}))))
+
+;; Show all nodes containing the given property
+(rum/defcs property-related-objects < rum/reactive db-mixins/query mixins/container-id
+  [state property]
+  (when property
+    (let [property' (db/sub-block (:db/id property))
+          config {:container-id (:container-id state)}
+          ;; Show tags to help differentiate property rows
+          properties [property' (db/entity :block/tags)]
+          repo (state/get-current-repo)
+          objects (get-property-related-objects repo property)]
+      [:div.ml-2
+       (property-related-objects-inner config property' objects properties)])))

+ 7 - 3
src/main/frontend/components/page.cljs

@@ -561,9 +561,13 @@
 
 
             (when (and db-based? (ldb/class? page))
             (when (and db-based? (ldb/class? page))
               [:div.mt-8
               [:div.mt-8
-               (objects/objects page)])
+               (objects/class-objects page)])
 
 
-            (when-not (and db-based? (ldb/class? page))
+            (when (and db-based? (ldb/property? page))
+              [:div.mt-8
+               (objects/property-related-objects page)])
+
+            (when-not (and db-based? (or (ldb/class? page) (ldb/property? page)))
               [:div
               [:div
                (when (and block? (not sidebar?) (not whiteboard?))
                (when (and block? (not sidebar?) (not whiteboard?))
                  (let [config (merge config {:id "block-parent"
                  (let [config (merge config {:id "block-parent"
@@ -571,7 +575,7 @@
                    [:div.mb-4
                    [:div.mb-4
                     (component-block/breadcrumb config repo block-id {:level-limit 3})]))
                     (component-block/breadcrumb config repo block-id {:level-limit 3})]))
 
 
-             ;; blocks
+               ;; blocks
                (page-blocks-cp repo page (merge option {:sidebar? sidebar?
                (page-blocks-cp repo page (merge option {:sidebar? sidebar?
                                                         :whiteboard? whiteboard?}))])])
                                                         :whiteboard? whiteboard?}))])])
 
 

+ 16 - 4
src/main/frontend/components/property.cljs

@@ -238,6 +238,7 @@
   db-mixins/query
   db-mixins/query
   (rum/local nil ::property-name)
   (rum/local nil ::property-name)
   (rum/local nil ::property-schema)
   (rum/local nil ::property-schema)
+  (rum/local nil ::property-description)
   {:init (fn [state]
   {:init (fn [state]
            (let [*values (atom :loading)]
            (let [*values (atom :loading)]
              (p/let [result (db-async/<get-block-property-values (state/get-current-repo)
              (p/let [result (db-async/<get-block-property-values (state/get-current-repo)
@@ -248,6 +249,7 @@
                  (let [[property _opts] (:rum/args state)]
                  (let [[property _opts] (:rum/args state)]
                    (reset! (::property-name state) (:block/title property))
                    (reset! (::property-name state) (:block/title property))
                    (reset! (::property-schema state) (:block/schema property))
                    (reset! (::property-schema state) (:block/schema property))
+                   (reset! (::property-description state) (db-property/property-value-content (:logseq.property/description property)))
                    (state/set-state! :editor/property-configure? true)
                    (state/set-state! :editor/property-configure? true)
                    state))
                    state))
    :will-unmount (fn [state]
    :will-unmount (fn [state]
@@ -260,6 +262,7 @@
     (when-not (= :loading values)
     (when-not (= :loading values)
       (let [*property-name (::property-name state)
       (let [*property-name (::property-name state)
             *property-schema (::property-schema state)
             *property-schema (::property-schema state)
+            *property-description (::property-description state)
             property (db/sub-block (:db/id property))
             property (db/sub-block (:db/id property))
             built-in? (ldb/built-in? property)
             built-in? (ldb/built-in? property)
             disabled? (or built-in? config/publishing?)
             disabled? (or built-in? config/publishing?)
@@ -391,15 +394,24 @@
                                     (swap! *property-schema assoc :hide? (not hide?))
                                     (swap! *property-schema assoc :hide? (not hide?))
                                     (save-property-fn))})])
                                     (save-property-fn))})])
 
 
-          (let [description (or (:description @*property-schema) "")]
+          (let [description (or @*property-description "")]
             [:div.grid.grid-cols-5.gap-1.items-start.leading-8
             [:div.grid.grid-cols-5.gap-1.items-start.leading-8
              [:label.col-span-2 "Description:"]
              [:label.col-span-2 "Description:"]
              [:div.col-span-3
              [:div.col-span-3
               [:div.mt-1
               [:div.mt-1
                (shui/textarea
                (shui/textarea
                 {:on-change (fn [e]
                 {:on-change (fn [e]
-                              (swap! *property-schema assoc :description (util/evalue e)))
-                 :on-blur save-property-fn
+                              (reset! *property-description (util/evalue e)))
+                 :on-blur (fn []
+                            (if-let [ent (:logseq.property/description property)]
+                              (db/transact! (state/get-current-repo)
+                                            [(outliner-core/block-with-updated-at
+                                              {:db/id (:db/id ent) :block/title @*property-description})]
+                                            {:outliner-op :save-block})
+                              (db-property-handler/set-block-property!
+                               (:db/id property)
+                               :logseq.property/description
+                               @*property-description)))
                  :disabled disabled?
                  :disabled disabled?
                  :default-value description})]]])]]))))
                  :default-value description})]]])]]))))
 
 
@@ -716,7 +728,7 @@
           [:div.flex.flex-1
           [:div.flex.flex-1
            (if (and (:class-schema? opts) (:page-configure? opts))
            (if (and (:class-schema? opts) (:page-configure? opts))
              [:div.property-description.text-sm.opacity-70
              [:div.property-description.text-sm.opacity-70
-              (inline-text {} :markdown (get-in property [:block/schema :description]))]
+              (inline-text {} :markdown (db-property/property-value-content (:logseq.property/description property)))]
              [:div.property-value.flex.flex-1
              [:div.property-value.flex.flex-1
               (pv/property-value block property v opts)])]]]))))
               (pv/property-value block property v opts)])]]]))))
 
 

+ 1 - 1
src/main/frontend/components/property/closed_value.cljs

@@ -63,7 +63,7 @@
            (let [block (second (:rum/args state))
            (let [block (second (:rum/args state))
                  value (or (str (db-property/closed-value-content block)) "")
                  value (or (str (db-property/closed-value-content block)) "")
                  icon (:logseq.property/icon block)
                  icon (:logseq.property/icon block)
-                 description (or (get-in block [:block/schema :description]) "")]
+                 description (or (db-property/property-value-content (:logseq.property/description block)) "")]
              (assoc state
              (assoc state
                     ::value (atom value)
                     ::value (atom value)
                     ::icon (atom icon)
                     ::icon (atom icon)

+ 16 - 8
src/main/frontend/components/property/value.cljs

@@ -70,14 +70,16 @@
           (if (and (= :default (get-in property [:block/schema :type]))
           (if (and (= :default (get-in property [:block/schema :type]))
                    (not (db-property/many? property)))
                    (not (db-property/many? property)))
             (p/let [existing-value (get block (:db/ident property))
             (p/let [existing-value (get block (:db/ident property))
-                    new-block-id (when-not existing-value (db/new-block-id))
-                    _ (when-not existing-value
+                    existing-value? (and (some? existing-value)
+                                         (not= (:db/ident existing-value) :logseq.property/empty-placeholder))
+                    new-block-id (when-not existing-value? (db/new-block-id))
+                    _ (when-not existing-value?
                         (db-property-handler/create-property-text-block!
                         (db-property-handler/create-property-text-block!
                          (:db/id block)
                          (:db/id block)
                          (:db/id property)
                          (:db/id property)
                          value
                          value
                          {:new-block-id new-block-id}))]
                          {:new-block-id new-block-id}))]
-              (or existing-value (db/entity [:block/uuid new-block-id])))
+              (if existing-value? existing-value (db/entity [:block/uuid new-block-id])))
             (p/let [new-block-id (db/new-block-id)
             (p/let [new-block-id (db/new-block-id)
                     _ (db-property-handler/create-property-text-block!
                     _ (db-property-handler/create-property-text-block!
                        (:db/id block)
                        (:db/id block)
@@ -349,7 +351,8 @@
            (let [result (rum/react *result)]
            (let [result (rum/react *result)]
              (if (empty? result)
              (if (empty? result)
                (let [v (get block (:db/ident property))]
                (let [v (get block (:db/ident property))]
-                 (if (every? de/entity? v) v [v]))
+                 (remove #(= :logseq.property/empty-placeholder (:db/ident %))
+                         (if (every? de/entity? v) v [v])))
                (remove (fn [node]
                (remove (fn [node]
                          (or (= (:db/id block) (:db/id node))
                          (or (= (:db/id block) (:db/id node))
                               ;; A page's alias can't be itself
                               ;; A page's alias can't be itself
@@ -535,8 +538,11 @@
   [block property value-block opts]
   [block property value-block opts]
   (let [multiple-values? (db-property/many? property)
   (let [multiple-values? (db-property/many? property)
         block-container (state/get-component :block/container)
         block-container (state/get-component :block/container)
-        blocks-container (state/get-component :block/blocks-container)]
-    (if value-block
+        blocks-container (state/get-component :block/blocks-container)
+        value-block (if (and (coll? value-block) (every? de/entity? value-block))
+                      (set (remove #(= (:db/ident %) :logseq.property/empty-placeholder) value-block))
+                      value-block)]
+    (if (seq value-block)
       [:div.property-block-container.content.w-full
       [:div.property-block-container.content.w-full
        (let [config {:id (str (if multiple-values?
        (let [config {:id (str (if multiple-values?
                                 (:block/uuid block)
                                 (:block/uuid block)
@@ -818,7 +824,9 @@
               (when date?
               (when date?
                 [(property-value-date-picker block property nil {:toggle-fn toggle-fn})]))
                 [(property-value-date-picker block property nil {:toggle-fn toggle-fn})]))
              (when-not editing?
              (when-not editing?
-               (property-empty-text-value))))]))))
+               (if date?
+                 [(property-empty-text-value) (property-value-date-picker block property nil {:toggle-fn toggle-fn})]
+                 (property-empty-text-value)))))]))))
 
 
 (rum/defc multiple-values < rum/reactive db-mixins/query
 (rum/defc multiple-values < rum/reactive db-mixins/query
   [block property opts schema]
   [block property opts schema]
@@ -845,7 +853,6 @@
          schema (:block/schema property)
          schema (:block/schema property)
          type (some-> schema (get :type :default))
          type (some-> schema (get :type :default))
          multiple-values? (db-property/many? property)
          multiple-values? (db-property/many? property)
-         empty-value? (= :logseq.property/empty-placeholder v)
          v (cond
          v (cond
              (and multiple-values? (or (set? v) (and (coll? v) (empty? v)) (nil? v)))
              (and multiple-values? (or (set? v) (and (coll? v) (empty? v)) (nil? v)))
              v
              v
@@ -855,6 +862,7 @@
              (first v)
              (first v)
              :else
              :else
              v)
              v)
+         empty-value? (= :logseq.property/empty-placeholder (:db/ident (first v)))
          closed-values? (seq (:property/closed-values property))
          closed-values? (seq (:property/closed-values property))
          value-cp [:div.property-value-inner
          value-cp [:div.property-value-inner
                    {:data-type type
                    {:data-type type

+ 4 - 17
src/main/frontend/components/repo.css

@@ -16,27 +16,15 @@
 
 
 .ui__dropdown-menu-content {
 .ui__dropdown-menu-content {
   &.repos-list {
   &.repos-list {
-    @apply px-2 pb-[210px] relative overflow-hidden;
-    @apply min-w-[280px] sm:max-w-[320px] max-h-[66vh];
-
-    &.no-repos {
-      @apply pb-[180px];
-    }
-
-    &[data-mode=db] {
-      @apply pb-[114px];
-
-      &.no-repos {
-        @apply pb-[109px];
-      }
-    }
+    @apply px-2 relative overflow-hidden;
+    @apply min-w-[280px] sm:max-w-[320px];
 
 
     .ui__dropdown-menu-item {
     .ui__dropdown-menu-item {
       @apply overflow-hidden overflow-ellipsis;
       @apply overflow-hidden overflow-ellipsis;
     }
     }
 
 
     .cp__repos-list-wrap {
     .cp__repos-list-wrap {
-      @apply max-h-96 overflow-scroll m-[-8px] px-2 pb-6;
+      @apply max-h-80 overflow-scroll mx-[-8px] px-2 pb-2;
     }
     }
   }
   }
 }
 }
@@ -64,8 +52,7 @@
 }
 }
 
 
 .cp__repos-quick-actions {
 .cp__repos-quick-actions {
-  @apply absolute left-[1px] right-[1px] bottom-[1px] bg-gray-01 px-2 py-3 border-t
-  flex flex-col rounded-b overflow-hidden;
+  @apply -mx-2 bg-gray-01 px-2 pb-1.5 pt-3 border-t flex flex-col rounded-b overflow-hidden;
 
 
   .ui__button {
   .ui__button {
     @apply w-full !py-4 !justify-start opacity-70 font-medium hover:opacity-90
     @apply w-full !py-4 !justify-start opacity-70 font-medium hover:opacity-90

+ 9 - 9
src/main/frontend/components/views.cljs

@@ -95,7 +95,7 @@
   [block property]
   [block property]
   (let [type (get-in property [:block/schema :type])
   (let [type (get-in property [:block/schema :type])
         many? (= :db.cardinality/many (get property :db/cardinality))
         many? (= :db.cardinality/many (get property :db/cardinality))
-        ref-types (into db-property-type/value-ref-property-types #{:entity})
+        ref-types (into db-property-type/ref-property-types #{:entity})
         number-type? (= :number type)
         number-type? (= :number type)
         v (get block (:db/ident property))
         v (get block (:db/ident property))
         v' (if many? v [v])
         v' (if many? v [v])
@@ -871,13 +871,13 @@
      (fn [sorting]
      (fn [sorting]
        (set-sorting! sorting)
        (set-sorting! sorting)
        (p/let [entity (or entity (create-view!))]
        (p/let [entity (or entity (create-view!))]
-         (property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-sorting sorting)))
+         (property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/sorting sorting)))
      :set-filters!
      :set-filters!
      (fn [filters]
      (fn [filters]
        (let [filters (table-filters->persist-state filters)]
        (let [filters (table-filters->persist-state filters)]
          (set-filters! filters)
          (set-filters! filters)
          (p/let [entity (or entity (create-view!))]
          (p/let [entity (or entity (create-view!))]
-           (property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-filters filters))))
+           (property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/filters filters))))
      :set-visible-columns!
      :set-visible-columns!
      (fn [columns]
      (fn [columns]
        (let [hidden-columns (vec (keep (fn [[column visible?]]
        (let [hidden-columns (vec (keep (fn [[column visible?]]
@@ -885,24 +885,24 @@
                                            column)) columns))]
                                            column)) columns))]
          (set-visible-columns! columns)
          (set-visible-columns! columns)
          (p/let [entity (or entity (create-view!))]
          (p/let [entity (or entity (create-view!))]
-           (property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-hidden-columns hidden-columns))))
+           (property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/hidden-columns hidden-columns))))
      :set-ordered-columns!
      :set-ordered-columns!
      (fn [ordered-columns]
      (fn [ordered-columns]
        (let [ids (vec (remove #{:select} ordered-columns))]
        (let [ids (vec (remove #{:select} ordered-columns))]
          (set-ordered-columns! ordered-columns)
          (set-ordered-columns! ordered-columns)
          (p/let [entity (or entity (create-view!))]
          (p/let [entity (or entity (create-view!))]
-           (property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-ordered-columns ids))))}))
+           (property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/ordered-columns ids))))}))
 
 
 (rum/defc view-inner < rum/static
 (rum/defc view-inner < rum/static
   [view-entity {:keys [data set-data! columns add-new-object! create-view! title-key] :as option}]
   [view-entity {:keys [data set-data! columns add-new-object! create-view! title-key] :as option}]
   (let [[input set-input!] (rum/use-state "")
   (let [[input set-input!] (rum/use-state "")
-        sorting (:logseq.property/table-sorting view-entity)
+        sorting (:logseq.property.table/sorting view-entity)
         [sorting set-sorting!] (rum/use-state (or sorting [{:id :block/updated-at, :asc? false}]))
         [sorting set-sorting!] (rum/use-state (or sorting [{:id :block/updated-at, :asc? false}]))
-        filters (:logseq.property/table-filters view-entity)
+        filters (:logseq.property.table/filters view-entity)
         [filters set-filters!] (rum/use-state (or filters []))
         [filters set-filters!] (rum/use-state (or filters []))
-        hidden-columns (:logseq.property/table-hidden-columns view-entity)
+        hidden-columns (:logseq.property.table/hidden-columns view-entity)
         [visible-columns set-visible-columns!] (rum/use-state (zipmap hidden-columns (repeat false)))
         [visible-columns set-visible-columns!] (rum/use-state (zipmap hidden-columns (repeat false)))
-        ordered-columns (vec (concat [:select] (:logseq.property/table-ordered-columns view-entity)))
+        ordered-columns (vec (concat [:select] (:logseq.property.table/ordered-columns view-entity)))
         [ordered-columns set-ordered-columns!] (rum/use-state ordered-columns)
         [ordered-columns set-ordered-columns!] (rum/use-state ordered-columns)
         {:keys [set-sorting! set-filters! set-visible-columns! set-ordered-columns!]}
         {:keys [set-sorting! set-filters! set-visible-columns! set-ordered-columns!]}
         (db-set-table-state! view-entity {:set-sorting! set-sorting!
         (db-set-table-state! view-entity {:set-sorting! set-sorting!

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

@@ -253,6 +253,15 @@
         [?page :block/name]]
         [?page :block/name]]
       tag-id))
       tag-id))
 
 
+(defn <get-property-objects
+  [graph property-ident]
+  (<q graph {:transact-db? true}
+      '[:find [(pull ?b [*]) ...]
+        :in $ ?property-ident
+        :where
+        [?b ?property-ident]]
+      property-ident))
+
 (defn <get-tag-objects
 (defn <get-tag-objects
   [graph class-id]
   [graph class-id]
   (let [class-children (db-model/get-class-children graph class-id)
   (let [class-children (db-model/get-class-children graph class-id)

+ 9 - 0
src/main/frontend/db/model.cljs

@@ -797,6 +797,15 @@ independent of format as format specific heading characters are stripped"
                  nil)
                  nil)
         react)))
         react)))
 
 
+(defn get-property-related-objects
+  [repo property-id]
+  (when-let [property (db-utils/entity repo property-id)]
+    (->> (d/q '[:find [?objects ...]
+                :in $ ?prop
+                :where [?objects ?prop]]
+              (conn/get-db repo)
+              (:db/ident property))
+         (map #(db-utils/entity repo %)))))
 
 
 (defn get-all-namespace-relation
 (defn get-all-namespace-relation
   [repo]
   [repo]

+ 1 - 1
src/main/frontend/db/query_dsl.cljs

@@ -268,7 +268,7 @@
             (subs v' 1)
             (subs v' 1)
             (or (page-ref/get-page-name v') v'))
             (or (page-ref/get-page-name v') v'))
           ;; Convert number pages to string
           ;; Convert number pages to string
-          (and (double? v) (= :page (get-in (db-utils/entity k) [:block/schema :type])))
+          (and (double? v) (= :node (get-in (db-utils/entity k) [:block/schema :type])))
           (str v)
           (str v)
           :else
           :else
           v')))
           v')))

+ 1 - 1
src/main/frontend/handler/editor.cljs

@@ -1535,7 +1535,7 @@
       (path/get-relative-path current-file-fpath file-path))
       (path/get-relative-path current-file-fpath file-path))
     file-path))
     file-path))
 
 
-(defn upload-asset
+(defn upload-asset!
   "Paste asset and insert link to current editing block"
   "Paste asset and insert link to current editing block"
   [id ^js files format uploading? drop-or-paste?]
   [id ^js files format uploading? drop-or-paste?]
   (let [repo (state/get-current-repo)]
   (let [repo (state/get-current-repo)]

+ 0 - 14
src/main/frontend/handler/events.cljs

@@ -56,7 +56,6 @@
             [frontend.handler.user :as user-handler]
             [frontend.handler.user :as user-handler]
             [frontend.handler.property.util :as pu]
             [frontend.handler.property.util :as pu]
             [frontend.handler.db-based.property.util :as db-pu]
             [frontend.handler.db-based.property.util :as db-pu]
-            [frontend.handler.file-based.property.util :as property-util]
             [frontend.handler.property :as property-handler]
             [frontend.handler.property :as property-handler]
             [frontend.handler.file-based.nfs :as nfs-handler]
             [frontend.handler.file-based.nfs :as nfs-handler]
             [frontend.handler.code :as code-handler]
             [frontend.handler.code :as code-handler]
@@ -846,19 +845,6 @@
 (defmethod handle :graph/save-db-to-disk [[_ _opts]]
 (defmethod handle :graph/save-db-to-disk [[_ _opts]]
   (persist-db/export-current-graph! {:succ-notification? true}))
   (persist-db/export-current-graph! {:succ-notification? true}))
 
 
-(defmethod handle :search/transact-data [[_ repo data]]
-  (let [file-based? (config/local-file-based-graph? repo)
-        data' (cond-> data
-                file-based?
-                ;; remove built-in properties from content
-                (update :blocks-to-add
-                  (fn [blocks]
-                    (map #(update % :content
-                            (fn [content]
-                              (property-util/remove-built-in-properties (get % :format :markdown) content)))
-                      blocks))))]
-    (search/transact-blocks! repo data')))
-
 (defmethod handle :class/configure [[_ page]]
 (defmethod handle :class/configure [[_ page]]
   (shui/dialog-open!
   (shui/dialog-open!
     #(vector :<>
     #(vector :<>

+ 4 - 2
src/main/frontend/handler/page.cljs

@@ -44,7 +44,8 @@
             [frontend.modules.outliner.ui :as ui-outliner-tx]
             [frontend.modules.outliner.ui :as ui-outliner-tx]
             [frontend.modules.outliner.op :as outliner-op]
             [frontend.modules.outliner.op :as outliner-op]
             [frontend.handler.property.util :as pu]
             [frontend.handler.property.util :as pu]
-            [datascript.impl.entity :as de]))
+            [datascript.impl.entity :as de]
+            [logseq.db.frontend.property :as db-property]))
 
 
 (def <create! page-common-handler/<create!)
 (def <create! page-common-handler/<create!)
 (def <delete! page-common-handler/<delete!)
 (def <delete! page-common-handler/<delete!)
@@ -495,4 +496,5 @@
   (property-handler/set-block-property! (state/get-current-repo)
   (property-handler/set-block-property! (state/get-current-repo)
                                         (:block/uuid page-entity)
                                         (:block/uuid page-entity)
                                         :logseq.property/hide-properties?
                                         :logseq.property/hide-properties?
-                                        (not (:logseq.property/hide-properties? page-entity))))
+                                        (not
+                                         (db-property/property-value-content (:logseq.property/hide-properties? page-entity)))))

+ 1 - 1
src/main/frontend/handler/paste.cljs

@@ -220,7 +220,7 @@
           files (.-files clipboard-data)]
           files (.-files clipboard-data)]
       (when-let [file (first files)]
       (when-let [file (first files)]
         (when-let [block (state/get-edit-block)]
         (when-let [block (state/get-edit-block)]
-          (editor-handler/upload-asset id #js[file] (:block/format block)
+          (editor-handler/upload-asset! id #js[file] (:block/format block)
                                        editor-handler/*asset-uploading? true)))
                                        editor-handler/*asset-uploading? true)))
       (util/stop e))))
       (util/stop e))))
 
 

+ 9 - 1
src/main/frontend/handler/plugin.cljs

@@ -252,10 +252,18 @@
 
 
     (js/window.apis.addListener channel listener)))
     (js/window.apis.addListener channel listener)))
 
 
+(defn- normalize-plugin-metadata
+  [metadata]
+  (cond-> metadata
+    (not (string? (:author metadata)))
+    (assoc :author (or (get-in metadata [:author :name]) ""))))
+
 (defn register-plugin
 (defn register-plugin
   [plugin-metadata]
   [plugin-metadata]
   (when-let [pid (keyword (:id plugin-metadata))]
   (when-let [pid (keyword (:id plugin-metadata))]
-    (swap! state/state update-in [:plugin/installed-plugins] assoc pid plugin-metadata)))
+    (some->> plugin-metadata
+      (normalize-plugin-metadata)
+      (swap! state/state update-in [:plugin/installed-plugins] assoc pid))))
 
 
 (defn host-mounted!
 (defn host-mounted!
   []
   []

+ 0 - 5
src/main/frontend/search.cljs

@@ -106,11 +106,6 @@
   (when-let [engine (get-engine repo)]
   (when-let [engine (get-engine repo)]
     (protocol/remove-db! engine)))
     (protocol/remove-db! engine)))
 
 
-(defn transact-blocks!
-  [repo data]
-  (when-let [engine (get-engine repo)]
-    (protocol/transact-blocks! engine data)))
-
 (defn get-unlinked-refs
 (defn get-unlinked-refs
   "Get matched result from search first, and then filter by worker db"
   "Get matched result from search first, and then filter by worker db"
   [eid]
   [eid]

+ 22 - 1
src/main/frontend/worker/db/migrate.cljs

@@ -43,6 +43,26 @@
   [{:db/id (:db/id (d/entity @conn :logseq.class/task))
   [{:db/id (:db/id (d/entity @conn :logseq.class/task))
     :db/ident :logseq.class/Task}])
     :db/ident :logseq.class/Task}])
 
 
+(defn- update-table-properties
+  [conn _search-db]
+  (let [old-new-props {:logseq.property/table-sorting :logseq.property.table/sorting
+                       :logseq.property/table-filters :logseq.property.table/filters
+                       :logseq.property/table-ordered-columns :logseq.property.table/ordered-columns
+                       :logseq.property/table-hidden-columns :logseq.property.table/hidden-columns}
+        props-tx (mapv (fn [[old new]]
+                         {:db/id (:db/id (d/entity @conn old))
+                          :db/ident new})
+                       old-new-props)]
+    ;; Property changes need to be in their own tx for subsequent uses of properties to take effect
+    (ldb/transact! conn props-tx {:db-migrate? true})
+
+    (mapcat (fn [[old new]]
+              (->> (d/q '[:find ?b ?prop-v :in $ ?prop :where [?b ?prop ?prop-v]] @conn old)
+                   (mapcat (fn [[id prop-value]]
+                             [[:db/retract id old]
+                              [:db/add id new prop-value]]))))
+            old-new-props)))
+
 (def schema-version->updates
 (def schema-version->updates
   [[3 {:properties [:logseq.property/table-sorting :logseq.property/table-filters
   [[3 {:properties [:logseq.property/table-sorting :logseq.property/table-filters
                     :logseq.property/table-hidden-columns :logseq.property/table-ordered-columns]
                     :logseq.property/table-hidden-columns :logseq.property/table-ordered-columns]
@@ -60,7 +80,8 @@
    [6 {:properties [:logseq.property.asset/remote-metadata]}]
    [6 {:properties [:logseq.property.asset/remote-metadata]}]
    [7 {:fix replace-original-name-content-with-title}]
    [7 {:fix replace-original-name-content-with-title}]
    [8 {:fix replace-object-and-page-type-with-node}]
    [8 {:fix replace-object-and-page-type-with-node}]
-   [9 {:fix update-task-ident}]])
+   [9 {:fix update-task-ident}]
+   [10 {:fix update-table-properties}]])
 
 
 (let [max-schema-version (apply max (map first schema-version->updates))]
 (let [max-schema-version (apply max (map first schema-version->updates))]
   (assert (<= db-schema/version max-schema-version))
   (assert (<= db-schema/version max-schema-version))

+ 7 - 6
src/main/frontend/worker/rtc/client.cljs

@@ -306,12 +306,13 @@
 
 
 (defn- rollback
 (defn- rollback
   [repo block-ops-map-coll]
   [repo block-ops-map-coll]
-  (let [ops (map (fn [m]
-                   (keep (fn [[k op]]
-                           (when (not= :block/uuid k)
-                             op))
-                         m))
-                 block-ops-map-coll)]
+  (let [ops (mapcat
+             (fn [m]
+               (keep (fn [[k op]]
+                       (when (not= :block/uuid k)
+                         op))
+                     m))
+             block-ops-map-coll)]
     (client-op/add-ops repo ops)
     (client-op/add-ops repo ops)
     nil))
     nil))
 
 

+ 1 - 1
src/main/frontend/worker/rtc/client_op.cljs

@@ -85,7 +85,7 @@
     (if (> t1 t2)
     (if (> t1 t2)
       (merge-update-ops update-op2 update-op1)
       (merge-update-ops update-op2 update-op1)
       (let [{av-coll1 :av-coll block-uuid :block-uuid} (last update-op1)
       (let [{av-coll1 :av-coll block-uuid :block-uuid} (last update-op1)
-            {av-coll2 :av-coll} (last update-op1)]
+            {av-coll2 :av-coll} (last update-op2)]
         [:update t2
         [:update t2
          {:block-uuid block-uuid
          {:block-uuid block-uuid
           :av-coll (concat av-coll1 av-coll2)}]))))
           :av-coll (concat av-coll1 av-coll2)}]))))

+ 2 - 2
src/test/frontend/db/db_based_model_test.cljs

@@ -26,7 +26,7 @@
 ;;         _ (test-helper/create-page! "page2" opts)
 ;;         _ (test-helper/create-page! "page2" opts)
 ;;         p1id (:block/uuid (db/get-page "page1"))
 ;;         p1id (:block/uuid (db/get-page "page1"))
 ;;         p2id (:block/uuid (db/get-page "page2"))]
 ;;         p2id (:block/uuid (db/get-page "page2"))]
-;;     (outliner-property/upsert-property! repo "property-1" {:type :page} {})
+;;     (outliner-property/upsert-property! repo "property-1" {:type :node} {})
 ;;     (outliner-property/set-block-property! repo fbid "property-1" p1id {})
 ;;     (outliner-property/set-block-property! repo fbid "property-1" p1id {})
 ;;     (outliner-property/set-block-property! repo sbid "property-1" p2id {})
 ;;     (outliner-property/set-block-property! repo sbid "property-1" p2id {})
 ;;     (is (= '("[[page1]]" "[[page2]]") (model/get-db-property-values repo "property-1")))))
 ;;     (is (= '("[[page1]]" "[[page2]]") (model/get-db-property-values repo "property-1")))))
@@ -63,7 +63,7 @@
         class1 (db/get-case-page "class1")
         class1 (db/get-case-page "class1")
         class2 (db/get-case-page "class2")
         class2 (db/get-case-page "class2")
         conn (db/get-db false)]
         conn (db/get-db false)]
-    (outliner-property/upsert-property! conn :user.property/property-1 {:type :page} {})
+    (outliner-property/upsert-property! conn :user.property/property-1 {:type :node} {})
     (outliner-property/class-add-property! conn (:db/id class1) :user.property/property-1)
     (outliner-property/class-add-property! conn (:db/id class1) :user.property/property-1)
     (outliner-property/class-add-property! conn (:db/id class2) :user.property/property-1)
     (outliner-property/class-add-property! conn (:db/id class2) :user.property/property-1)
     (let [property (db/entity :user.property/property-1)
     (let [property (db/entity :user.property/property-1)

+ 12 - 12
src/test/frontend/db/query_dsl_test.cljs

@@ -223,14 +223,14 @@ prop-d:: [[nada]]"}])
       "Page property queries ORed")
       "Page property queries ORed")
 
 
   (is (= ["page1" "page3"]
   (is (= ["page1" "page3"]
-           (map :block/name
-                (dsl-query "(and (page-property parent [[child page 1]]) (or (page-property foo baz) (page-property parent [[child page 2]])))"))))
+         (map :block/name
+              (dsl-query "(and (page-property parent [[child page 1]]) (or (page-property foo baz) (page-property parent [[child page 2]])))"))))
 
 
   (is (= ["page4"]
   (is (= ["page4"]
-           (map
-            :block/name
-            (dsl-query "(and (page-property parent [[child page 2]]) (not (page-property foo bar)))")))
-        "Page property queries nested NOT in second clause")
+         (map
+          :block/name
+          (dsl-query "(and (page-property parent [[child page 2]]) (not (page-property foo bar)))")))
+      "Page property queries nested NOT in second clause")
 
 
   (is (= ["page4"]
   (is (= ["page4"]
          (map
          (map
@@ -239,13 +239,13 @@ prop-d:: [[nada]]"}])
       "Page property queries nested NOT in first clause")
       "Page property queries nested NOT in first clause")
 
 
   (testing "boolean values"
   (testing "boolean values"
-      (is (= ["page1"]
-             (map :block/name (dsl-query "(page-property interesting true)")))
-          "Boolean true")
+    (is (= ["page1"]
+           (map :block/name (dsl-query "(page-property interesting true)")))
+        "Boolean true")
 
 
-      (is (= ["page2" "page3"]
-             (map :block/name (dsl-query "(page-property interesting false)")))
-          "Boolean false")))
+    (is (= #{"page2" "page3"}
+           (set (map :block/name (dsl-query "(page-property interesting false)"))))
+        "Boolean false")))
 
 
 (deftest page-property-queries
 (deftest page-property-queries
   (testing "page property tests with default config"
   (testing "page property tests with default config"

+ 1 - 1
src/test/frontend/handler/paste_test.cljs

@@ -241,7 +241,7 @@
       reset
       reset
       [state/preferred-pasting-file? (constantly true)
       [state/preferred-pasting-file? (constantly true)
        ;; paste-file-if-exists mocks below
        ;; paste-file-if-exists mocks below
-       editor-handler/upload-asset (fn [_id file & _]
+       editor-handler/upload-asset! (fn [_id file & _]
                                      (reset! pasted-file file))
                                      (reset! pasted-file file))
        util/stop (constantly nil)
        util/stop (constantly nil)
        state/get-edit-block (constantly {})]
        state/get-edit-block (constantly {})]

+ 22 - 18
src/test/logseq/api_test.cljs

@@ -12,28 +12,32 @@
 (deftest get-block
 (deftest get-block
   (with-redefs [state/get-current-repo (constantly test-helper/test-db)]
   (with-redefs [state/get-current-repo (constantly test-helper/test-db)]
     (db/transact! test-helper/test-db
     (db/transact! test-helper/test-db
-                  [{:db/id 10000
-                    :block/uuid #uuid "4406f839-6410-43b5-87db-25e9b8f54cc0"
-                    :block/title "1"}
-                   {:db/id 10001
-                    :block/uuid #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
-                    :block/title "2"}
-                   {:db/id 10002
-                    :block/uuid #uuid "adae3006-f03e-4814-a1f5-f17f15b86556"
-                    :block/parent 10001
-                    :block/title "3"}
-                   {:db/id 10003
-                    :block/uuid #uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d"
-                    :block/parent 10002
-                    :block/title "4"}])
+      [{:db/id 10000
+        :block/uuid #uuid "4406f839-6410-43b5-87db-25e9b8f54cc0"
+        :block/title "1"}
+       {:db/id 10001
+        :block/uuid #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
+        :block/title "2"}
+       {:db/id 10002
+        :block/uuid #uuid "adae3006-f03e-4814-a1f5-f17f15b86556"
+        :block/parent 10001
+        :block/title "3"}
+       {:db/id 10003
+        :block/uuid #uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d"
+        :block/parent 10002
+        :block/title "4"}])
 
 
     (is (= (:title (bean/->clj (api-block/get_block 10000 #js {}))) "1"))
     (is (= (:title (bean/->clj (api-block/get_block 10000 #js {}))) "1"))
     (is (= (:title (bean/->clj (api-block/get_block "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
     (is (= (:title (bean/->clj (api-block/get_block "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
     (is (= (:title (bean/->clj (api-block/get_block #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
     (is (= (:title (bean/->clj (api-block/get_block #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
     (is (= {:id 10001, :title "2", :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172", :children [["uuid" "adae3006-f03e-4814-a1f5-f17f15b86556"]]}
     (is (= {:id 10001, :title "2", :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172", :children [["uuid" "adae3006-f03e-4814-a1f5-f17f15b86556"]]}
-           (select-keys (js->clj (api-block/get_block 10001 #js {:includeChildren false}) :keywordize-keys true)
-                        [:id :title :uuid :children])))
-    (is (= {:title "2", :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172", :id 10001, :children [{:title "3", :parent {:id 10001}, :uuid "adae3006-f03e-4814-a1f5-f17f15b86556", :id 10002, :level 1, :children [{:title "4", :parent {:id 10002}, :uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d", :id 10003, :level 2, :children []}]}]}
-           (js->clj (api-block/get_block 10001 #js {:includeChildren true}) :keywordize-keys true)))))
+          (select-keys (js->clj (api-block/get_block 10001 #js {:includeChildren false}) :keywordize-keys true)
+            [:id :title :uuid :children])))
+    ;; NOTE: `content` key is to be compatible with old APIs
+    (is (= {:id 10001, :title "2", :content "2" :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
+            :children [{:id 10002 :title "3", :content "3"
+                        :parent {:id 10001}, :uuid "adae3006-f03e-4814-a1f5-f17f15b86556", :level 1,
+                        :children [{:id 10003, :title "4", :content "4" :parent {:id 10002}, :uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d", :level 2, :children []}]}]}
+          (js->clj (api-block/get_block 10001 #js {:includeChildren true}) :keywordize-keys true)))))
 
 
 #_(cljs.test/run-tests)
 #_(cljs.test/run-tests)

+ 4 - 4
yarn.lock

@@ -5070,10 +5070,10 @@ mkdirp@^1.0.3:
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
   integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
   integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
 
 
-mldoc@^1.5.8:
-  version "1.5.8"
-  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.8.tgz#5433950c9124f8917075bafa4f1ed886959504c5"
-  integrity sha512-wNUGgwdgB/5c3GTp2qRPzWD8CpeTmA/HDlGJjTJUo2WXJttiBaz8cHQh2OdAshiLdVxteqIaSTXSPFRf7z1YRw==
+mldoc@^1.5.9:
+  version "1.5.9"
+  resolved "https://registry.yarnpkg.com/mldoc/-/mldoc-1.5.9.tgz#43d740351c64285f0f4988ac9497922d54ae66fc"
+  integrity sha512-87FQ7hseS87tsk+VdpIigpu8LH+GwmbbFgpxgFwvnbH5oOjmIrc47laH4Dyggzqiy8/vMjDHkl7vsId0eXhCDQ==
   dependencies:
   dependencies:
     yargs "^12.0.2"
     yargs "^12.0.2"