Browse Source

fix: more redirects use uuid instead of page name

Tienson Qin 1 year ago
parent
commit
5f08e17a85

+ 6 - 7
src/main/frontend/components/class.cljs

@@ -37,9 +37,9 @@
                {:on-pointer-down
                 (fn [e]
                   (when (util/meta-key? e)
-                    (if-let [page-name (:block/name (db/entity [:block/uuid (some-> (util/evalue e) uuid)]))]
+                    (if-let [page (db/entity [:block/uuid (some-> (util/evalue e) uuid)])]
                       (do
-                        (route-handler/redirect-to-page! page-name)
+                        (route-handler/redirect-to-page! (:block/uuid page))
                         (.preventDefault e))
                       (js/console.error "No selected option found to navigate to"))))})))
 
@@ -75,10 +75,9 @@
         (if config/publishing?
           [:div.col-span-3
            (if-let [parent-class (some-> (:db/id (:class/parent page))
-                                         db/entity
-                                         :block/original-name)]
-             [:a {:on-click #(route-handler/redirect-to-page! parent-class)}
-              parent-class]
+                                         db/entity)]
+             [:a {:on-click #(route-handler/redirect-to-page! (:block/uuid parent-class))}
+              (:block/original-name parent-class)]
              "None")]
           [:div.col-span-3
            (let [parent (some-> (:db/id (:class/parent page))
@@ -99,7 +98,7 @@
                           (map (fn [class-name]
                                  (if (= class-name (:block/original-name page))
                                    [:span class-name]
-                                   [:a {:on-click #(route-handler/redirect-to-page! class-name)} class-name]))
+                                   [:a {:on-click #(route-handler/redirect-to-page! (:block/uuid page))} class-name]))
                                class-ancestors))]])))])))
 
 (defn class-children-aux

+ 13 - 17
src/main/frontend/components/cmdk.cljs

@@ -386,11 +386,8 @@
 (defmethod handle-action :open-page [_ state _event]
   (when-let [page-name (get-highlighted-page-name state)]
     (let [redirect-page-name (model/get-redirect-page-name page-name)
-          page (db/get-page redirect-page-name)
-          original-name (:block/original-name page)]
-      (if (= (:block/type page) "whiteboard")
-        (route-handler/redirect-to-page! original-name)
-        (route-handler/redirect-to-page! original-name)))
+          page (db/get-page redirect-page-name)]
+      (route-handler/redirect-to-page! (:block/uuid page)))
     (state/close-modal!)))
 
 (defmethod handle-action :open-block [_ state _event]
@@ -398,18 +395,17 @@
     (p/let [repo (state/get-current-repo)
             _ (db-async/<get-block repo block-id :children? false)]
       (let [get-block-page (partial model/get-block-page repo)
-           block (db/entity [:block/uuid block-id])]
-       (when block
-         (when-let [page (some-> block-id get-block-page)]
-           (let [page-name (:block/name page)]
-             (cond
-               (= (:block/type page) "whiteboard")
-               (route-handler/redirect-to-page! page-name {:block-id block-id})
-               (model/parents-collapsed? (state/get-current-repo) block-id)
-               (route-handler/redirect-to-page! block-id)
-               :else
-               (route-handler/redirect-to-page! page-name {:anchor (str "ls-block-" block-id)})))
-           (state/close-modal!)))))))
+            block (db/entity [:block/uuid block-id])]
+        (when block
+          (when-let [page (some-> block-id get-block-page)]
+            (cond
+              (db/whiteboard-page? page)
+              (route-handler/redirect-to-page! (:block/uuid page) {:block-id block-id})
+              (model/parents-collapsed? (state/get-current-repo) block-id)
+              (route-handler/redirect-to-page! block-id)
+              :else
+              (route-handler/redirect-to-page! (:block/uuid page) {:anchor (str "ls-block-" block-id)}))
+            (state/close-modal!)))))))
 
 (defmethod handle-action :open-page-right [_ state _event]
   (when-let [page-name (get-highlighted-page-name state)]

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

@@ -1024,7 +1024,7 @@
        (for [[n {:block/keys [name created-at updated-at backlinks] :as page}] (medley/indexed pages)]
          [:tr {:key name}
           [:td.n.w-12 [:span.opacity-70 (str (inc n) ".")]]
-          [:td.name [:a {:href     (rfe/href :page {:name (:block/name page)})}
+          [:td.name [:a {:href     (rfe/href :page {:name (str (:block/uuid page))})}
                      (component-block/page-cp {} page)]]
           [:td.backlinks [:span (or backlinks "0")]]
           (when-not orphaned-pages? [:td.created-at [:span (if created-at (date/int->local-time-2 created-at) "Unknown")]])
@@ -1046,7 +1046,7 @@
                                                                     {:error-handler
                                                                      (fn []
                                                                        (swap! failed-pages conj (:block/name page)))}))
-                                        pages))]
+                                           pages))]
                        (if (seq @failed-pages)
                          (notification/show! (t :all-pages/failed-to-delete-pages (string/join ", " (map pr-str @failed-pages)))
                                              :warning false)
@@ -1084,16 +1084,16 @@
          (ui/icon "chevrons-right")]])]))
 
 (rum/defcs ^:large-vars/cleanup-todo all-pages < rum/reactive
-                                                 (rum/local nil ::pages)
-                                                 (rum/local nil ::search-key)
-                                                 (rum/local nil ::results-all)
-                                                 (rum/local nil ::results)
-                                                 (rum/local {} ::checks)
-                                                 (rum/local :block/updated-at ::sort-by-item)
-                                                 (rum/local true ::desc?)
-                                                 (rum/local {:journals? false :page-type ""} ::filters)
-                                                 (rum/local nil ::filter-fn)
-                                                 (rum/local 1 ::current-page)
+  (rum/local nil ::pages)
+  (rum/local nil ::search-key)
+  (rum/local nil ::results-all)
+  (rum/local nil ::results)
+  (rum/local {} ::checks)
+  (rum/local :block/updated-at ::sort-by-item)
+  (rum/local true ::desc?)
+  (rum/local {:journals? false :page-type ""} ::filters)
+  (rum/local nil ::filter-fn)
+  (rum/local 1 ::current-page)
   [state]
   (let [current-repo (state/sub :git/current-repo)
         per-page-num 40
@@ -1111,21 +1111,21 @@
 
         ;; TODO: remove this
         *indeterminate (rum/derived-atom
-                         [*checks] ::indeterminate
-                         (fn [checks]
-                           (when-let [checks (vals checks)]
-                             (if (every? true? checks)
-                               1 (if (some true? checks) -1 0)))))
+                        [*checks] ::indeterminate
+                        (fn [checks]
+                          (when-let [checks (vals checks)]
+                            (if (every? true? checks)
+                              1 (if (some true? checks) -1 0)))))
 
         mobile? (util/mobile?)
         total-items (count @*results-all)
         ;; FIXME: "pages" is ambiguous here, it can be either "Logseq pages" or "result pages"
         total-pages (if-not @*results-all 0
-                                          (js/Math.ceil (/ total-items per-page-num)))
+                            (js/Math.ceil (/ total-items per-page-num)))
         to-page (fn [page]
                   (when (> total-pages 1)
                     (if (and (> page 0)
-                          (<= page total-pages))
+                             (<= page total-pages))
                       (reset! *current-page page)
                       (reset! *current-page 1))
                     (js/setTimeout #(util/scroll-to-top))))
@@ -1133,7 +1133,7 @@
         search-key (fn [key]
                      (when-let [key (and key (string/trim key))]
                        (if (and (not (string/blank? key))
-                             (seq @*results))
+                                (seq @*results))
                          (reset! *search-key key)
                          (reset! *search-key nil))))
 
@@ -1151,18 +1151,18 @@
        ;; all pages
        (when (nil? @*pages)
          (let [pages (->> (page-handler/get-all-pages current-repo)
-                       (map-indexed (fn [idx page] (assoc page
-                                                     :block/backlinks (count (:block/_refs (db/entity (:db/id page))))
-                                                     :block/idx idx))))]
+                          (map-indexed (fn [idx page] (assoc page
+                                                             :block/backlinks (count (:block/_refs (db/entity (:db/id page))))
+                                                             :block/idx idx))))]
            (reset! *filter-fn
-             (memoize (fn [sort-by-item desc? {:keys [journal? page-type]}]
-                        (->> pages
-                          (filter #(and
-                                     (or (boolean journal?)
-                                       (= false (boolean (:block/journal? %))))
-                                     (or (empty? page-type)
-                                       (contains? (set (:block/type %)) page-type))))
-                          (sort-pages-by sort-by-item desc?)))))
+                   (memoize (fn [sort-by-item desc? {:keys [journal? page-type]}]
+                              (->> pages
+                                   (filter #(and
+                                             (or (boolean journal?)
+                                                 (= false (boolean (:block/journal? %))))
+                                             (or (empty? page-type)
+                                                 (contains? (set (:block/type %)) page-type))))
+                                   (sort-pages-by sort-by-item desc?)))))
            (reset! *pages pages)))
 
        ;; filter results
@@ -1172,8 +1172,8 @@
                ;; search key
                pages (if-not (string/blank? @*search-key)
                        (search/fuzzy-search pages (util/page-name-sanity-lc @*search-key)
-                         :limit 20
-                         :extract-fn :block/name)
+                                            :limit 20
+                                            :extract-fn :block/name)
                        pages)
 
                _ (reset! *results-all pages)
@@ -1187,24 +1187,24 @@
        [:div.cp__all_pages-content
         [:div.actions.pt-4
          {:class (util/classnames [{:has-selected (or (nil? @*indeterminate)
-                                                    (not= 0 @*indeterminate))}])}
+                                                      (not= 0 @*indeterminate))}])}
          [:div.l.flex.items-center
           [:div.actions-wrap
            (ui/button
-             (t :delete)
-             {:on-click
-              (fn []
-                (let [selected (filter (fn [[_ v]] v) @*checks)
-                      selected (and (seq selected)
-                                 (into #{} (for [[k _] selected] k)))]
-                  (when-let [pages (and selected (filter #(contains? selected (:block/idx %)) @*results))]
-                    (state/set-modal! (batch-delete-dialog pages false #(do
-                                                                          (reset! *checks nil)
-                                                                          (refresh-pages)))))))
-              :icon "trash"
-              :variant :destructive
-              :icon-props {:size 14}
-              :size :sm})]
+            (t :delete)
+            {:on-click
+             (fn []
+               (let [selected (filter (fn [[_ v]] v) @*checks)
+                     selected (and (seq selected)
+                                   (into #{} (for [[k _] selected] k)))]
+                 (when-let [pages (and selected (filter #(contains? selected (:block/idx %)) @*results))]
+                   (state/set-modal! (batch-delete-dialog pages false #(do
+                                                                         (reset! *checks nil)
+                                                                         (refresh-pages)))))))
+             :icon "trash"
+             :variant :destructive
+             :icon-props {:size 14}
+             :size :sm})]
 
           [:div.search-wrap.flex.items-center.pl-2
            (let [search-fn (fn []
@@ -1217,9 +1217,9 @@
                               (reset! *search-key nil)))]
 
              [(ui/button (ui/icon "search")
-                :on-click search-fn
-                :variant :link
-                :size :xs)
+                         :on-click search-fn
+                         :variant :link
+                         :size :xs)
               [:input.form-input {:placeholder   (t :search/page-names)
                                   :on-key-up     (fn [^js e]
                                                    (let [^js target (.-target e)]
@@ -1240,63 +1240,63 @@
            (ui/select (->> (if (config/db-based-graph? current-repo)
                              ["" "class" "property" "whiteboard"]
                              ["" "whiteboard"])
-                        (map (fn [block-type]
-                               {:label (if (seq block-type) (string/capitalize block-type) "Filter by page type")
-                                :selected (= block-type type)
-                                :disabled config/publishing?
-                                :value block-type})))
-             (fn [_e value]
-               (swap! *filters assoc :page-type value)))]
+                           (map (fn [block-type]
+                                  {:label (if (seq block-type) (string/capitalize block-type) "Filter by page type")
+                                   :selected (= block-type type)
+                                   :disabled config/publishing?
+                                   :value block-type})))
+                      (fn [_e value]
+                        (swap! *filters assoc :page-type value)))]
           [:div
            (ui/tippy
-             {:html  [:small (t :page/show-journals)]
-              :arrow true}
-             [:a.button.journal
-              {:class    (util/classnames [{:active (boolean (:journal? @*filters))}])
-               :on-click #(swap! *filters update :journal? not)}
-              (ui/icon "calendar" {:size ui/icon-size})])]
+            {:html  [:small (t :page/show-journals)]
+             :arrow true}
+            [:a.button.journal
+             {:class    (util/classnames [{:active (boolean (:journal? @*filters))}])
+              :on-click #(swap! *filters update :journal? not)}
+             (ui/icon "calendar" {:size ui/icon-size})])]
 
           [:div.paginates
            (pagination :current @*current-page
-             :total total-items
-             :per-page per-page-num
-             :on-change #(to-page %))]
+                       :total total-items
+                       :per-page per-page-num
+                       :on-change #(to-page %))]
 
           (ui/dropdown-with-links
-            (fn [{:keys [toggle-fn]}]
-              [:a.button.fade-link
-               {:on-click toggle-fn}
-               (ui/icon "dots" {:size ui/icon-size})])
-            [{:title (t :remove-orphaned-pages)
-              :options {:on-click (fn []
-                                    (let [orphaned-pages (model/get-orphaned-pages {})
-                                          orphaned-pages? (seq orphaned-pages)]
-                                      (if orphaned-pages?
-                                        (state/set-modal!
-                                          (batch-delete-dialog
-                                            orphaned-pages  true
-                                            #(do
-                                               (reset! *checks nil)
-                                               (refresh-pages))))
-                                        (notification/show! "Congratulations, no orphaned pages in your graph!" :success))))}
-              :icon (ui/icon "file-x")}
-             {:title (t :all-files)
-              :options {:href (rfe/href :all-files)}
-              :icon (ui/icon "files")}]
-            {})]]
+           (fn [{:keys [toggle-fn]}]
+             [:a.button.fade-link
+              {:on-click toggle-fn}
+              (ui/icon "dots" {:size ui/icon-size})])
+           [{:title (t :remove-orphaned-pages)
+             :options {:on-click (fn []
+                                   (let [orphaned-pages (model/get-orphaned-pages {})
+                                         orphaned-pages? (seq orphaned-pages)]
+                                     (if orphaned-pages?
+                                       (state/set-modal!
+                                        (batch-delete-dialog
+                                         orphaned-pages  true
+                                         #(do
+                                            (reset! *checks nil)
+                                            (refresh-pages))))
+                                       (notification/show! "Congratulations, no orphaned pages in your graph!" :success))))}
+             :icon (ui/icon "file-x")}
+            {:title (t :all-files)
+             :options {:href (rfe/href :all-files)}
+             :icon (ui/icon "files")}]
+           {})]]
 
         [:table.table-auto.cp__all_pages_table
          [:thead
           [:tr
            [:th.selector
             (checkbox-opt "all-pages-select-all"
-              (= 1 @*indeterminate)
-              {:on-change     (fn []
-                                (let [indeterminate? (= -1 @*indeterminate)
-                                      all? (= 1 @*indeterminate)]
-                                  (doseq [{:block/keys [idx]} @*results]
-                                    (swap! *checks assoc idx (or indeterminate? (not all?))))))
-               :indeterminate (when (= -1 @*indeterminate) "indeterminate")})]
+                          (= 1 @*indeterminate)
+                          {:on-change     (fn []
+                                            (let [indeterminate? (= -1 @*indeterminate)
+                                                  all? (= 1 @*indeterminate)]
+                                              (doseq [{:block/keys [idx]} @*results]
+                                                (swap! *checks assoc idx (or indeterminate? (not all?))))))
+                           :indeterminate (when (= -1 @*indeterminate) "indeterminate")})]
            [:th.icon ""]
            (sortable-title (t :block/name) :block/name *sort-by-item *desc?)
            (when-not mobile?
@@ -1310,9 +1310,9 @@
               [:tr {:key name}
                [:td.selector
                 (checkbox-opt (str "label-" idx)
-                  (get @*checks idx)
-                  {:on-change (fn []
-                                (swap! *checks update idx not))})]
+                              (get @*checks idx)
+                              {:on-change (fn []
+                                            (swap! *checks update idx not))})]
                [:td.icon.w-4.p-0.overflow-hidden
                 (when-let [icon (:logseq.property/icon page)]
                   icon)]
@@ -1321,10 +1321,10 @@
                                           (let [repo (state/get-current-repo)]
                                             (when (gobj/get e "shiftKey")
                                               (state/sidebar-add-block!
-                                                repo
-                                                (:db/id page)
-                                                :page))))
-                              :href     (rfe/href :page {:name (:block/name page)})}
+                                               repo
+                                               (:db/id page)
+                                               :page))))
+                              :href     (rfe/href :page {:name (str (:block/uuid page))})}
                           (component-block/page-cp {} page)]]
 
                (when-not mobile?
@@ -1338,6 +1338,6 @@
 
         [:div.flex.justify-end.py-4
          (pagination :current @*current-page
-           :total total-items
-           :per-page per-page-num
-           :on-change #(to-page %))]])]))
+                     :total total-items
+                     :per-page per-page-num
+                     :on-change #(to-page %))]])]))

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

@@ -597,7 +597,7 @@
 
      (if config/publishing?
        [:a.property-k.flex.select-none.jtrigger.pl-2
-        {:on-click #(route-handler/redirect-to-page! (:block/name property))}
+        {:on-click #(route-handler/redirect-to-page! (:block/uuid property))}
         (:block/original-name property)]
 
        (shui/trigger-as :a
@@ -606,7 +606,7 @@
                          :class "property-k flex select-none jtrigger pl-2"
                          :on-pointer-down (fn [^js e]
                                             (when (util/meta-key? e)
-                                              (route-handler/redirect-to-page! (:block/name property))
+                                              (route-handler/redirect-to-page! (:block/uuid property))
                                               (.preventDefault e)))
                          :on-click (fn [^js e]
                                      (shui/popup-show!

+ 6 - 8
src/main/frontend/components/right_sidebar.cljs

@@ -168,14 +168,13 @@
                          :on-input-change (fn [new-value]
                                             (reset! *db-id new-value))
                          :on-input-blur (fn [new-value]
-                                            (state/sidebar-replace-block! [repo db-id block-type]
-                                                                          [repo new-value block-type]))})
+                                          (state/sidebar-replace-block! [repo db-id block-type]
+                                                                        [repo new-value block-type]))})
        (str init-key))]
 
     :page-slide-view
-    (let [page (db/entity db-id)
-          page-name (:block/name page)]
-      [[:a.page-title {:href (rfe/href :page {:name page-name})}
+    (let [page (db/entity db-id)]
+      [[:a.page-title {:href (rfe/href :page {:name (str (:block/uuid page))})}
         (:block/original-name page)]
        [:div.ml-2.slide.mt-2
         (slide/slide page)]])
@@ -218,9 +217,8 @@
      (when multi-items? (menu-item {:on-click #(state/sidebar-block-set-collapsed-all! false)} (t :right-side-bar/pane-expand-all)))
      (when (= type :page) [:hr.menu-separator])
      (when (= type :page)
-       (let [page  (db/entity db-id)
-             name (:block/name page)]
-         (menu-item {:href (rfe/href :page {:name name})} (t :right-side-bar/pane-open-as-page)))))))
+       (let [page  (db/entity db-id)]
+         (menu-item {:href (rfe/href :page {:name (str (:block/uuid page))})} (t :right-side-bar/pane-open-as-page)))))))
 
 (rum/defc drop-indicator
   [idx drag-to]

+ 1 - 1
src/main/frontend/extensions/zotero/handler.cljs

@@ -60,7 +60,7 @@
                       :sibling? false}))))
 
 (defn- create-page [page-name properties]
-  (page-handler/create!
+  (page-handler/<create!
    page-name
    {:redirect? false
     :format :markdown

+ 6 - 9
src/main/frontend/handler/common/page.cljs

@@ -41,12 +41,10 @@
    (let [repo (state/get-current-repo)
          conn (db/get-db repo false)
          config (state/get-config repo)
-         ;; FIXME: create! returns page-entity
-         [_ page-name] (worker-page/create! repo conn config title options)]
+         [_ page-name page-uuid] (worker-page/create! repo conn config title options)]
      (when redirect?
-       ;; FIXME: use uuid instead
-       (route-handler/redirect-to-page! page-name))
-     (when-let [first-block (first (:block/_left (db/get-page page-name)))]
+       (route-handler/redirect-to-page! page-uuid))
+     (when-let [first-block (first (:block/_left (db/get-page page-uuid)))]
        (block-handler/edit-block! first-block :max nil))
      page-name)))
 
@@ -59,12 +57,11 @@
    (p/let [repo (state/get-current-repo)
            conn (db/get-db repo false)
            config (state/get-config repo)
-           [p page-name] (worker-page/create! repo conn config title options)
+           [p _page-name page-uuid] (worker-page/create! repo conn config title options)
            _result p]
      (when redirect?
-       ;; FIXME: use uuid instead
-       (route-handler/redirect-to-page! page-name))
-     (let [page (db/get-page page-name)]
+       (route-handler/redirect-to-page! page-uuid))
+     (let [page (db/get-page page-uuid)]
        (when-let [first-block (first (:block/_left page))]
          (block-handler/edit-block! first-block :max nil))
        page))))

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

@@ -197,7 +197,7 @@
                              "/"
                              (get-file-name journal? page)
                              ".org")]
-          (create! page {:redirect? false})
+          (<create! page {:redirect? false})
           (util/format "[[file:%s][%s]]"
                        (util/get-relative-path edit-block-file-path ref-file-path)
                        page)))

+ 2 - 10
src/main/frontend/modules/editor/undo_redo.cljs

@@ -153,11 +153,7 @@
           editor-cursor (:before (get @(get @state/state :history/tx->editor-cursor) tx-id))]
       (push-redo e)
       (p/do!
-       (transact! new-txs (assoc tx-meta :undo? true))
-
-       (when (= :rename-page (:outliner-op tx-meta))
-         (when-let [old-page (:old-name (:data tx-meta))]
-           (route-handler/redirect-to-page! old-page))))
+       (transact! new-txs (assoc tx-meta :undo? true)))
       (assoc e
              :txs-op new-txs
              :editor-cursor editor-cursor))))
@@ -174,11 +170,7 @@
                             (or (:after s) (:before s))))]
       (push-undo e)
       (p/do!
-       (transact! new-txs (assoc tx-meta :redo? true))
-
-       (when (= :rename-page (:outliner-op tx-meta))
-         (when-let [new-page (:new-name (:data tx-meta))]
-           (route-handler/redirect-to-page! new-page))))
+       (transact! new-txs (assoc tx-meta :redo? true)))
 
       (assoc e
              :txs-op new-txs

+ 31 - 34
src/main/frontend/worker/handler/page.cljs

@@ -79,40 +79,37 @@
   (let [date-formatter (common-config/get-date-formatter config)
         [title page-name] (get-title-and-pagename title)
         with-uuid? (if (uuid? uuid) uuid true)
-        result (when (ldb/page-empty? @conn page-name)
-                 (let [pages    [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)
-                                           (assoc :block/format format)))
-                                     pages)
-                       txs      (->> pages
-                                     (mapcat #(build-page-tx repo conn config date-formatter format nil % {}))
-                                     (remove nil?))
-                       page-txs (build-page-tx repo conn config date-formatter format properties (last pages) (select-keys options [:whiteboard? :class? :tags]))
-                       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/left page-id
-                                             :block/content ""
-                                             :block/format format})]))
-                       txs      (concat
-                                 txs
-                                 page-txs
-                                 first-block-tx)]
-                   (when (seq txs)
-                     (ldb/transact! conn txs (cond-> {:persist-op? persist-op?}
-                                               today-journal?
-                                               (assoc :create-today-journal? true
-                                                      :today-journal-name page-name))))))] ;; FIXME: prettier validation
-    [result page-name]))
+        [page-uuid result] (when (ldb/page-empty? @conn page-name)
+                             (let [format   (or format (common-config/get-preferred-format config))
+                                   page (-> (gp-block/page-name->map title with-uuid? @conn true date-formatter)
+                                            (assoc :block/format format))
+                                   page-uuid (:block/uuid page)
+                                   txs      (->> [page]
+                                                 (mapcat #(build-page-tx repo conn config date-formatter format nil % {}))
+                                                 (remove nil?))
+                                   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)
+                                                    (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/left page-id
+                                                         :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?}
+                                                                      today-journal?
+                                                                      (assoc :create-today-journal? true
+                                                                             :today-journal-name page-name)))])))] ;; FIXME: prettier validation
+    [result page-name page-uuid]))
 
 (defn db-refs->page
   "Replace [[page name]] with page name"