|
|
@@ -24,28 +24,29 @@
|
|
|
title (:title data)
|
|
|
type (:item-type data)
|
|
|
abstract (str (subs (:abstract-note data) 0 200) "...")]
|
|
|
- [:div.zotero-search-item.px-2.py-4.border-b.cursor-pointer.border-solid.last:border-none.relative
|
|
|
+ [:div.zotero-search-item.px-2.py-2.border-b.cursor-pointer.border-solid.last:border-none.relative
|
|
|
{:on-click (fn [] (go
|
|
|
- (set-is-creating-page! true)
|
|
|
- (<!
|
|
|
- (zotero-handler/create-zotero-page item {:block-dom-id id}))
|
|
|
- (set-is-creating-page! false)))}
|
|
|
- [[:div [[:span.font-bold.mb-1.mr-1 title]
|
|
|
+ (set-is-creating-page! true)
|
|
|
+ (<!
|
|
|
+ (zotero-handler/create-zotero-page item {:block-dom-id id}))
|
|
|
+ (set-is-creating-page! false)))}
|
|
|
+ [[:div [[:span.font-medium.mb-1.mr-1.text-sm title]
|
|
|
[:span.zotero-search-item-type.text-xs.p-1.rounded type]]]
|
|
|
- [:div.text-sm abstract]]
|
|
|
+ [:div.text-sm.opacity-60 abstract]]
|
|
|
|
|
|
- (when is-creating-page [:div.zotero-search-item-loading-indicator [:span.animate-spin-reverse svg/refresh]])]))
|
|
|
+ (when is-creating-page
|
|
|
+ [:div.zotero-search-item-loading-indicator [:span.animate-spin-reverse (svg/refresh)]])]))
|
|
|
|
|
|
(rum/defc zotero-search
|
|
|
[id]
|
|
|
|
|
|
- (let [[term set-term!] (rum/use-state "")
|
|
|
- [search-result set-search-result!] (rum/use-state [])
|
|
|
- [prev-page set-prev-page!] (rum/use-state "")
|
|
|
- [next-page set-next-page!] (rum/use-state "")
|
|
|
+ (let [[term set-term!] (rum/use-state "")
|
|
|
+ [search-result set-search-result!] (rum/use-state [])
|
|
|
+ [prev-page set-prev-page!] (rum/use-state "")
|
|
|
+ [next-page set-next-page!] (rum/use-state "")
|
|
|
[prev-search-term set-prev-search-term!] (rum/use-state "")
|
|
|
- [search-error set-search-error!] (rum/use-state nil)
|
|
|
- [is-searching set-is-searching!] (rum/use-state false)
|
|
|
+ [search-error set-search-error!] (rum/use-state nil)
|
|
|
+ [is-searching set-is-searching!] (rum/use-state false)
|
|
|
|
|
|
search-fn (fn [s-term start]
|
|
|
(go
|
|
|
@@ -66,55 +67,59 @@
|
|
|
(set-is-searching! false))))]
|
|
|
|
|
|
(rum/use-effect!
|
|
|
- (fn []
|
|
|
- (let [d-chan (chan)]
|
|
|
- (a/tap debounce-chan-mult d-chan)
|
|
|
- (go-loop []
|
|
|
- (let [d-term (<! d-chan)]
|
|
|
- (<! (search-fn d-term "0")))
|
|
|
- (recur))
|
|
|
+ (fn []
|
|
|
+ (let [d-chan (chan)]
|
|
|
+ (a/tap debounce-chan-mult d-chan)
|
|
|
+ (go-loop []
|
|
|
+ (let [d-term (<! d-chan)]
|
|
|
+ (<! (search-fn d-term "0")))
|
|
|
+ (recur))
|
|
|
|
|
|
- (fn [] (a/untap debounce-chan-mult d-chan))))
|
|
|
- [])
|
|
|
+ (fn [] (a/untap debounce-chan-mult d-chan))))
|
|
|
+ [])
|
|
|
|
|
|
(when-not (setting/valid?)
|
|
|
(route-handler/redirect! {:to :zotero-setting})
|
|
|
(notification/show! "Please setup Zotero API key and user/group id first!" :warn false))
|
|
|
|
|
|
- [:div#zotero-search.zotero-search.p-4
|
|
|
- {:style {:width 720}}
|
|
|
-
|
|
|
- [:div.flex.items-center.mb-2
|
|
|
- [[:input.p-2.border.mr-2.flex-1.focus:outline-none
|
|
|
- {:autoFocus true
|
|
|
- :placeholder "Search for your Zotero journal article (title, author, text, anything)"
|
|
|
- :value term :on-change (fn [e]
|
|
|
- (go
|
|
|
- (>! term-chan (util/evalue e)))
|
|
|
- (set-term! (util/evalue e)))}]
|
|
|
-
|
|
|
- [:span.animate-spin-reverse {:style {:visibility (if is-searching "visible" "hidden")}} svg/refresh]]]
|
|
|
-
|
|
|
- [:div.h-2.text-sm.text-error.mb-2 (if search-error (str "Search error: " search-error) "")]
|
|
|
-
|
|
|
- [:div
|
|
|
- (map
|
|
|
- (fn [item] (rum/with-key (zotero-search-item item id) (:key item)))
|
|
|
- search-result)
|
|
|
- (when-not (str/blank? prev-page)
|
|
|
- (ui/button
|
|
|
- "prev"
|
|
|
- :on-click
|
|
|
- (fn []
|
|
|
- (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
|
|
|
- (search-fn prev-search-term prev-page))))
|
|
|
- (when-not (str/blank? next-page)
|
|
|
- (ui/button
|
|
|
- "next"
|
|
|
- :on-click
|
|
|
- (fn []
|
|
|
- (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
|
|
|
- (search-fn prev-search-term next-page))))]]))
|
|
|
+ [:div#zotero-search.zotero-search
|
|
|
+ [:div.flex.items-center.input-wrap
|
|
|
+ [:input.flex-1.focus:outline-none
|
|
|
+ {:autoFocus true
|
|
|
+ :placeholder "Search for your Zotero articles (title, author, text, anything)"
|
|
|
+ :value term
|
|
|
+ :on-change (fn [e]
|
|
|
+ (go
|
|
|
+ (>! term-chan (util/evalue e)))
|
|
|
+ (set-term! (util/evalue e)))}]
|
|
|
+
|
|
|
+ (when is-searching (ui/loading ""))]
|
|
|
+
|
|
|
+ (when search-error
|
|
|
+ [:div.h-2.text-sm.text-error.mb-2
|
|
|
+ (str "Search error: " search-error "")])
|
|
|
+
|
|
|
+ (when (seq search-result)
|
|
|
+ [:div.p-2
|
|
|
+ (map
|
|
|
+ (fn [item] (rum/with-key (zotero-search-item item id) (:key item)))
|
|
|
+ search-result)
|
|
|
+
|
|
|
+ ;; pagination
|
|
|
+ (when-not (str/blank? prev-page)
|
|
|
+ (ui/button
|
|
|
+ "prev"
|
|
|
+ :on-click
|
|
|
+ (fn []
|
|
|
+ (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
|
|
|
+ (search-fn prev-search-term prev-page))))
|
|
|
+ (when-not (str/blank? next-page)
|
|
|
+ (ui/button
|
|
|
+ "next"
|
|
|
+ :on-click
|
|
|
+ (fn []
|
|
|
+ (set! (.-scrollTop (.-parentNode (gdom/getElement "zotero-search"))) 0)
|
|
|
+ (search-fn prev-search-term next-page))))])]))
|
|
|
|
|
|
(rum/defcs user-or-group-setting <
|
|
|
(rum/local (setting/setting :type-id) ::type-id)
|
|
|
@@ -150,15 +155,15 @@
|
|
|
:on-change (fn [e] (reset! (::type-id state) (util/evalue e)))}]]]]
|
|
|
|
|
|
(when
|
|
|
- (and (not (str/blank? (str @(::type-id state))))
|
|
|
- (not (re-matches #"^\d+$" (str @(::type-id state)))))
|
|
|
+ (and (not (str/blank? (str @(::type-id state))))
|
|
|
+ (not (re-matches #"^\d+$" (str @(::type-id state)))))
|
|
|
(ui/admonition
|
|
|
- :warning
|
|
|
- [:p.text-error
|
|
|
- "User ID is different from username and can be found on the "
|
|
|
- [:a {:href "https://www.zotero.org/settings/keys" :target "_blank"}
|
|
|
- "https://www.zotero.org/settings/keys"]
|
|
|
- " page, it's a number of digits"]))])
|
|
|
+ :warning
|
|
|
+ [:p.text-error
|
|
|
+ "User ID is different from username and can be found on the "
|
|
|
+ [:a {:href "https://www.zotero.org/settings/keys" :target "_blank"}
|
|
|
+ "https://www.zotero.org/settings/keys"]
|
|
|
+ " page, it's a number of digits"]))])
|
|
|
|
|
|
(rum/defc overwrite-mode-setting <
|
|
|
rum/reactive
|
|
|
@@ -175,9 +180,9 @@
|
|
|
true)]]]
|
|
|
(when (setting/setting :overwrite-mode?)
|
|
|
(ui/admonition
|
|
|
- :warning
|
|
|
- [:p.text-error
|
|
|
- "Dangerous! This will delete and recreate Zotero existing page! Make sure to backup your notes first in case something goes wrong. Make sure you don't put any personal item in previous Zotero page and it's OK to overwrite the page!"]))])
|
|
|
+ :warning
|
|
|
+ [:p.text-error
|
|
|
+ "Dangerous! This will delete and recreate Zotero existing page! Make sure to backup your notes first in case something goes wrong. Make sure you don't put any personal item in previous Zotero page and it's OK to overwrite the page!"]))])
|
|
|
|
|
|
(rum/defc attachment-setting <
|
|
|
rum/reactive
|
|
|
@@ -284,7 +289,7 @@
|
|
|
(rum/defc extra-tags-setting []
|
|
|
[:div.row
|
|
|
[:label.title
|
|
|
- {:for "zotero_extra_tags"
|
|
|
+ {:for "zotero_extra_tags"
|
|
|
:title "Extra tags to add for every imported page. Separate by comma, or leave it empty."}
|
|
|
"Extra tags to add:"]
|
|
|
[:div.mt-1.sm:mt-0.sm:col-span-2
|
|
|
@@ -300,8 +305,8 @@
|
|
|
{:for "zotero_data_directory"}
|
|
|
"Zotero data directory"
|
|
|
[:a.ml-2
|
|
|
- {:title "Set Zotero data directory to open pdf attachment in Logseq. Click to learn more."
|
|
|
- :href "https://www.zotero.org/support/zotero_data"
|
|
|
+ {:title "Set Zotero data directory to open pdf attachment in Logseq. Click to learn more."
|
|
|
+ :href "https://www.zotero.org/support/zotero_data"
|
|
|
:target "_blank"}
|
|
|
(svg/info)]]
|
|
|
[:div.mt-1.sm:mt-0.sm:col-span-2
|
|
|
@@ -322,9 +327,9 @@
|
|
|
"Please enter your profile name"]]]
|
|
|
|
|
|
[:input.form-input.block.w-full.sm:text-sm.sm:leading-5.my-2
|
|
|
- {:auto-focus true
|
|
|
+ {:auto-focus true
|
|
|
:default-value ""
|
|
|
- :on-change (fn [e] (reset! input (util/evalue e)))}]
|
|
|
+ :on-change (fn [e] (reset! input (util/evalue e)))}]
|
|
|
|
|
|
[:div.mt-5.sm:mt-4.sm:flex.sm:flex-row-reverse
|
|
|
[:span.flex.w-full.rounded-md.shadow-sm.sm:ml-3.sm:w-auto
|
|
|
@@ -340,7 +345,7 @@
|
|
|
(state/close-modal!))))]
|
|
|
[:span.mt-3.flex.w-full.rounded-md.shadow-sm.sm:mt-0.sm:w-auto
|
|
|
[:button.inline-flex.justify-center.w-full.rounded-md.border.border-gray-300.px-4.py-2.bg-white.text-base.leading-6.font-medium.text-gray-700.shadow-sm.hover:text-gray-500.focus:outline-none.focus:border-blue-300.focus:shadow-outline-blue.transition.ease-in-out.duration-150.sm:text-sm.sm:leading-5
|
|
|
- {:type "button"
|
|
|
+ {:type "button"
|
|
|
:on-click close-fn}
|
|
|
"Cancel"]]]]))
|
|
|
|
|
|
@@ -358,27 +363,27 @@
|
|
|
(p/let [_ (setting/set-profile profile)]
|
|
|
(reset! profile* profile))))}
|
|
|
(map-indexed (fn [i x] [:option
|
|
|
- {:key i
|
|
|
- :value x}
|
|
|
+ {:key i
|
|
|
+ :value x}
|
|
|
x]) (setting/all-profiles))]
|
|
|
(ui/button
|
|
|
- "New profile"
|
|
|
- :small? true
|
|
|
- :class "ml-4"
|
|
|
- :on-click
|
|
|
- (fn []
|
|
|
- (state/set-modal!
|
|
|
- (fn [close-fn]
|
|
|
- (profile-name-dialog-inner profile* close-fn)))))
|
|
|
+ "New profile"
|
|
|
+ :small? true
|
|
|
+ :class "ml-4"
|
|
|
+ :on-click
|
|
|
+ (fn []
|
|
|
+ (state/set-modal!
|
|
|
+ (fn [close-fn]
|
|
|
+ (profile-name-dialog-inner profile* close-fn)))))
|
|
|
(ui/button
|
|
|
- "Delete profile!"
|
|
|
- :small? true
|
|
|
- :background "red"
|
|
|
- :class "ml-4"
|
|
|
- :on-click
|
|
|
- (fn []
|
|
|
- (p/let [_ (setting/remove-profile @profile*)]
|
|
|
- (reset! profile* (setting/profile)))))]])
|
|
|
+ "Delete profile!"
|
|
|
+ :small? true
|
|
|
+ :background "red"
|
|
|
+ :class "ml-4"
|
|
|
+ :on-click
|
|
|
+ (fn []
|
|
|
+ (p/let [_ (setting/remove-profile @profile*)]
|
|
|
+ (reset! profile* (setting/profile)))))]])
|
|
|
|
|
|
(rum/defcs add-all-items <
|
|
|
(rum/local nil ::progress)
|
|
|
@@ -393,24 +398,24 @@
|
|
|
"Add all zotero items"]
|
|
|
[:div.mt-1.sm:mt-0.sm:col-span-2
|
|
|
(ui/button
|
|
|
- @(::fetching-button state)
|
|
|
- :on-click
|
|
|
- (fn []
|
|
|
- (go
|
|
|
- (let [_ (reset! (::fetching-button state) "Fetching..")
|
|
|
- total (<! (api/all-top-items-count))
|
|
|
- _ (reset! (::fetching-button state) "Add all")]
|
|
|
- (when (.confirm
|
|
|
- js/window
|
|
|
- (str "This will import all your zotero items and add total number of " total " pages. Do you wish to continue?"))
|
|
|
-
|
|
|
- (reset! (::total state) total)
|
|
|
- (<! (zotero-handler/add-all (::progress state)))
|
|
|
- (reset! (::total state) false)
|
|
|
- (notification/show! "Successfully added all items!" :success))))))]]
|
|
|
+ @(::fetching-button state)
|
|
|
+ :on-click
|
|
|
+ (fn []
|
|
|
+ (go
|
|
|
+ (let [_ (reset! (::fetching-button state) "Fetching..")
|
|
|
+ total (<! (api/all-top-items-count))
|
|
|
+ _ (reset! (::fetching-button state) "Add all")]
|
|
|
+ (when (.confirm
|
|
|
+ js/window
|
|
|
+ (str "This will import all your zotero items and add total number of " total " pages. Do you wish to continue?"))
|
|
|
+
|
|
|
+ (reset! (::total state) total)
|
|
|
+ (<! (zotero-handler/add-all (::progress state)))
|
|
|
+ (reset! (::total state) false)
|
|
|
+ (notification/show! "Successfully added all items!" :success))))))]]
|
|
|
(ui/admonition
|
|
|
- :warning
|
|
|
- "If you have a lot of items in Zotero, adding them all can slow down Logseq. You can type /zotero to import specific item on demand instead.")
|
|
|
+ :warning
|
|
|
+ "If you have a lot of items in Zotero, adding them all can slow down Logseq. You can type /zotero to import specific item on demand instead.")
|
|
|
|
|
|
(when @(::total state)
|
|
|
[:div.row
|
|
|
@@ -460,18 +465,18 @@
|
|
|
(defn open-button [full-path]
|
|
|
(if (str/ends-with? (str/lower-case full-path) "pdf")
|
|
|
(ui/button
|
|
|
- "open"
|
|
|
- :small? true
|
|
|
- :on-click
|
|
|
- (fn [e]
|
|
|
- (when-let [current (pdf-assets/inflate-asset full-path)]
|
|
|
- (util/stop e)
|
|
|
- (state/set-state! :pdf/current current))))
|
|
|
+ "open"
|
|
|
+ :small? true
|
|
|
+ :on-click
|
|
|
+ (fn [e]
|
|
|
+ (when-let [current (pdf-assets/inflate-asset full-path)]
|
|
|
+ (util/stop e)
|
|
|
+ (state/set-state! :pdf/current current))))
|
|
|
(ui/button
|
|
|
- "open"
|
|
|
- :small? true
|
|
|
- :target "_blank"
|
|
|
- :href full-path)))
|
|
|
+ "open"
|
|
|
+ :small? true
|
|
|
+ :target "_blank"
|
|
|
+ :href full-path)))
|
|
|
|
|
|
(rum/defc zotero-imported-file
|
|
|
[item-key filename]
|
|
|
@@ -481,10 +486,10 @@
|
|
|
full-path
|
|
|
(str "file://"
|
|
|
(util/node-path.join
|
|
|
- (setting/setting :zotero-data-directory)
|
|
|
- "storage"
|
|
|
- item-key
|
|
|
- filename))]
|
|
|
+ (setting/setting :zotero-data-directory)
|
|
|
+ "storage"
|
|
|
+ item-key
|
|
|
+ filename))]
|
|
|
(open-button full-path))))
|
|
|
|
|
|
(rum/defc zotero-linked-file
|
|
|
@@ -495,6 +500,6 @@
|
|
|
full-path
|
|
|
(str "file://"
|
|
|
(util/node-path.join
|
|
|
- (setting/setting :zotero-linked-attachment-base-directory)
|
|
|
- (str/replace-first path "attachments:" "")))]
|
|
|
+ (setting/setting :zotero-linked-attachment-base-directory)
|
|
|
+ (str/replace-first path "attachments:" "")))]
|
|
|
(open-button full-path))))
|