Преглед на файлове

chore: move db graph property fns to db-based.property

Doing this revealed db graph fns were being called on file graphs for
every block and linked reference. Also removed property.handler fns
that were just wrapping a graph-specific fn as they were making handlers
less explicit and adding duplicate config/db-based-graph? checks
Gabriel Horner преди 2 години
родител
ревизия
be747bd728

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

@@ -50,8 +50,8 @@
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.whiteboard :as whiteboard-handler]
             [frontend.handler.export.common :as export-common-handler]
-            [frontend.handler.property :as property-handler]
             [frontend.handler.property.util :as pu]
+            [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.db-based.property.util :as db-pu]
             [frontend.mobile.util :as mobile-util]
             [frontend.modules.outliner.tree :as tree]
@@ -625,10 +625,10 @@
            :on-mouse-down
            (fn [e]
              (util/stop e)
-             (property-handler/delete-property-value! repo
-                                                      block
-                                                      (db-pu/get-built-in-property-uuid repo :tags)
-                                                      (:block/uuid page-entity)))}
+             (db-property-handler/delete-property-value! repo
+                                                         block
+                                                         (db-pu/get-built-in-property-uuid repo :tags)
+                                                         (:block/uuid page-entity)))}
           (ui/icon "x" {:size 15})]))]))
 
 (rum/defc page-preview-trigger
@@ -2314,7 +2314,7 @@
 
 (rum/defc block-closed-values-properties
   [block]
-  (let [closed-values-properties (property-handler/get-block-other-position-properties (:db/id block))]
+  (let [closed-values-properties (db-property-handler/get-block-other-position-properties (:db/id block))]
     (when (seq closed-values-properties)
       [:div.closed-values-properties.flex.flex-row.items-center.gap-1.select-none.h-full
        (for [pid closed-values-properties]
@@ -2483,7 +2483,7 @@
         repo (state/get-current-repo)
         db-based? (config/db-based-graph? repo)]
     [:div.flex.flex-1.flex-row.flex-wrap.gap-1.items-start
-     (block-closed-values-properties block)
+     (when db-based? (block-closed-values-properties block))
      (if (and edit? editor-box)
        [:div.editor-wrapper.flex.flex-1
         {:id editor-id}
@@ -2610,8 +2610,8 @@
                               level-limit 3}
                          :as opts}]
   (when block-id
-    (let [block-id (or (when block-id
-                         (some-> (property-handler/get-property-block-created-block [:block/uuid block-id])
+    (let [block-id (or (when (and block-id (config/db-based-graph? repo))
+                         (some-> (db-property-handler/get-property-block-created-block [:block/uuid block-id])
                                  db/entity
                                  :block/uuid))
                        block-id)

+ 8 - 8
src/main/frontend/components/page.cljs

@@ -13,8 +13,8 @@
             [frontend.components.property.value :as pv]
             [frontend.components.class :as class-component]
             [frontend.handler.property.util :as pu]
+            [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.db-based.property.util :as db-pu]
-            [frontend.handler.property :as property-handler]
             [frontend.components.svg :as svg]
             [frontend.config :as config]
             [frontend.context.i18n :refer [t]]
@@ -358,7 +358,7 @@
         (not class-or-property?)
         (when (and (not class?)
                    (not property?)
-                   (not (property-handler/block-has-viewable-properties? page)))
+                   (not (db-property-handler/block-has-viewable-properties? page)))
           (page-properties page page-opts))
 
         @*show-page-properties?
@@ -377,7 +377,7 @@
                                                       :inline-text component-block/inline-text)))])]
 
      (when (and class-or-property?
-                (not (property-handler/block-has-viewable-properties? page))
+                (not (db-property-handler/block-has-viewable-properties? page))
                 (not config/publishing?)
                 (empty? (:properties (:block/schema page))))
        [:a.fade-link.flex.flex-row.items-center.gap-1.text-sm
@@ -457,7 +457,7 @@
           (if (and (map? icon) db-based?)
             (property/icon icon {:on-chosen (fn [_e icon]
                                               (let [icon-property-id (db-pu/get-built-in-property-uuid :icon)]
-                                                (property-handler/update-property!
+                                                (db-property-handler/update-property!
                                                  repo
                                                  (:block/uuid page)
                                                  {:properties {icon-property-id icon}})))})
@@ -521,7 +521,7 @@
              (page-tags page tags-property *hover? *configuring?))
 
            (when (or (some #(contains? #{"class" "property"} %) (:block/type page))
-                     (not (property-handler/block-has-viewable-properties? page)))
+                     (not (db-property-handler/block-has-viewable-properties? page)))
              (page-configure page *hover? *configuring?))]])])))
 
 (defn- page-mouse-over
@@ -560,7 +560,7 @@
         edit-input-id-prefix (str "edit-block-" (:block/uuid page))
         configure-opts {:selected? false
                         :page-configure? true}
-        has-viewable-properties? (property-handler/block-has-viewable-properties? page)
+        has-viewable-properties? (db-property-handler/block-has-viewable-properties? page)
         has-class-properties? (seq (:properties (:block/schema page)))]
     (when (or configure? has-viewable-properties? has-class-properties?)
       [:div.ls-page-properties.mb-4 {:style {:padding 2}}
@@ -574,7 +574,7 @@
                                               (str edit-input-id-prefix "-schema")
                                               (assoc configure-opts :class-schema? true))]
 
-           (not (property-handler/block-has-viewable-properties? page))
+           (not (db-property-handler/block-has-viewable-properties? page))
            [:div
             [:div.mb-1 "Page properties:"]
             (component-block/db-properties-cp {:editor-box editor/box}
@@ -626,7 +626,7 @@
 (rum/defc page-properties-react < rum/reactive
   [page* page-opts]
   (let [page (db/sub-block (:db/id page*))]
-    (when (or (property-handler/block-has-viewable-properties? page)
+    (when (or (db-property-handler/block-has-viewable-properties? page)
               ;; Allow class and property pages to add new property
               (some #{"class" "property"} (:block/type page)))
       (page-properties page page-opts))))

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

@@ -161,7 +161,7 @@
                              {:disabled? disabled?
                               :on-chosen (fn [_e icon]
                                            (let [icon-property-id (db-pu/get-built-in-property-uuid :icon)]
-                                             (property-handler/update-property!
+                                             (db-property-handler/update-property!
                                               (state/get-current-repo)
                                               (:block/uuid property)
                                               {:properties {icon-property-id icon}})))})])]
@@ -286,7 +286,7 @@
                                              (js/confirm "Are you sure you want to delete this property?"))
                                      (let [repo (state/get-current-repo)
                                            f (if (and class? class-schema?)
-                                               property-handler/class-remove-property!
+                                               db-property-handler/class-remove-property!
                                                property-handler/remove-block-property!)]
                                        (f repo (:block/uuid block) (:block/uuid property))
                                        (when toggle-fn (toggle-fn)))))}
@@ -439,7 +439,7 @@
        [:div#edit-new-property
         (property-input block *property-key *property-value opts)]
 
-       (and (or (property-handler/block-has-viewable-properties? block)
+       (and (or (db-property-handler/block-has-viewable-properties? block)
                 (:page-configure? opts))
             (not config/publishing?)
             (not (:in-block-container? opts)))
@@ -474,7 +474,7 @@
        [:a.block-control
         {:on-click (fn [event]
                      (util/stop event)
-                     (property-handler/collapse-expand-property! repo block property (not collapsed?)))}
+                     (db-property-handler/collapse-expand-property! repo block property (not collapsed?)))}
         [:span {:class (cond
                          (or collapsed? @*hover?)
                          "control-show cursor-pointer"
@@ -495,9 +495,9 @@
            (fn [_e icon]
              (let [icon-property-id (db-pu/get-built-in-property-uuid :icon)]
                (when icon
-                 (property-handler/update-property! repo
-                                                    (:block/uuid property)
-                                                    {:properties {icon-property-id icon}})
+                 (db-property-handler/update-property! repo
+                                                       (:block/uuid property)
+                                                       {:properties {icon-property-id icon}})
                  (toggle-fn))))})])
       {:modal-class (util/hiccup->class
                      "origin-top-right.absolute.left-0.rounded-md.shadow-lg.mt-2")})
@@ -592,7 +592,7 @@
                                      (let [schema (assoc (:block/schema block)
                                                          :properties properties)]
                                        (when (seq properties)
-                                         (property-handler/class-set-schema! (state/get-current-repo) (:block/uuid block) schema))))}))
+                                         (db-property-handler/class-set-schema! (state/get-current-repo) (:block/uuid block) schema))))}))
         (for [[k v] properties]
           (property-cp block k v opts))))))
 
@@ -625,7 +625,7 @@
                                                  (when (uuid? id)
                                                    (contains? db-property/hidden-built-in-properties (keyword (:block/name (db/entity [:block/uuid id])))))))
                                              properties))
-        {:keys [classes all-classes classes-properties]} (property-handler/get-block-classes-properties (:db/id block))
+        {:keys [classes all-classes classes-properties]} (db-property-handler/get-block-classes-properties (:db/id block))
         one-class? (= 1 (count classes))
         block-own-properties (->> (concat (seq alias-properties)
                                           (seq properties))

+ 3 - 2
src/main/frontend/components/property/closed_value.cljs

@@ -9,6 +9,7 @@
             [frontend.components.icon :as icon-component]
             [frontend.components.property.util :as pu-component]
             [frontend.handler.property :as property-handler]
+            [frontend.handler.db-based.property :as db-property-handler]
             [frontend.components.property.value :as property-value]
             [frontend.db :as db]
             [frontend.state :as state]
@@ -17,7 +18,7 @@
 (defn- upsert-closed-value!
   "Create new closed value and returns its block UUID."
   [property item]
-  (let [{:keys [block-id tx-data]} (property-handler/upsert-closed-value property item)]
+  (let [{:keys [block-id tx-data]} (db-property-handler/upsert-closed-value property item)]
     (when (seq tx-data) (db/transact! tx-data))
     block-id))
 
@@ -131,7 +132,7 @@
         (assoc opts
                :delete-choice
                (fn []
-                 (property-handler/delete-closed-value property block))
+                 (db-property-handler/delete-closed-value property block))
                :update-icon
                (fn [icon]
                  (property-handler/set-block-property! (state/get-current-repo) (:block/uuid block) :icon icon)))))

+ 2 - 2
src/main/frontend/components/property/util.cljs

@@ -1,11 +1,11 @@
 (ns frontend.components.property.util
   "Property component utils"
   (:require [frontend.state :as state]
-            [frontend.handler.property :as property-handler]))
+            [frontend.handler.db-based.property :as db-property-handler]))
 
 (defn update-property!
   [property property-name property-schema]
-  (property-handler/update-property!
+  (db-property-handler/update-property!
    (state/get-current-repo)
    (:block/uuid property)
    {:property-name property-name

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

@@ -11,6 +11,7 @@
             [frontend.handler.editor :as editor-handler]
             [frontend.handler.page :as page-handler]
             [frontend.handler.property :as property-handler]
+            [frontend.handler.db-based.property :as db-property-handler]
             [frontend.state :as state]
             [frontend.ui :as ui]
             [frontend.util :as util]
@@ -53,7 +54,7 @@
          class? (contains? (:block/type block) "class")]
      (when property-key
        (if (and class? class-schema?)
-         (property-handler/class-add-property! repo (:block/uuid block) property-key)
+         (db-property-handler/class-add-property! repo (:block/uuid block) property-key)
          (property-handler/set-block-property! repo (:block/uuid block) property-key property-value)))
      (when exit-edit?
        (exit-edit-property)))))
@@ -307,7 +308,7 @@
 (defn create-new-block!
   [block property value]
   (let [repo (state/get-current-repo)
-        {:keys [page blocks]} (property-handler/property-create-new-block block property value editor-handler/wrap-parse-block)
+        {:keys [page blocks]} (db-property-handler/property-create-new-block block property value editor-handler/wrap-parse-block)
         last-block-id (:block/uuid (last blocks))]
     (db/transact! repo (if page (cons page blocks) blocks) {:outliner-op :insert-blocks})
     (add-property! block (:block/original-name property)
@@ -318,7 +319,7 @@
   "`template`: tag block"
   [block property template]
   (let [repo (state/get-current-repo)
-        {:keys [page blocks]} (property-handler/property-create-new-block-from-template block property template)]
+        {:keys [page blocks]} (db-property-handler/property-create-new-block-from-template block property template)]
     (db/transact! repo (if page (cons page blocks) blocks) {:outliner-op :insert-blocks})
     (add-property! block (:block/original-name property) (:block/uuid (last blocks)))
     (last blocks)))

+ 277 - 36
src/main/frontend/handler/db_based/property.cljs

@@ -3,17 +3,18 @@
   (:require [clojure.string :as string]
             [frontend.db :as db]
             [frontend.db.model :as model]
+            [frontend.format.block :as block]
             [frontend.handler.notification :as notification]
+            [frontend.handler.db-based.property.util :as db-pu]
             [frontend.modules.outliner.core :as outliner-core]
             [frontend.util :as util]
+            [frontend.state :as state]
             [logseq.graph-parser.util :as gp-util]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.db.frontend.property.type :as db-property-type]
             [malli.util :as mu]
             [malli.error :as me]
-            [frontend.format.block :as block]
-            [logseq.graph-parser.util.page-ref :as page-ref]
-            [frontend.handler.db-based.property.util :as db-pu]))
+            [logseq.graph-parser.util.page-ref :as page-ref]))
 
 ;; schema -> type, cardinality, object's class
 ;;           min, max -> string length, number range, cardinality size limit
@@ -297,43 +298,46 @@
                         {:outliner-op :save-block}))))))
 
 (defn class-add-property!
-  [repo class k-name]
-  (when (contains? (:block/type class) "class")
-    (let [k-name (name k-name)
-          property (db/pull repo '[*] [:block/name (gp-util/page-name-sanity-lc k-name)])
-          property-uuid (or (:block/uuid property) (db/new-block-id))
-          property-type (get-in property [:block/schema :type])
-          {:keys [properties] :as class-schema} (:block/schema class)
-          _ (upsert-property! repo k-name
-                              (cond-> (:block/schema property)
-                                (some? property-type)
-                                (assoc :type property-type))
-                              {:property-uuid property-uuid})
-          new-properties (vec (distinct (conj properties property-uuid)))
-          class-new-schema (assoc class-schema :properties new-properties)]
-      (db/transact! repo
-                    [{:db/id (:db/id class)
-                      :block/schema class-new-schema}]
-                    {:outliner-op :save-block}))))
-
-(defn class-remove-property!
-  [repo class k-uuid]
-  (when (contains? (:block/type class) "class")
-    (when-let [property (db/pull repo '[*] [:block/uuid k-uuid])]
-      (let [property-uuid (:block/uuid property)
+  [repo class-uuid k-name]
+  (when-let [class (db/entity repo [:block/uuid class-uuid])]
+    (when (contains? (:block/type class) "class")
+      (let [k-name (name k-name)
+            property (db/pull repo '[*] [:block/name (gp-util/page-name-sanity-lc k-name)])
+            property-uuid (or (:block/uuid property) (db/new-block-id))
+            property-type (get-in property [:block/schema :type])
             {:keys [properties] :as class-schema} (:block/schema class)
-            new-properties (vec (distinct (remove #{property-uuid} properties)))
+            _ (upsert-property! repo k-name
+                                (cond-> (:block/schema property)
+                                  (some? property-type)
+                                  (assoc :type property-type))
+                                {:property-uuid property-uuid})
+            new-properties (vec (distinct (conj properties property-uuid)))
             class-new-schema (assoc class-schema :properties new-properties)]
-        (db/transact! repo [{:db/id (:db/id class)
-                             :block/schema class-new-schema}]
-          {:outliner-op :save-block})))))
+        (db/transact! repo
+                      [{:db/id (:db/id class)
+                        :block/schema class-new-schema}]
+                      {:outliner-op :save-block})))))
+
+(defn class-remove-property!
+  [repo class-uuid k-uuid]
+  (when-let [class (db/entity repo [:block/uuid class-uuid])]
+    (when (contains? (:block/type class) "class")
+      (when-let [property (db/pull repo '[*] [:block/uuid k-uuid])]
+        (let [property-uuid (:block/uuid property)
+              {:keys [properties] :as class-schema} (:block/schema class)
+              new-properties (vec (distinct (remove #{property-uuid} properties)))
+              class-new-schema (assoc class-schema :properties new-properties)]
+          (db/transact! repo [{:db/id (:db/id class)
+                               :block/schema class-new-schema}]
+                        {:outliner-op :save-block}))))))
 
 (defn class-set-schema!
-  [repo class schema]
-  (when (contains? (:block/type class) "class")
-    (db/transact! repo [{:db/id (:db/id class)
-                         :block/schema schema}]
-                  {:outliner-op :save-block})))
+  [repo class-uuid schema]
+  (when-let [class (db/entity repo [:block/uuid class-uuid])]
+    (when (contains? (:block/type class) "class")
+      (db/transact! repo [{:db/id (:db/id class)
+                           :block/schema schema}]
+                    {:outliner-op :save-block}))))
 
 (defn batch-set-property!
   "Notice that this works only for properties with cardinality equals to `one`."
@@ -476,8 +480,245 @@
    (vals m)))
 
 (defn collapse-expand-property!
+  "Notice this works only if the value itself if a block (property type should be either :default or :template)"
   [repo block property collapse?]
   (let [f (if collapse? :db/add :db/retract)]
     (db/transact! repo
                   [[f (:db/id block) :block/collapsed-properties (:db/id property)]]
                   {:outliner-op :save-block})))
+
+(defn- get-namespace-parents
+  [tags]
+  (let [tags' (filter (fn [tag] (contains? (:block/type tag) "class")) tags)
+        *namespaces (atom #{})]
+    (doseq [tag tags']
+      (when-let [ns (:block/namespace tag)]
+        (loop [current-ns ns]
+          (when (and
+                 current-ns
+                 (contains? (:block/type ns) "class")
+                 (not (contains? @*namespaces (:db/id ns))))
+            (swap! *namespaces conj current-ns)
+            (recur (:block/namespace current-ns))))))
+    @*namespaces))
+
+(defn get-block-classes-properties
+  [eid]
+  (let [block (db/entity eid)
+        classes (->> (:block/tags block)
+                     (sort-by :block/name)
+                     (filter (fn [tag] (contains? (:block/type tag) "class"))))
+        namespace-parents (get-namespace-parents classes)
+        all-classes (->> (concat classes namespace-parents)
+                         (filter (fn [class]
+                                   (seq (:properties (:block/schema class))))))
+        all-properties (-> (mapcat (fn [class]
+                                     (seq (:properties (:block/schema class)))) all-classes)
+                           distinct)]
+    {:classes classes
+     :all-classes all-classes           ; block own classes + parent classes
+     :classes-properties all-properties}))
+
+(defn- closed-value-other-position?
+  [property-id block-properties]
+  (and
+   (some? (get block-properties property-id))
+   (let [schema (:block/schema (db/entity [:block/uuid property-id]))]
+     (= (:position schema) "block-beginning"))))
+
+(defn get-block-other-position-properties
+  [eid]
+  (let [block (db/entity eid)
+        own-properties (keys (:block/properties block))]
+    (->> (:classes-properties (get-block-classes-properties eid))
+         (concat own-properties)
+         (filter (fn [id] (closed-value-other-position? id (:block/properties block))))
+         (distinct))))
+
+(defn block-has-viewable-properties?
+  [block-entity]
+  (let [properties (:block/properties block-entity)]
+    (or
+     (seq (:block/alias properties))
+     (and (seq properties)
+          (not= (keys properties) [(db-pu/get-built-in-property-uuid :icon)])))))
+
+(defn property-create-new-block
+  [block property value parse-block]
+  (let [current-page-id (:block/uuid (or (:block/page block) block))
+        page-name (str "$$$" current-page-id)
+        page-entity (db/entity [:block/name page-name])
+        page (or page-entity
+                 (-> (block/page-name->map page-name true)
+                     (assoc :block/type #{"hidden"}
+                            :block/format :markdown
+                            :block/metadata {:source-page-id current-page-id})))
+        page-tx (when-not page-entity page)
+        page-id [:block/uuid (:block/uuid page)]
+        parent-id (db/new-block-id)
+        metadata {:created-from-block (:block/uuid block)
+                  :created-from-property (:block/uuid property)}
+        parent (-> {:block/uuid parent-id
+                    :block/format :markdown
+                    :block/content ""
+                    :block/page page-id
+                    :block/parent page-id
+                    :block/left (or (when page-entity (model/get-block-last-direct-child (db/get-db) (:db/id page-entity)))
+                                    page-id)
+                    :block/metadata metadata}
+                   outliner-core/block-with-timestamps)
+        child-1-id (db/new-block-id)
+        child-1 (-> {:block/uuid child-1-id
+                     :block/format :markdown
+                     :block/content value
+                     :block/page page-id
+                     :block/parent [:block/uuid parent-id]
+                     :block/left [:block/uuid parent-id]}
+                    outliner-core/block-with-timestamps
+                    parse-block)]
+    {:page page-tx
+     :blocks [parent child-1]}))
+
+(defn property-create-new-block-from-template
+  [block property template]
+  (let [current-page-id (:block/uuid (or (:block/page block) block))
+        page-name (str "$$$" current-page-id)
+        page-entity (db/entity [:block/name page-name])
+        page (or page-entity
+                 (-> (block/page-name->map page-name true)
+                     (assoc :block/type #{"hidden"}
+                            :block/format :markdown
+                            :block/metadata {:source-page-id current-page-id})))
+        page-tx (when-not page-entity page)
+        page-id [:block/uuid (:block/uuid page)]
+        block-id (db/new-block-id)
+        metadata {:created-from-block (:block/uuid block)
+                  :created-from-property (:block/uuid property)
+                  :created-from-template (:block/uuid template)}
+        new-block (-> {:block/uuid block-id
+                       :block/format :markdown
+                       :block/content ""
+                       :block/tags #{(:db/id template)}
+                       :block/page page-id
+                       :block/metadata metadata
+                       :block/parent page-id
+                       :block/left (or (when page-entity (model/get-block-last-direct-child (db/get-db) (:db/id page-entity)))
+                                       page-id)}
+                      outliner-core/block-with-timestamps)]
+    {:page page-tx
+     :blocks [new-block]}))
+
+(defn upsert-closed-value
+  "id should be a block UUID or nil"
+  [property {:keys [id value icon description]}]
+  (assert (or (nil? id) (uuid? id)))
+  (let [property-type (get-in property [:block/schema :type] :default)]
+    (when (contains? db-property-type/closed-values-schema-types property-type)
+     (let [value (if (string? value) (string/trim value) value)
+           property-schema (:block/schema property)
+           closed-values (:values property-schema)
+           block-values (map (fn [id] (db/entity [:block/uuid id])) closed-values)
+           resolved-value (try
+                            (convert-property-input-string (:type property-schema) value)
+                            (catch :default e
+                              (js/console.error e)
+                              (notification/show! (str e) :error false)
+                              nil))
+           block (when id (db/entity [:block/uuid id]))
+           value-block (when (uuid? value) (db/entity [:block/uuid value]))
+           validate-message (validate-property-value
+                             (get (builtin-schema-types property {:new-closed-value? true}) property-type)
+                             resolved-value)]
+       (cond
+         (nil? resolved-value)
+         nil
+
+         (some (fn [b] (and (if (contains? (get-in b [:block/schema :type]) "closed value")
+                              (= resolved-value (get-in b [:block/schema :value]))
+                              (= resolved-value (:block/uuid b)))
+                            (not= id (:block/uuid b)))) block-values)
+         (do
+           (notification/show! "Choice already exists" :warning)
+           :value-exists)
+
+         validate-message
+         (do
+           (notification/show! validate-message :warning)
+           :value-invalid)
+
+         (:block/name value-block)             ; page
+         (let [new-values (vec (conj closed-values value))]
+           {:block-id value
+            :tx-data [{:db/id (:db/id property)
+                       :block/schema (assoc property-schema :values new-values)}]})
+
+         :else
+         (let [block-id (or id (db/new-block-id))
+               icon-id (db-pu/get-built-in-property-uuid "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
+                         [(let [properties (:block/properties block)
+                                schema (assoc (:block/schema block)
+                                              :value resolved-value)]
+                            {:block/uuid id
+                             :block/properties (if icon
+                                                 (assoc properties icon-id icon)
+                                                 (dissoc properties icon-id))
+                             :block/schema (if description
+                                             (assoc schema :description description)
+                                             (dissoc schema :description))})]
+                         (let [page-name (str "$$$" (:block/uuid property))
+                               page-entity (db/entity [:block/name page-name])
+                               page (or page-entity
+                                        (-> (block/page-name->map page-name true)
+                                            (assoc :block/type #{"hidden"}
+                                                   :block/format :markdown)))
+                               page-tx (when-not page-entity page)
+                               page-id [:block/uuid (:block/uuid page)]
+                               metadata {:created-from-property (:block/uuid property)}
+                               new-block (cond->
+                                          {:block/type #{"closed value"}
+                                           :block/format :markdown
+                                           :block/uuid block-id
+                                           :block/page page-id
+                                           :block/metadata metadata
+                                           :block/schema {:value resolved-value}
+                                           :block/parent page-id}
+                                           icon
+                                           (assoc :block/properties {icon-id icon})
+
+                                           description
+                                           (update :block/schema assoc :description description)
+
+                                           true
+                                           outliner-core/block-with-timestamps)
+                               new-values (vec (conj closed-values block-id))]
+                           (->> (cons page-tx [new-block
+                                               {:db/id (:db/id property)
+                                                :block/schema (assoc property-schema :values new-values)}])
+                                (remove nil?))))]
+           {:block-id block-id
+            :tx-data tx-data}))))))
+
+(defn delete-closed-value
+  [property item]
+  (if (seq (:block/_refs item))
+    (notification/show! "The choice can't be deleted because it's still used." :warning)
+    (let [schema (:block/schema property)
+          tx-data [[:db/retractEntity (:db/id item)]
+                   {:db/id (:db/id property)
+                    :block/schema (update schema :values
+                                          (fn [values]
+                                            (vec (remove #{(:block/uuid item)} values))))}]]
+      (db/transact! tx-data))))
+
+(defn get-property-block-created-block
+  "Get the root block that created this property block."
+  [eid]
+  (let [b (db/entity eid)
+        parents (model/get-block-parents (state/get-current-repo) (:block/uuid b) {})
+        from-id (some #(get-in % [:block/metadata :created-from-block]) (reverse parents))
+        from (when from-id (db/entity [:block/uuid from-id]))]
+    (or (:db/id from) (:db/id b))))

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

@@ -912,14 +912,7 @@
   [block-ids]
   (let [repo (state/get-current-repo)]
     (when-not (config/db-based-graph? repo)
-      (let [block-ids (remove nil? block-ids)
-            col (map (fn [block-id]
-                       (when-let [block (db/entity [:block/uuid block-id])]
-                         (when-not (:block/pre-block? block)
-                           [block-id :id (str block-id)])))
-                  block-ids)
-            col (remove nil? col)]
-        (property-handler/file-batch-set-property! repo col)))))
+      (file-editor-handler/set-blocks-id! block-ids))))
 
 (defn copy-block-ref!
   ([block-id]

+ 17 - 4
src/main/frontend/handler/file_based/editor.cljs

@@ -211,7 +211,20 @@
 
 (defn batch-set-heading! [block-ids heading]
   (outliner-tx/transact!
-       {:outliner-op :save-block}
-       (doseq [block-id block-ids]
-         (when-let [block (set-heading-aux! block-id heading)]
-           (outliner-core/save-block! block)))))
+   {:outliner-op :save-block}
+   (doseq [block-id block-ids]
+     (when-let [block (set-heading-aux! block-id heading)]
+       (outliner-core/save-block! block)))))
+
+(defn set-blocks-id!
+  "Persist block uuid to file if the uuid is valid, and it's not persisted in file.
+   Accepts a list of uuids."
+  [block-ids]
+  (let [block-ids (remove nil? block-ids)
+        col (map (fn [block-id]
+                   (when-let [block (db/entity [:block/uuid block-id])]
+                     (when-not (:block/pre-block? block)
+                       [block-id :id (str block-id)])))
+                 block-ids)
+        col (remove nil? col)]
+    (file-property-handler/batch-set-block-property-aux! col)))

+ 3 - 288
src/main/frontend/handler/property.cljs

@@ -1,20 +1,12 @@
 (ns frontend.handler.property
-  "Block properties handler."
+  "Property fns for both file and DB graphs"
   (:require [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.file-based.property :as file-property-handler]
             [frontend.handler.file-based.page-property :as file-page-property]
-            [frontend.handler.notification :as notification]
-            [logseq.db.frontend.property.type :as db-property-type]
             [frontend.config :as config]
             [frontend.util :as util]
             [frontend.state :as state]
-            [frontend.db :as db]
-            [frontend.format.block :as block]
-            [frontend.db.model :as model]
-            [frontend.modules.outliner.core :as outliner-core]
-            [frontend.handler.property.util :as pu]
-            [frontend.handler.db-based.property.util :as db-pu]
-            [clojure.string :as string]))
+            [frontend.db :as db]))
 
 (defn remove-block-property!
   [repo block-id key]
@@ -30,18 +22,6 @@
       (db-property-handler/set-block-property! repo block-id key v opts))
     (file-property-handler/set-block-property! block-id key v)))
 
-(defn update-property!
-  [repo property-uuid opts]
-  {:pre [(uuid? property-uuid)]}
-  (when (config/db-based-graph? repo)
-    (db-property-handler/update-property! repo property-uuid opts)))
-
-(defn delete-property-value!
-  "Delete value if a property has multiple values"
-  [repo block property-id property-value]
-  (when (config/db-based-graph? repo)
-    (db-property-handler/delete-property-value! repo block property-id property-value)))
-
 (defn add-page-property!
   "Sanitized page-name, unsanitized key / value"
   [page-name key value]
@@ -60,24 +40,6 @@
   (set-editing-new-property! (state/get-edit-input-id))
   (state/clear-edit!))
 
-(defn class-add-property!
-  [repo class-uuid k-name]
-  (when-let [class (db/entity repo [:block/uuid class-uuid])]
-    (when (config/db-based-graph? repo)
-      (db-property-handler/class-add-property! repo class k-name))))
-
-(defn class-remove-property!
-  [repo class-uuid k-uuid]
-  (when-let [class (db/entity repo [:block/uuid class-uuid])]
-    (when (config/db-based-graph? repo)
-      (db-property-handler/class-remove-property! repo class k-uuid))))
-
-(defn class-set-schema!
-  [repo class-uuid schema]
-  (when-let [class (db/entity repo [:block/uuid class-uuid])]
-    (when (config/db-based-graph? repo)
-      (db-property-handler/class-set-schema! repo class schema))))
-
 (defn remove-id-property
   [repo format content]
   (if (config/db-based-graph? repo)
@@ -103,255 +65,8 @@
       (db-property-handler/batch-set-property! repo block-ids key value))
     (file-property-handler/batch-set-block-property! block-ids key value)))
 
-(defn file-batch-set-property!
-  [repo col]
-  (when-not (config/db-based-graph? repo)
-    (file-property-handler/batch-set-block-property-aux! col)))
-
 (defn replace-key-with-id!
   [repo m]
   (if (config/db-based-graph? repo)
     (db-property-handler/replace-key-with-id! m)
-    m))
-
-(defn collapse-expand-property!
-  "Notice this works only if the value itself if a block (property type should be either :default or :template)"
-  [repo block property collapse?]
-  (when (config/db-based-graph? repo)
-    (db-property-handler/collapse-expand-property! repo block property collapse?)))
-
-(defn- get-namespace-parents
-  [tags]
-  (let [tags' (filter (fn [tag] (contains? (:block/type tag) "class")) tags)
-        *namespaces (atom #{})]
-    (doseq [tag tags']
-      (when-let [ns (:block/namespace tag)]
-        (loop [current-ns ns]
-          (when (and
-                 current-ns
-                 (contains? (:block/type ns) "class")
-                 (not (contains? @*namespaces (:db/id ns))))
-            (swap! *namespaces conj current-ns)
-            (recur (:block/namespace current-ns))))))
-    @*namespaces))
-
-(defn get-block-classes-properties
-  [eid]
-  (let [block (db/entity eid)
-        classes (->> (:block/tags block)
-                     (sort-by :block/name)
-                     (filter (fn [tag] (contains? (:block/type tag) "class"))))
-        namespace-parents (get-namespace-parents classes)
-        all-classes (->> (concat classes namespace-parents)
-                         (filter (fn [class]
-                                   (seq (:properties (:block/schema class))))))
-        all-properties (-> (mapcat (fn [class]
-                                     (seq (:properties (:block/schema class)))) all-classes)
-                           distinct)]
-    {:classes classes
-     :all-classes all-classes           ; block own classes + parent classes
-     :classes-properties all-properties}))
-
-(defn closed-value-other-position?
-  [property-id block-properties]
-  (and
-   (some? (get block-properties property-id))
-   (let [schema (:block/schema (db/entity [:block/uuid property-id]))]
-     (= (:position schema) "block-beginning"))))
-
-(defn get-block-other-position-properties
-  [eid]
-  (let [block (db/entity eid)
-        own-properties (keys (:block/properties block))]
-    (->> (:classes-properties (get-block-classes-properties eid))
-         (concat own-properties)
-         (filter (fn [id] (closed-value-other-position? id (:block/properties block))))
-         (distinct))))
-
-(defn block-has-viewable-properties?
-  [block-entity]
-  (let [properties (:block/properties block-entity)]
-    (or
-     (seq (:block/alias properties))
-     (and (seq properties)
-          (not= (keys properties) [(db-pu/get-built-in-property-uuid :icon)])))))
-
-(defn property-create-new-block
-  [block property value parse-block]
-  (let [current-page-id (:block/uuid (or (:block/page block) block))
-        page-name (str "$$$" current-page-id)
-        page-entity (db/entity [:block/name page-name])
-        page (or page-entity
-                 (-> (block/page-name->map page-name true)
-                     (assoc :block/type #{"hidden"}
-                            :block/format :markdown
-                            :block/metadata {:source-page-id current-page-id})))
-        page-tx (when-not page-entity page)
-        page-id [:block/uuid (:block/uuid page)]
-        parent-id (db/new-block-id)
-        metadata {:created-from-block (:block/uuid block)
-                  :created-from-property (:block/uuid property)}
-        parent (-> {:block/uuid parent-id
-                    :block/format :markdown
-                    :block/content ""
-                    :block/page page-id
-                    :block/parent page-id
-                    :block/left (or (when page-entity (model/get-block-last-direct-child (db/get-db) (:db/id page-entity)))
-                                    page-id)
-                    :block/metadata metadata}
-                   outliner-core/block-with-timestamps)
-        child-1-id (db/new-block-id)
-        child-1 (-> {:block/uuid child-1-id
-                     :block/format :markdown
-                     :block/content value
-                     :block/page page-id
-                     :block/parent [:block/uuid parent-id]
-                     :block/left [:block/uuid parent-id]}
-                    outliner-core/block-with-timestamps
-                    parse-block)]
-    {:page page-tx
-     :blocks [parent child-1]}))
-
-(defn property-create-new-block-from-template
-  [block property template]
-  (let [current-page-id (:block/uuid (or (:block/page block) block))
-        page-name (str "$$$" current-page-id)
-        page-entity (db/entity [:block/name page-name])
-        page (or page-entity
-                 (-> (block/page-name->map page-name true)
-                     (assoc :block/type #{"hidden"}
-                            :block/format :markdown
-                            :block/metadata {:source-page-id current-page-id})))
-        page-tx (when-not page-entity page)
-        page-id [:block/uuid (:block/uuid page)]
-        block-id (db/new-block-id)
-        metadata {:created-from-block (:block/uuid block)
-                  :created-from-property (:block/uuid property)
-                  :created-from-template (:block/uuid template)}
-        new-block (-> {:block/uuid block-id
-                       :block/format :markdown
-                       :block/content ""
-                       :block/tags #{(:db/id template)}
-                       :block/page page-id
-                       :block/metadata metadata
-                       :block/parent page-id
-                       :block/left (or (when page-entity (model/get-block-last-direct-child (db/get-db) (:db/id page-entity)))
-                                       page-id)}
-                      outliner-core/block-with-timestamps)]
-    {:page page-tx
-     :blocks [new-block]}))
-
-(defn upsert-closed-value
-  "id should be a block UUID or nil"
-  [property {:keys [id value icon description]}]
-  (assert (or (nil? id) (uuid? id)))
-  (let [property-type (get-in property [:block/schema :type] :default)]
-    (when (contains? db-property-type/closed-values-schema-types property-type)
-     (let [value (if (string? value) (string/trim value) value)
-           property-schema (:block/schema property)
-           closed-values (:values property-schema)
-           block-values (map (fn [id] (db/entity [:block/uuid id])) closed-values)
-           resolved-value (try
-                            (db-property-handler/convert-property-input-string (:type property-schema) value)
-                            (catch :default e
-                              (js/console.error e)
-                              (notification/show! (str e) :error false)
-                              nil))
-           block (when id (db/entity [:block/uuid id]))
-           value-block (when (uuid? value) (db/entity [:block/uuid value]))
-           validate-message (db-property-handler/validate-property-value
-                             (get (db-property-handler/builtin-schema-types property {:new-closed-value? true}) property-type)
-                             resolved-value)]
-       (cond
-         (nil? resolved-value)
-         nil
-
-         (some (fn [b] (and (if (contains? (get-in b [:block/schema :type]) "closed value")
-                              (= resolved-value (get-in b [:block/schema :value]))
-                              (= resolved-value (:block/uuid b)))
-                            (not= id (:block/uuid b)))) block-values)
-         (do
-           (notification/show! "Choice already exists" :warning)
-           :value-exists)
-
-         validate-message
-         (do
-           (notification/show! validate-message :warning)
-           :value-invalid)
-
-         (:block/name value-block)             ; page
-         (let [new-values (vec (conj closed-values value))]
-           {:block-id value
-            :tx-data [{:db/id (:db/id property)
-                       :block/schema (assoc property-schema :values new-values)}]})
-
-         :else
-         (let [block-id (or id (db/new-block-id))
-               icon-id (pu/get-pid "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
-                         [(let [properties (:block/properties block)
-                                schema (assoc (:block/schema block)
-                                              :value resolved-value)]
-                            {:block/uuid id
-                             :block/properties (if icon
-                                                 (assoc properties icon-id icon)
-                                                 (dissoc properties icon-id))
-                             :block/schema (if description
-                                             (assoc schema :description description)
-                                             (dissoc schema :description))})]
-                         (let [page-name (str "$$$" (:block/uuid property))
-                               page-entity (db/entity [:block/name page-name])
-                               page (or page-entity
-                                        (-> (block/page-name->map page-name true)
-                                            (assoc :block/type #{"hidden"}
-                                                   :block/format :markdown)))
-                               page-tx (when-not page-entity page)
-                               page-id [:block/uuid (:block/uuid page)]
-                               metadata {:created-from-property (:block/uuid property)}
-                               new-block (cond->
-                                          {:block/type #{"closed value"}
-                                           :block/format :markdown
-                                           :block/uuid block-id
-                                           :block/page page-id
-                                           :block/metadata metadata
-                                           :block/schema {:value resolved-value}
-                                           :block/parent page-id}
-                                           icon
-                                           (assoc :block/properties {icon-id icon})
-
-                                           description
-                                           (update :block/schema assoc :description description)
-
-                                           true
-                                           outliner-core/block-with-timestamps)
-                               new-values (vec (conj closed-values block-id))]
-                           (->> (cons page-tx [new-block
-                                               {:db/id (:db/id property)
-                                                :block/schema (assoc property-schema :values new-values)}])
-                                (remove nil?))))]
-           {:block-id block-id
-            :tx-data tx-data}))))))
-
-(defn delete-closed-value
-  [property item]
-  (if (seq (:block/_refs item))
-    (notification/show! "The choice can't be deleted because it's still used." :warning)
-    (let [schema (:block/schema property)
-          tx-data [[:db/retractEntity (:db/id item)]
-                   {:db/id (:db/id property)
-                    :block/schema (update schema :values
-                                          (fn [values]
-                                            (vec (remove #{(:block/uuid item)} values))))}]]
-      (db/transact! tx-data))))
-
-(defn get-property-block-created-block
-  "Get the root block that created this property block."
-  [eid]
-  (let [b (db/entity eid)
-        parents (model/get-block-parents (state/get-current-repo) (:block/uuid b) {})
-        from-id (some #(get-in % [:block/metadata :created-from-block]) (reverse parents))
-        from (when from-id (db/entity [:block/uuid from-id]))]
-    (or (:db/id from) (:db/id b))))
+    m))