浏览代码

fix: separate page/create impl for db and file graphs

Also, move rtc page create impl to its own fn.
Tienson Qin 1 年之前
父节点
当前提交
1dc72d79f2

+ 46 - 45
deps/graph-parser/src/logseq/graph_parser/block.cljs

@@ -297,58 +297,59 @@
 (defn page-name->map
   "Create a page's map structure given a original page name (string).
    map as input is supported for legacy compatibility.
-   with-id?: if true, assign uuid to the map structure.
+   `with-id?`: if true, assign uuid to the map structure.
     if the page entity already exists, no-op.
     else, if with-id? is a uuid, the uuid is used.
     otherwise, generate a uuid.
-   with-timestamp?: assign timestampes to the map structure.
+   `with-timestamp?`: assign timestampes to the map structure.
     Useful when creating new pages from references or namespaces,
-    as there's no chance to introduce timestamps via editing in page"
+    as there's no chance to introduce timestamps via editing in page
+   `skip-existing-page-check?`: if true, allows pages to have the same name"
   [original-page-name with-id? db with-timestamp? date-formatter
-   & {:keys [from-page class?]}]
+   & {:keys [from-page class? skip-existing-page-check?]}]
   (let [db-based? (ldb/db-based-graph? db)]
     (cond
-     (and original-page-name (string? original-page-name))
-     (let [original-page-name (common-util/remove-boundary-slashes original-page-name)
-           [original-page-name page-name journal-day] (convert-page-if-journal original-page-name date-formatter)
-           namespace? (and (not db-based?)
-                           (not (boolean (text/get-nested-page-name original-page-name)))
-                           (text/namespace-page? original-page-name))
-           page-entity (when db
-                         (if class?
-                           (ldb/get-case-page db original-page-name)
-                           (ldb/get-page db original-page-name)))
-           original-page-name (or from-page (:block/original-name page-entity) original-page-name)]
-       (merge
-        {:block/name page-name
-         :block/original-name original-page-name}
-        (when with-id?
-          (let [new-uuid (or
-                          (cond page-entity      (:block/uuid page-entity)
-                                (uuid? with-id?) with-id?)
-                          (d/squuid))]
-            {:block/uuid new-uuid}))
-        (when namespace?
-          (let [namespace (first (common-util/split-last "/" original-page-name))]
-            (when-not (string/blank? namespace)
-              {:block/namespace {:block/name (common-util/page-name-sanity-lc namespace)}})))
-        (when (and with-timestamp? (not page-entity)) ;; Only assign timestamp on creating new entity
-          (let [current-ms (common-util/time-ms)]
-            {:block/created-at current-ms
-             :block/updated-at current-ms}))
-        (if journal-day
-          {:block/type "journal"
-           :block/journal-day journal-day}
-          {})))
-
-     (and (map? original-page-name) (:block/uuid original-page-name))
-     original-page-name
-
-     (and (map? original-page-name) with-id?)
-     (assoc original-page-name :block/uuid (d/squuid))
-
-     :else
-     nil)))
+      (and original-page-name (string? original-page-name))
+      (let [original-page-name (common-util/remove-boundary-slashes original-page-name)
+            [original-page-name page-name journal-day] (convert-page-if-journal original-page-name date-formatter)
+            namespace? (and (not db-based?)
+                            (not (boolean (text/get-nested-page-name original-page-name)))
+                            (text/namespace-page? original-page-name))
+            page-entity (when (and db (not skip-existing-page-check?))
+                          (if class?
+                            (ldb/get-case-page db original-page-name)
+                            (ldb/get-page db original-page-name)))
+            original-page-name (or from-page (:block/original-name page-entity) original-page-name)]
+        (merge
+         {:block/name page-name
+          :block/original-name original-page-name}
+         (when with-id?
+           (let [new-uuid (or
+                           (cond page-entity      (:block/uuid page-entity)
+                                 (uuid? with-id?) with-id?)
+                           (d/squuid))]
+             {:block/uuid new-uuid}))
+         (when namespace?
+           (let [namespace (first (common-util/split-last "/" original-page-name))]
+             (when-not (string/blank? namespace)
+               {:block/namespace {:block/name (common-util/page-name-sanity-lc namespace)}})))
+         (when (and with-timestamp? (not page-entity)) ;; Only assign timestamp on creating new entity
+           (let [current-ms (common-util/time-ms)]
+             {:block/created-at current-ms
+              :block/updated-at current-ms}))
+         (if journal-day
+           {:block/type "journal"
+            :block/journal-day journal-day}
+           {})))
+
+      (and (map? original-page-name) (:block/uuid original-page-name))
+      original-page-name
+
+      (and (map? original-page-name) with-id?)
+      (assoc original-page-name :block/uuid (d/squuid))
+
+      :else
+      nil)))
 
 (defn- with-page-refs-and-tags
   [{:keys [title body tags refs marker priority] :as block} with-id? db date-formatter]

+ 121 - 83
src/main/frontend/worker/handler/page.cljs

@@ -17,7 +17,7 @@
             [logseq.db.frontend.property.build :as db-property-build]
             [logseq.db.frontend.class :as db-class]))
 
-(defn properties-block
+(defn file-based-properties-block
   [repo conn config date-formatter properties format page]
   (let [content (gp-property/insert-properties repo format "" properties)
         refs (gp-block/get-page-refs-from-properties properties @conn date-formatter config)]
@@ -55,7 +55,6 @@
             (into (vals property-vals-tx-m))
             true
             (conj (merge {:block/uuid (:block/uuid page)}
-                       ;; FIXME: Add refs for properties?
                          properties
                          (db-property-build/build-properties-with-ref-values property-vals-tx-m)))))
         (let [file-page (merge page'
@@ -63,7 +62,7 @@
           (if (and (seq properties)
                    (not whiteboard?)
                    (ldb/page-empty? @conn (:block/name page)))
-            [file-page (properties-block repo conn config date-formatter properties format page-entity)]
+            [file-page (file-based-properties-block repo conn config date-formatter properties format page-entity)]
             [file-page]))))))
 
 (defn get-title-and-pagename
@@ -76,6 +75,120 @@
         page-name  (common-util/page-name-sanity-lc title)]
     [title page-name]))
 
+(defn- build-first-block-tx
+  [page-uuid format]
+  (let [page-id [:block/uuid page-uuid]]
+    [(sqlite-util/block-with-timestamps
+      {:block/uuid (ldb/new-block-id)
+       :block/page page-id
+       :block/parent page-id
+       :block/order (db-order/gen-key nil nil)
+       :block/content ""
+       :block/format format})]))
+
+(defn- file-based-create!
+  [repo conn config title {:keys [create-first-block? format properties uuid persist-op? whiteboard? class? today-journal?]
+                           :or   {create-first-block?      true
+                                  format                   nil
+                                  properties               nil
+                                  uuid                     nil
+                                  persist-op?              true}
+                           :as options}]
+  (let [date-formatter (common-config/get-date-formatter config)
+        split-namespace? (not (or (string/starts-with? title "hls__")
+                                  (date/valid-journal-title? date-formatter title)))
+        [title page-name] (get-title-and-pagename title)
+        with-uuid? (if (uuid? uuid) uuid true)]
+    (when-not (ldb/get-page @conn page-name)
+      (let [pages    (if split-namespace?
+                       (common-util/split-namespace-pages title)
+                       [title])
+            format   (or format (common-config/get-preferred-format config))
+            pages    (map (fn [page]
+                            ;; only apply uuid to the deepest hierarchy of page to create if provided.
+                            (-> (gp-block/page-name->map page (if (= page title) with-uuid? true) @conn true date-formatter :class? class?)
+                                (assoc :block/format format)))
+                          pages)
+            txs      (->> pages
+                            ;; for namespace pages, only last page need properties
+                          drop-last
+                          (mapcat #(build-page-tx repo conn config date-formatter format nil % {}))
+                          (remove nil?))
+            txs      (map-indexed (fn [i page]
+                                    (if (zero? i)
+                                      page
+                                      (assoc page :block/namespace
+                                             [:block/uuid (:block/uuid (nth txs (dec i)))])))
+                                  txs)
+            page-uuid (:block/uuid (last pages))
+            page-txs (build-page-tx repo conn config date-formatter format properties (last pages) (select-keys options [:whiteboard? :class? :tags]))
+            page-txs (if (seq txs)
+                       (update page-txs 0
+                               (fn [p]
+                                 (assoc p :block/namespace [:block/uuid (:block/uuid (last txs))])))
+                       page-txs)
+            first-block-tx (when (and
+                                  create-first-block?
+                                  (not (or whiteboard? class?))
+                                  page-txs)
+                             (build-first-block-tx (:block/uuid (first page-txs)) format))
+            txs      (concat
+                      txs
+                      page-txs
+                      first-block-tx)
+            [page-uuid result] (when (seq txs)
+                                 [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op?
+                                                                             :outliner-op :create-page}
+                                                                      today-journal?
+                                                                      (assoc :create-today-journal? true
+                                                                             :today-journal-name page-name)))])]
+        [result page-name page-uuid]))))
+
+(defn db-based-create!
+  [repo conn config title
+   {:keys [create-first-block? properties uuid persist-op? whiteboard? class? today-journal?]
+    :or   {create-first-block?      true
+           properties               nil
+           uuid                     nil
+           persist-op?              true}
+    :as options}]
+  (let [date-formatter (common-config/get-date-formatter config)
+        [title page-name] (get-title-and-pagename title)
+        with-uuid? (if (uuid? uuid) uuid true)]
+    (when-not (ldb/get-page @conn page-name)
+      (let [format    :markdown
+            page      (-> (gp-block/page-name->map title with-uuid? @conn true date-formatter :class? class?)
+                          (assoc :block/format format))
+            page-uuid (:block/uuid page)
+            page-txs  (build-page-tx repo conn config date-formatter format properties page (select-keys options [:whiteboard? :class? :tags]))
+            first-block-tx (when (and
+                                  create-first-block?
+                                  (not (or whiteboard? class?))
+                                  page-txs)
+                             (build-first-block-tx (:block/uuid (first page-txs)) format))
+            txs      (concat
+                      page-txs
+                      first-block-tx)
+            [page-uuid result] (when (seq txs)
+                                 [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op?
+                                                                             :outliner-op :create-page}
+                                                                      today-journal?
+                                                                      (assoc :create-today-journal? true
+                                                                             :today-journal-name page-name)))])]
+        [result page-name page-uuid]))))
+
+(defn rtc-create-page!
+  [conn config title {:keys [uuid]}]
+  (assert (uuid? uuid) (str "rtc-create-page! `uuid` is not a uuid " uuid))
+  (let [date-formatter (common-config/get-date-formatter config)
+        [title page-name] (get-title-and-pagename title)
+        page      (-> (gp-block/page-name->map title uuid @conn true date-formatter
+                                               {:skip-existing-page-check? true})
+                      (assoc :block/format :markdown))
+        result (ldb/transact! conn [page] {:persist-op? false
+                                           :outliner-op :create-page})]
+    [result page-name (:block/uuid page)]))
+
 (defn create!
   "Create page. Has the following options:
 
@@ -86,86 +199,11 @@
    * :tags                     - tag uuids that are added to :block/tags
    * :persist-op?              - when true, add an update-page op
    * :properties               - properties to add to the page
-   * :create-even-page-exists? - create page even same-name page exists
-   TODO: Add other options"
-  [repo conn config title
-   & {:keys [create-first-block? format properties uuid persist-op? whiteboard? class? today-journal?
-             create-even-page-exists?]
-      :or   {create-first-block?      true
-             format                   nil
-             properties               nil
-             uuid                     nil
-             persist-op?              true
-             create-even-page-exists? false}
-      :as options}]
-  (let [db-based? (ldb/db-based-graph? @conn)
-        date-formatter (common-config/get-date-formatter config)
-        split-namespace? (and
-                          (not db-based?)
-                          (not (or (string/starts-with? title "hls__")
-                                   (date/valid-journal-title? date-formatter title))))
-        [title page-name] (get-title-and-pagename title)
-        with-uuid? (if (uuid? uuid) uuid true)
-        [page-uuid result] (when (or create-even-page-exists? (ldb/page-empty? @conn page-name))
-                             (let [pages    (if split-namespace?
-                                              (common-util/split-namespace-pages title)
-                                              [title])
-                                   format   (or format (common-config/get-preferred-format config))
-                                   pages    (map (fn [page]
-                                                   ;; only apply uuid to the deepest hierarchy of page to create if provided.
-                                                   (-> (gp-block/page-name->map page (if (= page title) with-uuid? true) @conn true date-formatter :class? class?)
-                                                       (assoc :block/format format)))
-                                                 pages)
-                                   txs      (when-not db-based?
-                                              (->> pages
-                                                   ;; for namespace pages, only last page need properties
-                                                   drop-last
-                                                   (mapcat #(build-page-tx repo conn config date-formatter format nil % {}))
-                                                   (remove nil?)))
-                                   txs      (when-not db-based?
-                                              (map-indexed (fn [i page]
-                                                             (if (zero? i)
-                                                               page
-                                                               (assoc page :block/namespace
-                                                                      [:block/uuid (:block/uuid (nth txs (dec i)))])))
-                                                           txs))
-                                   txs      (when-not db-based?
-                                              (map-indexed (fn [i page]
-                                                             (if (zero? i)
-                                                               page
-                                                               (assoc page :block/namespace
-                                                                      [:block/uuid (:block/uuid (nth txs (dec i)))])))
-                                                           txs))
-                                   page-uuid (:block/uuid (last pages))
-                                   page-txs (build-page-tx repo conn config date-formatter format properties (last pages) (select-keys options [:whiteboard? :class? :tags]))
-                                   page-txs (if (and (seq txs) (not db-based?))
-                                              (update page-txs 0
-                                                      (fn [p]
-                                                        (assoc p :block/namespace [:block/uuid (:block/uuid (last txs))])))
-                                              page-txs)
-                                   first-block-tx (when (and
-                                                         create-first-block?
-                                                         (not (or whiteboard? class?))
-                                                         page-txs)
-                                                    (let [page-id [:block/uuid (:block/uuid (first page-txs))]]
-                                                      [(sqlite-util/block-with-timestamps
-                                                        {:block/uuid (ldb/new-block-id)
-                                                         :block/page page-id
-                                                         :block/parent page-id
-                                                         :block/order (db-order/gen-key nil nil)
-                                                         :block/content ""
-                                                         :block/format format})]))
-                                   txs      (concat
-                                             txs
-                                             page-txs
-                                             first-block-tx)]
-                               (when (seq txs)
-                                 [page-uuid (ldb/transact! conn txs (cond-> {:persist-op? persist-op?
-                                                                             :outliner-op :create-page}
-                                                                      today-journal?
-                                                                      (assoc :create-today-journal? true
-                                                                             :today-journal-name page-name)))])))] ;; FIXME: prettier validation
-    [result page-name page-uuid]))
+  TODO: Add other options"
+  [repo conn config title & options]
+  (if (ldb/db-based-graph? @conn)
+    (db-based-create! repo conn config title options)
+    (file-based-create! repo conn config title options)))
 
 (defn db-refs->page
   "Replace [[page name]] with page name"

+ 2 - 5
src/main/frontend/worker/rtc/remote_update.cljs

@@ -478,11 +478,8 @@
     (doseq [{:keys [self _page-name]
              original-name :block/original-name
              :as op-value} update-page-ops]
-      (let [create-opts {:create-first-block? false
-                         :uuid self
-                         :persist-op? false
-                         :create-even-page-exists? true}
-            [_ x y] (worker-page/create! repo conn config (ldb/read-transit-str original-name) create-opts)]
+      (let [create-opts {:uuid self}
+            [_ x y] (worker-page/rtc-create-page! conn config (ldb/read-transit-str original-name) create-opts)]
         ;; TODO: current page-create fn is buggy, even provide :uuid option, it will create-page with different uuid,
         ;; if there's already existing same name page
         (prn :debug-create-page x y self)