Browse Source

feat: rename a page will rename corresponding namespace pages and files (#2283)

* feat: rename a page will rename corresponding namespace pages

and files.

* enhance: jump to namespace page instead of the [[page]] itself

* namespace: create prefix ns pages instead of pages themselve

* fix: only rename files when namespace prefix matches
Tienson Qin 4 years ago
parent
commit
e43cf125f6

+ 6 - 3
src/main/frontend/components/block.cljs

@@ -392,7 +392,9 @@
           href (if html-export?
                  (util/encode-str page)
                  (rfe/href :page {:name redirect-page-name}))
-          inner (page-inner config page-name href redirect-page-name page-entity contents-page? children html-export? label)]
+          inner (page-inner config
+                            page-name
+                            href redirect-page-name page-entity contents-page? children html-export? label)]
       (if (and (not (util/mobile?)) (not preview?))
         (ui/tippy {:html        (fn []
                                   [:div.tippy-wrapper.overflow-y-auto.p-4
@@ -401,7 +403,7 @@
                                             :font-weight    500
                                             :max-height     600
                                             :padding-bottom 64}}
-                                   (if (string/includes? page-original-name "/")
+                                   (if (and (string? page-original-name) (string/includes? page-original-name "/"))
                                      [:div.my-2
                                       (->>
                                        (for [page (string/split page-original-name #"/")]
@@ -474,7 +476,8 @@
        (let [s (string/trim s)]
          (page-cp (assoc config
                          :label (mldoc/plain->text label)
-                         :contents-page? contents-page?) {:block/name s}))
+                         :contents-page? contents-page?)
+                  {:block/name s}))
        (when (and (or show-brackets? nested-link?)
                   (not html-export?)
                   (not contents-page?))

+ 1 - 2
src/main/frontend/components/diff.cljs

@@ -6,7 +6,6 @@
             [frontend.handler.file :as file]
             [frontend.handler.notification :as notification]
             [frontend.handler.common :as common-handler]
-            [frontend.handler.file :as file-handler]
             [frontend.state :as state]
             [clojure.string :as string]
             [frontend.db :as db]
@@ -54,7 +53,7 @@
   {:will-mount (fn [state]
                  (let [*local-content (atom "")
                        [repo _ path & _others] (:rum/args state)]
-                   (p/let [content (file-handler/load-file repo path )]
+                   (p/let [content (file/load-file repo path )]
                      (reset! *local-content content))
                    (assoc state ::local-content *local-content)))}
   [state repo type path contents remote-oid]

+ 9 - 3
src/main/frontend/components/hierarchy.cljs

@@ -3,7 +3,8 @@
             [clojure.string :as string]
             [frontend.components.block :as block]
             [rum.core :as rum]
-            [frontend.ui :as ui]))
+            [frontend.ui :as ui]
+            [medley.core :as medley]))
 
 (defn get-relation
   ([page]
@@ -29,8 +30,13 @@
          (for [namespace namespaces]
            [:li.my-2
             (->>
-             (for [page namespace]
+             (for [[idx page] (medley/indexed namespace)]
                (when (and (string? page) page)
-                 (block/page-reference false page {} nil)))
+                 (let [full-page (->> (take (inc idx) namespace)
+                                      (string/join "/"))]
+                   (block/page-reference false
+                                         full-page
+                                         {}
+                                         page))))
              (interpose [:span.mx-2.opacity-30 "/"]))])]
         true)])))

+ 0 - 1
src/main/frontend/components/page.cljs

@@ -3,7 +3,6 @@
             [frontend.util :as util :refer [profile]]
             [frontend.util.marker :as marker]
             [frontend.tools.html-export :as html-export]
-            [frontend.handler.file :as file]
             [frontend.handler.page :as page-handler]
             [frontend.handler.ui :as ui-handler]
             [frontend.handler.common :as common-handler]

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

@@ -50,7 +50,7 @@
   get-pages get-pages-relation get-pages-that-mentioned-page get-public-pages get-tag-pages
   journal-page? local-native-fs? mark-repo-as-cloned! page-alias-set page-blocks-transform pull-block
   set-file-last-modified-at! transact-files-db! with-block-refs-count get-modified-pages page-empty? page-empty-or-dummy? get-alias-source-page
-  set-file-content! has-children?]
+  set-file-content! has-children? get-namespace-files]
 
  [frontend.db.react
   get-current-marker get-current-page get-current-priority set-key-value

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

@@ -1251,3 +1251,17 @@
            (conn/get-conn repo)
            page-id)
       ffirst))
+
+(defn get-namespace-files
+  [repo namespace]
+  (assert (string? namespace))
+  (let [db (conn/get-conn repo)
+        namespace (string/replace namespace "/" ".")]
+    (when-not (string/blank? namespace)
+     (let [namespace (string/trim namespace)
+           pattern-1 (re-pattern (util/format "[\\.|/]%s\\." namespace))
+           pattern-2 (re-pattern (util/format "^%s\\." namespace))]
+       (->> (d/datoms db :aevt :file/path)
+            (filter (fn [datom]
+                      (or (re-find pattern-1 (:v datom))
+                          (re-find pattern-2 (:v datom))))))))))

+ 2 - 0
src/main/frontend/db_schema.cljs

@@ -97,6 +97,8 @@
    ;; whether page's is a journal
    :block/journal? {}
    :block/journal-day {}
+   ;; page's namespace
+   :block/namespace {:db/valueType :db.type/ref}
 
    ;; block's file
    :block/file {:db/valueType :db.type/ref}

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

@@ -278,7 +278,7 @@
                                                    (not (string/starts-with? p "../"))
                                                    (not (string/starts-with? p "./"))
                                                    (not (string/starts-with? p "http")))
-                                          (string/split p #"/")))
+                                          (util/split-namespace-pages p)))
                                       refs)
                               (remove string/blank?))
           refs (->> (distinct (concat refs children-pages))

+ 1 - 3
src/main/frontend/handler/external.cljs

@@ -13,7 +13,6 @@
             [frontend.handler.page :as page]
             [frontend.handler.editor :as editor]))
 
-(defonce debug-files (atom nil))
 (defn index-files!
   [repo files finish-handler]
   (let [titles (->> files
@@ -35,8 +34,7 @@
                            {:file/path path
                             :file/content text}))))
                    files)
-        files (remove nil? files)
-        _ (reset! debug-files files)]
+        files (remove nil? files)]
     (repo-handler/parse-files-and-load-to-db! repo files nil)
     (let [files (map (fn [{:file/keys [path content]}] [path content]) files)]
       (file-handler/alter-files repo files {:add-history? false

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

@@ -71,7 +71,7 @@
            :or {redirect? true
                 create-first-block? true}}]
    (let [title (string/trim title)
-         pages (string/split title #"/")
+         pages (util/split-namespace-pages title)
          page (string/lower-case title)
          format (state/get-preferred-format)
          pages (map (fn [page]
@@ -203,6 +203,16 @@
         parts (concat (butlast result) [new-file])]
     (string/join "/" parts)))
 
+(defn- rename-file-aux!
+  [repo old-path new-path]
+  (fs/rename! repo
+              (if (util/electron?)
+                old-path
+                (str (config/get-repo-dir repo) "/" old-path))
+              (if (util/electron?)
+                new-path
+                (str (config/get-repo-dir repo) "/" new-path))))
+
 (defn rename-file!
   [file new-name ok-handler]
   (let [repo (state/get-current-repo)
@@ -213,13 +223,7 @@
     (db/transact! repo [{:db/id (:db/id file)
                          :file/path new-path}])
     (->
-     (p/let [_ (fs/rename! repo
-                           (if (util/electron?)
-                             old-path
-                             (str (config/get-repo-dir repo) "/" old-path))
-                           (if (util/electron?)
-                             new-path
-                             (str (config/get-repo-dir repo) "/" new-path)))
+     (p/let [_ (rename-file-aux! repo old-path new-path)
              _ (when-not (config/local-db? repo)
                  (git/rename repo old-path new-path))]
        (common-handler/check-changed-files-status)
@@ -258,6 +262,43 @@
                      f))
                  form))
 
+(defn- build-new-namespace-page-title
+  [old-page-title old-name new-name]
+  (string/replace-first old-page-title old-name new-name))
+
+;; FIXME: get namespace pages instead of files for compatibility with the
+;; database-only version.
+(defn- rename-namespace-pages!
+  [repo old-name new-name]
+  (doseq [datom (db/get-namespace-files repo old-name)]
+    (let [old-path (:v datom)
+          path-old-name (string/replace old-name "/" ".")
+          path-new-name (string/replace new-name "/" ".")
+          [search replace] (cond
+                             (string/includes? old-path (str "." path-old-name "."))
+                             [(str "." path-old-name ".") (str "." path-new-name ".")]
+
+                             (string/includes? old-path (str "/" path-old-name "."))
+                             [(str "/" path-old-name ".") (str "/" path-new-name ".")]
+
+                             :else
+                             [(str path-old-name ".") (str path-new-name ".")])
+          new-path (string/replace-first old-path search replace)
+          tx {:db/id (:e datom)
+              :file/path new-path}
+          page (db/entity (db/get-file-page-id old-path))
+          page-tx (when page
+                    (let [old-page-title (or (:block/original-name page)
+                                             (:block/name page))
+                          new-page-title (build-new-namespace-page-title old-page-title old-name new-name)]
+                      {:db/id (:db/id page)
+                       :block/original-name new-page-title
+                       :block/name (string/lower-case new-page-title)}))
+          txs (->> [tx page-tx] (remove nil?))]
+      (db/transact! repo txs)
+      (p/let [_ (rename-file-aux! repo old-path new-path)]
+        (println "Renamed " old-path " to " new-path ".")))))
+
 (defn rename!
   [old-name new-name]
   (let [new-name (string/trim new-name)]
@@ -324,6 +365,8 @@
 
                     (outliner-file/sync-to-file page))
 
+                  (rename-namespace-pages! repo old-name new-name)
+
                   ;; TODO: update browser history, remove the current one
 
                   ;; Redirect to the new page

+ 11 - 0
src/main/frontend/util.cljc

@@ -1284,6 +1284,17 @@
   [text]
   (string/join (replace regex-char-esc-smap text)))
 
+(defn split-namespace-pages
+  [title]
+  (let [parts (string/split title "/")]
+    (loop [others (rest parts)
+           result [(first parts)]]
+      (if (seq others)
+        (let [prev (last result)]
+          (recur (rest others)
+                 (conj result (str prev "/" (first others)))))
+        result))))
+
 (comment
   (re-matches (re-pattern (regex-escape "$u^8(d)+w.*[dw]d?")) "$u^8(d)+w.*[dw]d?"))