Browse Source

enhance(ux): able to move existing pages to Library

Tienson Qin 8 months ago
parent
commit
b348b031e4

+ 3 - 4
deps/shui/src/logseq/shui/base/core.cljs

@@ -44,13 +44,12 @@
     (apply button-base props' children)))
 
 (defn button-icon
-  [variant icon-name {:keys [icon-props size] :as props} child]
-
+  [variant icon-name {:keys [icon-props button-size] :as props} child]
   (button
-   (merge (dissoc props :icon-props :size)
+   (merge (dissoc props :icon-props :button-size)
           {:variant variant
            :data-button :icon
-           :style (when size {:width size :height size})})
+           :style (when button-size {:width button-size :height button-size})})
    (tabler-icon/root (name icon-name) (merge {:size 20} icon-props))
    child))
 

+ 71 - 0
src/main/frontend/components/library.cljs

@@ -0,0 +1,71 @@
+(ns frontend.components.library
+  "Library page"
+  (:require [clojure.string :as string]
+            [frontend.components.select :as components-select]
+            [frontend.db :as db]
+            [frontend.handler.db-based.property :as db-property-handler]
+            [frontend.handler.editor :as editor-handler]
+            [frontend.search :as search]
+            [frontend.state :as state]
+            [frontend.ui :as ui]
+            [logseq.shui.hooks :as hooks]
+            [logseq.shui.ui :as shui]
+            [promesa.core :as p]
+            [rum.core :as rum]))
+
+(rum/defc select-pages
+  [library-page]
+  (let [[result set-result!] (hooks/use-state nil)
+        [input set-input!] (hooks/use-state "")
+        [selected-choices set-selected-choices!] (hooks/use-state #{})
+        items (map (fn [block]
+                     {:value (:db/id block)
+                      :label (:block/title block)})
+                   result)]
+    (hooks/use-effect!
+     (fn []
+       (if (string/blank? input)
+         (set-result! nil)
+         (p/let [result (search/block-search (state/get-current-repo) input {:enable-snippet? false
+                                                                             :built-in? false
+                                                                             :page-only? true
+                                                                             :library-page-search? true})]
+           (set-result! result))))
+     [(hooks/use-debounced-value input 200)])
+    (components-select/select
+     {:items items
+      :extract-fn :label
+      :extract-chosen-fn :value
+      :selected-choices selected-choices
+      :on-chosen (fn [chosen selected?]
+                   (if selected?
+                     (do
+                       (editor-handler/move-blocks! [{:db/id chosen}] library-page false)
+                       (set-selected-choices! (conj selected-choices chosen)))
+                     (do
+                       (db/transact! (state/get-current-repo)
+                                     [[:db/retract chosen :block/parent]]
+                                     {:outliner-op :save-block})
+                       (set-selected-choices! (disj selected-choices chosen)))))
+      :multiple-choices? true
+      :input-default-placeholder "Add pages"
+      :show-new-when-not-exact-match? false
+      :on-input set-input!
+      :input-opts {:class "!p-1 !text-sm"}})))
+
+(rum/defc add-pages
+  [library-page]
+  [:div.ls-add-pages.px-1
+   (shui/button
+    {:variant :secondary
+     :size :sm
+     :class "text-muted-foreground hover:text-foreground"
+     :on-click (fn [e]
+                 (shui/popup-show!
+                  (.-target e)
+                  (fn []
+                    [:div {:style {:min-height 120}}
+                     (select-pages library-page)])
+                  {:align :start}))}
+    (ui/icon "plus" {:size 16})
+    "Add pages to Library")])

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

@@ -8,6 +8,7 @@
             [frontend.components.db-based.page :as db-page]
             [frontend.components.editor :as editor]
             [frontend.components.file-based.hierarchy :as hierarchy]
+            [frontend.components.library :as library]
             [frontend.components.objects :as objects]
             [frontend.components.plugins :as plugins]
             [frontend.components.property.config :as property-config]
@@ -630,6 +631,9 @@
                                         :preview? preview?})))
                (lsp-pagebar-slot)])
 
+            (when (and db-based? (ldb/library? page))
+              (library/add-pages page))
+
             (when (and db-based? sidebar? (ldb/page? page))
               [:div.-mb-8
                (sidebar-page-properties config page)])

+ 7 - 0
src/main/frontend/handler/editor.cljs

@@ -842,6 +842,13 @@
                    (delete-block-aux! block)
                    (when edit-block-f (edit-block-f))))))))))))
 
+(defn move-blocks!
+  [blocks target sibling?]
+  (when (seq blocks)
+    (ui-outliner-tx/transact!
+     {:outliner-op :move-blocks}
+     (outliner-op/move-blocks! blocks target sibling?))))
+
 (defn delete-block!
   [repo]
   (delete-block-inner! repo (get-state)))

+ 24 - 21
src/main/frontend/worker/search.cljs

@@ -273,7 +273,7 @@ DROP TRIGGER IF EXISTS blocks_au;
    * :limit - Number of result to limit search results. Defaults to 100
    * :dev? - Allow all nodes to be seen for development. Defaults to false
    * :built-in?  - Whether to return public built-in nodes for db graphs. Defaults to false"
-  [repo conn search-db q {:keys [limit page enable-snippet? built-in? dev? page-only?]
+  [repo conn search-db q {:keys [limit page enable-snippet? built-in? dev? page-only? library-page-search?]
                           :as option
                           :or {enable-snippet? true}}]
   (when-not (string/blank? q)
@@ -308,26 +308,29 @@ DROP TRIGGER IF EXISTS blocks_au;
                               (let [{:keys [id page title snippet]} result
                                     block-id (uuid id)]
                                 (when-let [block (d/entity @conn [:block/uuid block-id])]
-                                  (when (if dev?
-                                          true
-                                          (if built-in?
-                                            (or (not (ldb/built-in? block))
-                                                (not (ldb/private-built-in-page? block))
-                                                (ldb/class? block))
-                                            (or (not (ldb/built-in? block))
-                                                (ldb/class? block))))
-                                    {:db/id (:db/id block)
-                                     :block/uuid block-id
-                                     :block/title (if (ldb/page? block)
-                                                    (ldb/get-title-with-parents block)
-                                                    (or snippet title))
-                                     :block/page (if (common-util/uuid-string? page)
-                                                   (uuid page)
-                                                   nil)
-                                     :block/tags (seq (map :db/id (:block/tags block)))
-                                     :page? (ldb/page? block)
-                                     :alias (some-> (first (:block/_alias block))
-                                                    (select-keys [:block/uuid :block/title]))}))))))
+                                  (when-not (and library-page-search?
+                                                 (or (:block/parent block)
+                                                     (not (ldb/internal-page? block)))) ; remove pages that already have parents
+                                    (when (if dev?
+                                            true
+                                            (if built-in?
+                                              (or (not (ldb/built-in? block))
+                                                  (not (ldb/private-built-in-page? block))
+                                                  (ldb/class? block))
+                                              (or (not (ldb/built-in? block))
+                                                  (ldb/class? block))))
+                                      {:db/id (:db/id block)
+                                       :block/uuid block-id
+                                       :block/title (if (ldb/page? block)
+                                                      (ldb/get-title-with-parents block)
+                                                      (or snippet title))
+                                       :block/page (if (common-util/uuid-string? page)
+                                                     (uuid page)
+                                                     nil)
+                                       :block/tags (seq (map :db/id (:block/tags block)))
+                                       :page? (ldb/page? block)
+                                       :alias (some-> (first (:block/_alias block))
+                                                      (select-keys [:block/uuid :block/title]))})))))))
           page-or-object-result (filter (fn [b] (or (:page? b) (:block/tags result))) result)]
       (->>
        (concat page-or-object-result