Przeglądaj źródła

feat: merging pages when renaming one page to the name of another page

Close #476
Tienson Qin 4 lat temu
rodzic
commit
dd83ce4c44

+ 16 - 13
src/main/frontend/components/page.cljs

@@ -209,25 +209,28 @@
                   (pdf-assets/human-hls-filename-display title)
                   (if fmt-journal? (date/journal-title->custom-format title) title))
           old-name (or title page-name)
-          confirm-fn (ui/make-confirm-modal
-                      {:title         "Do you really want to change the page name?"
-                       :on-confirm    (fn [_e {:keys [close-fn]}]
-                                        (close-fn)
-                                        (page-handler/rename! (or title page-name) @*title-value)
-                                        (reset! *edit? false))
-                       :on-cancel     (fn []
-                                        (reset! *title-value old-name)
-                                        (reset! *edit? true))})
+          confirm-fn (fn []
+                       (let [merge? (and (not= (string/lower-case page-name) (string/lower-case @*title-value))
+                                         (page-handler/page-exists? page-name)
+                                         (page-handler/page-exists? @*title-value))]
+                         (ui/make-confirm-modal
+                          {:title         (if merge?
+                                            (str "Page \"" @*title-value "\" already exists, merge them?")
+                                            "Do you really want to change the page name?")
+                           :on-confirm    (fn [_e {:keys [close-fn]}]
+                                            (close-fn)
+                                            (page-handler/rename! (or title page-name) @*title-value)
+                                            (reset! *edit? false))
+                           :on-cancel     (fn []
+                                            (reset! *title-value old-name)
+                                            (reset! *edit? true))})))
           blur-fn (fn [e]
                     (cond
                       (= old-name @*title-value)
                       nil
 
-                      (page-handler/page-exists? @*title-value)
-                      (notification/show! "Page already exists!" :error)
-
                       :else
-                      (state/set-modal! confirm-fn))
+                      (state/set-modal! (confirm-fn)))
                     (util/stop e))]
       (if @*edit?
         [:h1.title {:style {:margin-left -2}}

+ 5 - 1
src/main/frontend/components/sidebar.cljs

@@ -172,7 +172,11 @@
 
    (let [pages (->> (db/sub-key-value :recent/pages)
                     (remove string/blank?)
-                    (filter string?))]
+                    (filter string?)
+                    (map (fn [page] {:lowercase (string/lower-case page)
+                                    :page page}))
+                    (util/distinct-by :lowercase)
+                    (map :page))]
      [:ul.text-sm
       (for [name pages]
         (when-let [entity (db/entity [:block/name (util/safe-lower-case name)])]

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

@@ -1458,3 +1458,11 @@
   ([repo orphaned-pages]
    (let [transaction (mapv (fn [page] [:db/retractEntity (:db/id page)]) orphaned-pages)]
      (db-utils/transact! transaction))))
+
+(defn get-block-last-direct-child
+  [db-id]
+  (when-let [block (db-utils/entity db-id)]
+    (let [children (:block/_parent block)
+          all-left (set (concat (map (comp :db/id :block/left) children) [db-id]))
+          all-ids (set (map :db/id children))]
+      (first (set/difference all-ids all-left)))))

+ 50 - 8
src/main/frontend/handler/page.cljs

@@ -9,6 +9,8 @@
             [frontend.db :as db]
             [frontend.db-schema :as db-schema]
             [frontend.db.model :as model]
+            [frontend.db.utils :as db-utils]
+            [frontend.db.conn :as conn]
             [frontend.format.block :as block]
             [frontend.fs :as fs]
             [frontend.git :as git]
@@ -296,7 +298,7 @@
   (when page-name
     (when-let [repo (state/get-current-repo)]
       (let [page-name (string/lower-case page-name)
-            blocks (db/get-page-blocks page-name)
+            blocks (db/get-page-blocks-no-cache page-name)
             tx-data (mapv
                      (fn [block]
                        [:db.fn/retractEntity [:block/uuid (:block/uuid block)]])
@@ -317,7 +319,7 @@
 
         (unfavorite-page! page-name)
 
-        (ok-handler)
+        (when (fn? ok-handler) (ok-handler))
         (ui-handler/re-render-root!)))))
 
 (defn- rename-page-aux [old-name new-name]
@@ -420,6 +422,51 @@
           (p/let [_ (rename-page-aux old-page-title new-page-title)]
             (println "Renamed " old-page-title " to " new-page-title)))))))
 
+(defn page-exists?
+  [page-name]
+  (when page-name
+    (db/entity [:block/name (string/lower-case page-name)])))
+
+(defn merge-pages!
+  [from to]
+  (when (and (page-exists? from) (page-exists? to) (not= from to))
+    (let [to-id (:db/id (db/entity [:block/name (string/lower-case to)]))
+          from-id (:db/id (db/entity [:block/name (string/lower-case from)]))
+          from-first-child (some->> (db/pull from-id)
+                                    (outliner-core/block)
+                                    (outliner-tree/-get-down)
+                                    (outliner-core/get-data))
+          to-last-direct-child-id (model/get-block-last-direct-child to-id)
+          repo (state/get-current-repo)
+          conn (conn/get-conn repo false)
+          datoms (d/datoms @conn :avet :block/page from-id)
+          block-eids (mapv :e datoms)
+          blocks (db-utils/pull-many repo '[:db/id :block/page :block/path-refs :block/left :block/parent] block-eids)
+          tx-data (map (fn [block]
+                         (let [id (:db/id block)]
+                           (cond->
+                            {:db/id id
+                             :block/page {:db/id to-id}
+                             :block/path-refs (->> (:block/path-refs block)
+                                                   (remove #{{:db/id from-id}})
+                                                   (cons {:db/id to-id})
+                                                   (distinct)
+                                                   (vec))}
+
+                             (and from-first-child (= id (:db/id from-first-child)))
+                             (assoc :block/left {:db/id (or to-last-direct-child-id to-id)})
+
+                             (= (:block/parent block) {:db/id from-id})
+                             (assoc :block/parent {:db/id to-id})))) blocks)]
+      (d/transact! conn tx-data)
+      (outliner-file/sync-to-file {:db/id to-id}))
+
+    (delete! from nil)
+
+    (route-handler/redirect! {:to          :page
+                              :push        false
+                              :path-params {:name (string/lower-case to)}})))
+
 (defn rename!
   [old-name new-name]
   (let [repo          (state/get-current-repo)
@@ -438,7 +485,7 @@
           (rename-page-aux old-name new-name)
 
           (db/pull [:block/name (string/lower-case new-name)])
-          (notification/show! "Page already exists!" :error)
+          (merge-pages! old-name new-name)
 
           namespace
           (rename-namespace-pages! repo old-name new-name)
@@ -546,11 +593,6 @@
   [page-name filter-state]
   (page-property/add-property! page-name :filters filter-state))
 
-(defn page-exists?
-  [page-name]
-  (when page-name
-    (db/entity [:block/name page-name])))
-
 ;; Editor
 (defn page-not-exists-handler
   [input id q current-pos]

+ 1 - 1
src/main/frontend/search.cljs

@@ -114,7 +114,7 @@
 
 (defn page-search
   ([q]
-   (page-search q 3))
+   (page-search q 10))
   ([q limit]
    (when-let [repo (state/get-current-repo)]
      (let [q (string/lower-case q)