Browse Source

Merge branch 'feat/db' into perf/lazy-load-data

Tienson Qin 1 year ago
parent
commit
62b90b7ae7

+ 16 - 0
deps/db/src/logseq/db/frontend/content.cljs

@@ -56,3 +56,19 @@
     content
     tags)
    (string/trim)))
+
+(defn replace-tags-with-page-refs
+  "Replace tags in content with page-ref ids"
+  [content tags]
+  (reduce
+   (fn [content tag]
+     (string/replace content
+                     (str "#" (:block/original-name tag))
+                     (str page-ref/left-brackets
+                                ;; TODO: Use uuid when it becomes available
+                                ;; page-ref-special-chars
+                                ;; (:block/uuid tag)
+                          (:block/original-name tag)
+                          page-ref/right-brackets)))
+   content
+   tags))

+ 4 - 0
deps/db/src/logseq/db/frontend/property.cljs

@@ -24,6 +24,10 @@
           :schema {:type :page
                    :cardinality :many
                    :classes #{:logseq.class}}}
+   :pagetags {:original-name "pageTags"
+              :visible true
+              :schema {:type :page
+                       :cardinality :many}}
    :background-color {:schema {:type :default :hide? true}
                       :visible true}
    :background-image {:schema {:type :default :hide? true}

+ 58 - 25
deps/graph-parser/src/logseq/graph_parser.cljs

@@ -135,23 +135,60 @@ Options available:
                 (assoc :block/created-at updated-at))]
     block))
 
-(defn- update-block-with-invalid-tags
-  [block]
+(defn- update-page-tags
+  [block tag-classes names-uuids page-tags-uuid]
+  (if (seq (:block/tags block))
+    (let [page-tags (->> (:block/tags block)
+                         (remove #(contains? tag-classes (:block/name %)))
+                         (map #(or (get names-uuids (:block/name %))
+                                   (throw (ex-info (str "No uuid found for tag " (pr-str (:block/name %)))
+                                                   {:tag %}))))
+                         set)]
+      (cond-> block
+        true
+        (update :block/tags
+                (fn [tags]
+                  (keep #(when (contains? tag-classes (:block/name %))
+                           (-> %
+                               add-missing-timestamps
+                               ;; don't use build-new-class b/c of timestamps
+                               (merge {:block/journal? false
+                                       :block/format :markdown
+                                       :block/type "class"
+                                       :block/uuid (d/squuid)})))
+                        tags)))
+        (seq page-tags)
+        (assoc :block/properties {page-tags-uuid page-tags})))
+    block))
+
+(defn- update-block-tags
+  [block tag-classes]
   (if (seq (:block/tags block))
-    (update block :block/tags
+    (-> block
+        (update :block/content
+                db-content/content-without-tags
+                (->> (:block/tags block)
+                     (filter #(tag-classes (:block/name %)))
+                     (map :block/original-name)))
+        (update :block/content
+                db-content/replace-tags-with-page-refs
+                (remove #(tag-classes (:block/name %))
+                        (:block/tags block)))
+        (update :block/tags
             (fn [tags]
-              (mapv #(-> %
-                         add-missing-timestamps
-                         ;; don't use build-new-class b/c of timestamps
-                         (merge {:block/journal? false
-                                 :block/format :markdown
-                                 :block/type "class"
-                                 :block/uuid (d/squuid)}))
-                    tags)))
+              (keep #(when (contains? tag-classes (:block/name %))
+                       (-> %
+                           add-missing-timestamps
+                           ;; don't use build-new-class b/c of timestamps
+                           (merge {:block/journal? false
+                                   :block/format :markdown
+                                   :block/type "class"
+                                   :block/uuid (d/squuid)})))
+                    tags))))
     block))
 
 (defn- update-imported-block
-  [conn block]
+  [conn block tag-classes]
   (prn ::block block)
   (let [remove-keys (fn [m pred] (into {} (remove (comp pred key) m)))]
     (-> block
@@ -180,14 +217,7 @@ Options available:
                                                new-key
                                                k)))
                               (remove-keys keyword?)))))))
-        update-block-with-invalid-tags
-        ((fn [block']
-           (if (seq (:block/tags block'))
-             (update block :block/content
-                     db-content/content-without-tags
-                     (map :block/original-name (:block/tags block')))
-             block)))
-
+        (update-block-tags tag-classes)
         ((fn [block']
            (if (seq (:block/refs block'))
              (update block' :block/refs
@@ -209,9 +239,10 @@ Options available:
 
 (defn import-file-to-db-graph
   "Parse file and save parsed data to the given db graph."
-  [conn file content {:keys [extract-options]
+  [conn file content {:keys [extract-options user-options page-tags-uuid]
                       :as options}]
   (let [format (common-util/get-format file)
+        tag-classes (set (map string/lower-case (:tag-classes user-options)))
         {:keys [tx ast]}
         (let [extract-options' (merge {:block-pattern (common-config/get-block-pattern format)
                                        :date-formatter "MMM do, yyyy"
@@ -242,6 +273,8 @@ Options available:
                                   (seq))
                  ;; To prevent "unique constraint" on datascript
               block-ids (set/union (set block-ids) (set block-refs-ids))
+              pages* (extract/with-ref-pages pages blocks)
+              names-uuids (into {} (map (juxt :block/name :block/uuid) pages*))
               pages (map #(-> (merge {:block/journal? false} %)
                               ;; Fix pages missing :block/original-name. Shouldn't happen
                               ((fn [m]
@@ -253,10 +286,10 @@ Options available:
                               (assoc :block/format :markdown)
                               (dissoc :block/properties-text-values :block/properties-order :block/invalid-properties
                                       :block/whiteboard?)
-                              update-block-with-invalid-tags
                               ;; FIXME: Remove when properties are supported
-                              (assoc :block/properties {}))
-                         (extract/with-ref-pages pages blocks))
+                              (assoc :block/properties {})
+                              (update-page-tags tag-classes names-uuids page-tags-uuid))
+                         pages*)
 
               ;; post-handling
               whiteboard-pages (->> pages
@@ -267,7 +300,7 @@ Options available:
                                                       :block/format :markdown
                                                       ;; fixme: missing properties
                                                       :block/properties {(get-pid @conn :ls-type) :whiteboard-page})))))
-              blocks (map #(update-imported-block conn %) blocks)
+              blocks (map #(update-imported-block conn % tag-classes) blocks)
               pages-index (map #(select-keys % [:block/name]) pages)]
 
           {:tx (concat refs whiteboard-pages pages-index pages block-ids blocks)

+ 198 - 0
deps/shui/src/logseq/shui/demo2.cljs

@@ -0,0 +1,198 @@
+(ns logseq.shui.demo2
+  (:require [rum.core :as rum]
+            [logseq.shui.ui :as ui]
+            [medley.core :as medley]
+            [logseq.shui.util :refer [use-atom]]
+            [frontend.components.icon :refer [emojis-cp emojis]]))
+
+;; {:id "" :open? false :content nil :position [0 0] :root-props nil :content-props nil}
+(defonce ^:private *popups (atom []))
+(defonce ^:private *id (atom 0))
+(defonce ^:private gen-id #(reset! *id (inc @*id)))
+
+(defn get-popup
+  [id]
+  (when id
+    (some->> (medley/indexed @*popups)
+      (filter #(= id (:id (second %)))) (first))))
+
+(defn upsert-popup!
+  [config]
+  (when-let [id (:id config)]
+    (if-let [[index config'] (get-popup id)]
+      (swap! *popups assoc index (merge config' config))
+      (swap! *popups conj config))))
+
+(defn update-popup!
+  [id ks val]
+  (when-let [[index config] (get-popup id)]
+    (let [ks (if (coll? ks) ks [ks])
+          config (if (nil? val)
+                   (medley/dissoc-in config ks)
+                   (assoc-in config ks val))]
+      (swap! *popups assoc index config))))
+
+(defn detach-popup!
+  [id]
+  (when-let [[index] (get-popup id)]
+    (swap! *popups #(->> % (medley/remove-nth index) (vec)))))
+
+(defn show-x-popup!
+  [^js event content & {:keys [id as-menu? root-props content-props] :as opts}]
+  (let [position (cond
+                   (vector? event) event
+
+                   (instance? js/MouseEvent (or (.-nativeEvent event) event))
+                   [(.-clientX event) (.-clientY event)]
+
+                   (instance? js/Element event)
+                   (let [^js rect (.getBoundingClientRect event)
+                         left (.-left rect)
+                         width (.-width rect)
+                         bottom (.-bottom rect)]
+                     [(+ left (/ width 2)) bottom])
+                   :else [0 0])]
+    (upsert-popup!
+      (merge opts
+        {:id       (or id (gen-id))
+         :open?    true :content content :position position
+         :as-menu? as-menu? :root-props root-props :content-props content-props}))))
+
+(defn hide-x-popup!
+  [id]
+  (update-popup! id :open? false))
+
+(defn hide-x-popup-all!
+  []
+  (doseq [{:keys [id]} @*popups]
+    (hide-x-popup! id)))
+
+(rum/defc x-popup [{:keys [id open? content position as-menu? root-props content-props] :as _props}]
+  (rum/use-effect!
+    (fn []
+      (when (false? open?)
+        (js/setTimeout #(detach-popup! id) 128)))
+    [open?])
+
+  (when-let [[x y] position]
+    (let [popup-root (if as-menu? ui/dropdown-menu ui/popover)
+          popup-trigger (if as-menu? ui/dropdown-menu-trigger ui/popover-trigger)
+          popup-content (if as-menu? ui/dropdown-menu-content ui/popover-content)]
+      (popup-root
+        (merge root-props {:open open?})
+        (popup-trigger
+          {:as-child true}
+          (ui/button {:class "w-1 h-1 overflow-hidden fixed p-0 opacity-0"
+                      :style {:top y :left x}} ""))
+        (popup-content
+          (merge {:onEscapeKeyDown      #(hide-x-popup! id)
+                  :onPointerDownOutside #(hide-x-popup! id)} content-props)
+          (if (fn? content) (content {:id id}) content))))))
+
+(rum/defc install-popups
+  < rum/static
+  []
+  (let [[popups _set-popups!] (use-atom *popups)]
+    [:<>
+     (for [config popups
+           :when (and (map? config) (:id config))]
+       (x-popup config))]))
+
+(rum/defc page []
+  [:div.sm:p-10
+   [:h1.text-3xl.font-bold.border-b.pb-4 "UI X Popup"]
+
+   (rum/portal
+     (install-popups)
+     js/document.body)
+
+   (let [[emoji set-emoji!] (rum/use-state nil)
+         [q set-q!] (rum/use-state "")
+         *q-ref (rum/use-ref nil)
+         emoji-picker (fn [_nested?]
+                        [:p.py-4
+                         "Choose a inline "
+                         [:a.underline
+                          {:on-click #(show-x-popup! %
+                                        [:div.max-h-72.overflow-auto.p-1
+                                         (emojis-cp (take 80 emojis)
+                                           {:on-chosen
+                                            (fn [_ t]
+                                              (set-emoji! t)
+                                              (hide-x-popup-all!))})]
+                                        {:content-props {:class "w-72 p-0"}
+                                         :as-menu?      true})}
+                          (if emoji [:strong.px-1.text-6xl [:em-emoji emoji]] "emoji :O")] "."])]
+     [:<>
+      (emoji-picker nil)
+
+      [:p.py-4
+       (ui/button
+         {:variant  :secondary
+          :on-click #(show-x-popup! %
+                       (fn []
+                         [:p.p-4
+                          (emoji-picker true)]))}
+         "Play a nested x popup.")]
+
+      [:p.py-4
+       (let [gen-content
+             (fn [q]
+               [:p.x-input-popup-content.bg-green-rx-06
+                (ui/button {:on-click #(ui/toast! "Just a joke :)")} "play a magic")
+                (emoji-picker true)
+                [:strong.px-1.text-6xl q]])]
+         (ui/input
+           {:placeholder "Select a fruit."
+            :ref         *q-ref
+            :value       q
+            :on-change   (fn [^js e]
+                           (let [val (.-value (.-target e))]
+                             (set-q! val)
+                             (update-popup! :select-a-fruit-input [:content] (gen-content val))))
+            :class       "w-1/5"
+            :on-focus    (fn [^js e]
+                           (let [id :select-a-fruit-input
+                                 [_ popup] (get-popup id)]
+                             (if (not popup)
+                               (show-x-popup! (.-target e)
+                                 (gen-content q)
+                                 {:id id
+                                  :content-props
+                                  {:class "x-input-popup-content"
+                                   :onPointerDownOutside
+                                   (fn [^js e]
+                                     (js/console.log "===>> onPointerDownOutside:" e (rum/deref *q-ref))
+                                     (when-let [q-ref (rum/deref *q-ref)]
+                                       (let [^js target (or (.-relatedTarget e)
+                                                          (.-target e))]
+                                         (js/console.log "t:" target)
+                                         (when (and
+                                                 (not (.contains q-ref target))
+                                                 (not (.closest target ".x-input-popup-content")))
+                                           (hide-x-popup! id)))))
+                                   :onOpenAutoFocus #(.preventDefault %)}})
+
+                               ;; update content
+                               (update-popup! id [:content]
+                                 (gen-content q)))))
+            ;:on-blur     (fn [^js e]
+            ;               (let [^js target (.-relatedTarget e)]
+            ;                 (js/console.log "==>>>" target)
+            ;                 (when-not (.closest target ".x-input-popup-content")
+            ;                   (hide-x-popup! :select-a-fruit-input))))
+            }))]
+
+      [:div.w-full.p-4.border.rounded.dotted.h-48.mt-8.bg-gray-02
+       {:on-click        #(show-x-popup! %
+                            (->> (range 8)
+                              (map (fn [it]
+                                     (ui/dropdown-menu-item
+                                       {:on-select (fn []
+                                                     (ui/toast! it)
+                                                     (hide-x-popup-all!))}
+                                       [:strong it]))))
+                            {:as-menu?      true
+                             :content-props {:class "w-48"}})
+        :on-context-menu #(show-x-popup! %
+                            [:h1.text-3xl.font-bold "hi x popup for custom context menu!"])}]])])

+ 3 - 0
packages/ui/src/vars-classic.css

@@ -23,6 +23,9 @@
   --ls-highlight-color-blue: var(--rx-blue-05);
   --ls-highlight-color-purple: var(--rx-purple-05);
   --ls-highlight-color-pink: var(--rx-pink-05);
+
+  /* NOTE: For compatible. Will be deprecated*/
+  --ls-block-bullet-color: var(--lx-gray-08, var(--rx-gray-08));
 }
 
 .white-theme,

+ 4 - 0
resources/css/shui.css

@@ -204,6 +204,10 @@ html[data-theme=dark] {
         @apply opacity-60 hover:opacity-90;
       }
     }
+
+    .form-input {
+      @apply border-accent-01;
+    }
   }
 }
 

+ 6 - 0
src/main/frontend/components/cmdk.css

@@ -0,0 +1,6 @@
+.cp__cmdk {
+  > .hints {
+    @apply flex w-full px-3 py-2 gap-2 justify-between
+    bg-gray-03 border-t border-gray-05;
+  }
+}

+ 52 - 30
src/main/frontend/components/container.cljs

@@ -84,11 +84,45 @@
                            (state/sidebar-add-block!
                              (state/get-current-repo)
                              (:db/id page-entity)
-                             :page))]
+                             :page))
+        x-menu-content (fn [type opts]
+                         (let [dropdown? (= type :dropdown)
+                               x-menu-content (if dropdown? shui/dropdown-menu-content shui/context-menu-content)
+                               x-menu-item (if dropdown? shui/dropdown-menu-item shui/context-menu-item)
+                               x-menu-shortcut (if dropdown? shui/dropdown-menu-shortcut shui/context-menu-shortcut)]
+                           (x-menu-content
+                             (merge {:class "w-60"} opts)
+                             (when-not recent?
+                               (x-menu-item
+                                 {:on-click #(page-handler/<unfavorite-page! original-name)}
+                                 (ctx-icon "star-off")
+                                 (t :page/unfavorite)
+                                 (x-menu-shortcut (some-> (shortcut-dh/shortcut-binding :command/toggle-favorite) (first)
+                                                               (shortcut-utils/decorate-binding)))))
+
+                             (when-let [page-fpath (and (util/electron?) file-rpath
+                                                     (config/get-repo-fpath (state/get-current-repo) file-rpath))]
+                               [:<>
+                                (x-menu-item
+                                  {:on-click #(ipc/ipc :openFileInFolder page-fpath)}
+                                  (ctx-icon "folder")
+                                  (t :page/open-in-finder))
+
+                                (x-menu-item
+                                  {:on-click #(js/window.apis.openPath page-fpath)}
+                                  (ctx-icon "file")
+                                  (t :page/open-with-default-app))])
+
+                             (x-menu-item
+                               {:on-click open-in-sidebar}
+                               (ctx-icon "layout-sidebar-right")
+                               (t :content/open-in-sidebar)
+                               (x-menu-shortcut (shortcut-utils/decorate-binding "shift+click"))))))]
+
     ;; TODO: move to standalone component
     (shui/context-menu
       (shui/context-menu-trigger
-        [:a.flex.items-center
+        [:a.flex.items-center.justify-between.relative.group
          {:on-click
           (fn [e]
             (let [name (if (empty? source-page) name (:block/name source-page))]
@@ -100,34 +134,22 @@
          [:span.page-icon.ml-3.justify-center (if whiteboard-page? (ui/icon "whiteboard" {:extension? true}) icon)]
          [:span.page-title {:class (when untitled? "opacity-50")}
           (if untitled? (t :untitled)
-                        (pdf-utils/fix-local-asset-pagename original-name))]]
-        (shui/context-menu-content
-          {:class "w-60"}
-          (when-not recent?
-            (shui/context-menu-item
-              {:on-click #(page-handler/<unfavorite-page! original-name)}
-              (ctx-icon "star-off")
-              (t :page/unfavorite)
-              (shui/context-menu-shortcut (some-> (shortcut-dh/shortcut-binding :command/toggle-favorite) (first)
-                                            (shortcut-utils/decorate-binding)))))
-          (when-let [page-fpath (and (util/electron?) file-rpath
-                                  (config/get-repo-fpath (state/get-current-repo) file-rpath))]
-            [:<>
-             (shui/context-menu-item
-               {:on-click #(ipc/ipc :openFileInFolder page-fpath)}
-               (ctx-icon "folder")
-               (t :page/open-in-finder))
-
-             (shui/context-menu-item
-               {:on-click #(js/window.apis.openPath page-fpath)}
-               (ctx-icon "file")
-               (t :page/open-with-default-app))])
-
-          (shui/context-menu-item
-            {:on-click open-in-sidebar}
-            (ctx-icon "layout-sidebar-right")
-            (t :content/open-in-sidebar)
-            (shui/context-menu-shortcut (shortcut-utils/decorate-binding "shift+click"))))))))
+                        (pdf-utils/fix-local-asset-pagename original-name))]
+
+         ;; dots trigger
+         (shui/dropdown-menu
+           (shui/dropdown-menu-trigger
+             (shui/button
+               {:size     :sm
+                :variant  :ghost
+                :class    "absolute right-2 top-0 px-1.5 scale-75 opacity-30 hidden group-hover:block hover:opacity-80 active:opacity-100"
+                :on-click #(util/stop %)}
+               [:i.relative {:style {:top "1px"}} (shui/tabler-icon "dots")]))
+           ;; menu content
+           (x-menu-content :dropdown {:align "start"}))]
+
+        ;; menu content
+        (x-menu-content :context nil)))))
 
  ;; Fall back to default if icon is undefined or empty
 

+ 10 - 8
src/main/frontend/components/icon.cljs

@@ -69,14 +69,16 @@
 (rum/defc emoji-cp < rum/static
   [{:keys [id name] :as emoji} {:keys [on-chosen hover]}]
   [:button.text-2xl.w-9.h-9.transition-opacity
-   {:tabIndex "0"
-    :title name
-    :on-click (fn [e]
-                (on-chosen e {:type :emoji
-                              :id id
-                              :name name}))
-    :on-mouse-over #(reset! hover emoji)
-    :on-mouse-out #(reset! hover nil)}
+   (cond->
+     {:tabIndex "0"
+      :title name
+      :on-click (fn [e]
+                  (on-chosen e {:type :emoji
+                                :id id
+                                :name name}))}
+     (not (nil? hover))
+     (assoc :on-mouse-over #(reset! hover emoji)
+            :on-mouse-out #(reset! hover nil)))
    [:em-emoji {:id id}]])
 
 (rum/defc emojis-cp < rum/static

+ 51 - 30
src/main/frontend/components/imports.cljs

@@ -35,7 +35,8 @@
             [promesa.core :as p]
             [rum.core :as rum]
             [logseq.common.config :as common-config]
-            [lambdaisland.glogi :as log]))
+            [lambdaisland.glogi :as log]
+            [frontend.handler.db-based.property.util :as db-pu]))
 
 ;; Can't name this component as `frontend.components.import` since shadow-cljs
 ;; will complain about it.
@@ -165,10 +166,10 @@
       (ui/button "Submit"
                  {:on-click on-submit})]]))
 
-
 (defn- import-from-doc-files!
-  [db-conn repo config doc-files]
-  (let [imported-chan (async/promise-chan)]
+  [db-conn repo config doc-files user-options]
+  (let [imported-chan (async/promise-chan)
+        page-tags-uuid (db-pu/get-built-in-property-uuid repo :pagetags)]
     (try
       (let [docs-chan (async/to-chan! (medley/indexed doc-files))]
         (state/set-state! [:graph/importing-state :total] (count doc-files))
@@ -189,7 +190,13 @@
                                   (p/then (fn [m]
                                             ;; Write to frontend first as writing to worker first is poor ux with slow streaming changes
                                             (let [{:keys [tx-report]}
-                                                  (graph-parser/import-file-to-db-graph db-conn (:file/path m) (:file/content m) {:extract-options extract-options})]
+                                                  (graph-parser/import-file-to-db-graph
+                                                   db-conn
+                                                   (:file/path m)
+                                                   (:file/content m)
+                                                   {:extract-options extract-options
+                                                    :user-options user-options
+                                                    :page-tags-uuid page-tags-uuid})]
                                               (db-browser/transact! @db-browser/*worker repo (:tx-data tx-report) (:tx-meta tx-report)))
                                             m)))))
               (recur))
@@ -286,11 +293,11 @@
                 (outliner-core/insert-blocks! repo db-conn (build-hidden-favorites-page-blocks page-block-uuid-coll)
                                               page-entity {}))))))))))
 
-
-(rum/defc confirm-graph-name-dialog
+(rum/defc import-file-graph-dialog
   [initial-name on-graph-name-confirmed]
-  (let [[input set-input!] (rum/use-state initial-name)
-        on-submit #(do (on-graph-name-confirmed input)
+  (let [[graph-input set-graph-input!] (rum/use-state initial-name)
+        [tags-input set-tags-input!] (rum/use-state "")
+        on-submit #(do (on-graph-name-confirmed {:graph-name graph-input :tags tags-input})
                        (state/close-modal!))]
     [:div.container
      [:div.sm:flex.sm:items-start
@@ -300,19 +307,32 @@
 
      [:input.form-input.block.w-full.sm:text-sm.sm:leading-5.my-2.mb-4
       {:auto-focus true
-       :default-value input
+       :default-value graph-input
        :on-change (fn [e]
-                    (set-input! (util/evalue e)))
+                    (set-graph-input! (util/evalue e)))
+       :on-key-down (fn [e]
+                      (when (= "Enter" (util/ekey e))
+                        (on-submit)))}]
+     [:div.sm:flex.sm:items-start
+      [:div.mt-3.text-center.sm:mt-0.sm:text-left
+       [:h3#modal-headline.leading-6.font-medium
+        "(Optional) Tags to import as tag classes:"]
+       [:span.text-xs
+        "Tags are case insensitive and separated by commas"]]]
+     [:input.form-input.block.w-full.sm:text-sm.sm:leading-5.my-2.mb-4
+      {:default-value tags-input
+       :on-change (fn [e]
+                    (set-tags-input! (util/evalue e)))
        :on-key-down (fn [e]
                       (when (= "Enter" (util/ekey e))
                         (on-submit)))}]
 
      [:div.mt-5.sm:mt-4.flex
-      (ui/button "Confirm"
+      (ui/button "Submit"
                  {:on-click on-submit})]]))
 
 (defn- import-file-graph
-  [*files graph-name config-file]
+  [*files {:keys [graph-name tags]} config-file]
   (state/set-state! :graph/importing :folder)
   (state/set-state! [:graph/importing-state :current-page] (str graph-name " Assets"))
   (async/go
@@ -325,7 +345,8 @@
           asset-files (filter #(string/starts-with? (:rpath %) "assets/") files)]
       (async/<! (p->c (import-logseq-files (filter #(string/starts-with? (:rpath %) "logseq/") files))))
       (async/<! (import-from-asset-files! asset-files))
-      (async/<! (import-from-doc-files! db-conn repo config doc-files))
+      (async/<! (import-from-doc-files! db-conn repo config doc-files
+                                        {:tag-classes (set (string/split tags #",\s*"))}))
       (async/<! (p->c (import-favorites-from-config-edn! db-conn repo config-file)))
       (state/set-state! :graph/importing nil)
       (state/set-state! :graph/importing-state nil)
@@ -335,14 +356,14 @@
                             :info false))
       (finished-cb))))
 
-(defn graph-folder-to-db-import-handler
+(defn import-file-to-db-handler
   "Import from a graph folder as a DB-based graph.
 
 - Page name, journal name creation"
   [ev _opts]
   (let [^js file-objs (array-seq (.-files (.-target ev)))
         original-graph-name (string/replace (.-webkitRelativePath (first file-objs)) #"/.*" "")
-        import-graph-fn (fn [graph-name]
+        import-graph-fn (fn [user-inputs]
                           (let [files (->> file-objs
                                            (map #(hash-map :file-object %
                                                            :rpath (path/trim-dir-prefix original-graph-name (.-webkitRelativePath %))))
@@ -350,24 +371,24 @@
                                                          ;; TODO: Update this when supporting more formats as this aggressively excludes most formats
                                                          (fs-util/ignored-path? original-graph-name (.-webkitRelativePath (:file-object %))))))]
                             (if-let [config-file (first (filter #(= (:rpath %) "logseq/config.edn") files))]
-                              (import-file-graph files graph-name config-file)
+                              (import-file-graph files user-inputs config-file)
                               (notification/show! "Import failed as the file 'logseq/config.edn' was not found for a Logseq graph."
                                                   :error))))]
     (state/set-modal!
-     #(confirm-graph-name-dialog original-graph-name
-                                 (fn [graph-name]
-                                   (cond
-                                     (repo/invalid-graph-name? graph-name)
-                                     (repo/invalid-graph-name-warning)
+     #(import-file-graph-dialog original-graph-name
+                                (fn [{:keys [graph-name] :as user-inputs}]
+                                  (cond
+                                    (repo/invalid-graph-name? graph-name)
+                                    (repo/invalid-graph-name-warning)
 
-                                     (string/blank? graph-name)
-                                     (notification/show! "Empty graph name." :error)
+                                    (string/blank? graph-name)
+                                    (notification/show! "Empty graph name." :error)
 
-                                     (repo-handler/graph-already-exists? graph-name)
-                                     (notification/show! "Please specify another name as another graph with this name already exists!" :error)
+                                    (repo-handler/graph-already-exists? graph-name)
+                                    (notification/show! "Please specify another name as another graph with this name already exists!" :error)
 
-                                     :else
-                                     (import-graph-fn graph-name)))))))
+                                    :else
+                                    (import-graph-fn user-inputs)))))))
 
 
   (rum/defc importer < rum/reactive
@@ -410,11 +431,11 @@
             [[:strong "File to DB graph"]
              [:small  "Import a file-based Logseq graph folder into a new DB graph"]]]
            [:input.absolute.hidden
-            {:id        "import-graph-folder"
+            {:id        "import-file-graph"
              :type      "file"
              :webkitdirectory "true"
              :on-change (debounce (fn [e]
-                                    (graph-folder-to-db-import-handler e {}))
+                                    (import-file-to-db-handler e {}))
                                   1000)}]])
 
          [:label.action-input.flex.items-center.mx-2.my-2

+ 1 - 3
src/main/frontend/components/page.css

@@ -175,9 +175,7 @@
       }
 
       .form-input {
-        padding: 3px;
-        padding-left: 30px;
-        padding-right: 8px;
+        padding: 3px 8px 3px 30px;
       }
 
       .cancel {

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

@@ -12,7 +12,7 @@
             [frontend.extensions.zotero :as zotero]
             [frontend.components.bug-report :as bug-report]
             [frontend.components.user.login :as login]
-            [logseq.shui.demo :as shui]
+            [logseq.shui.demo2 :as shui]
             [frontend.components.imports :as imports]))
 
 ;; http://localhost:3000/#?anchor=fn.1