mirror of https://github.com/logseq/logseq
Add a command to switch graphs (#4009)
* First pass at select-graph with select component * Add empty placeholder and move graph switch logic to events * Remove unused force? in shortcuts * Document additional option and make disabled open-select consistent * Address review feedback Add data check to :graph/switch, translation improvements and update browser to display graph names same as in the sidebar Co-authored-by: Tienson Qin <tiensonqin@gmail.com>pull/4016/head^2
parent
ca755f2605
commit
ec513a54d2
|
@ -1,4 +1,4 @@
|
|||
.cp__palette {
|
||||
.cp__palette, .cp__select {
|
||||
--palettle-input-height: 64px;
|
||||
--palettle-container-height: 75vh;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
|||
}
|
||||
|
||||
.command-results-wrap,
|
||||
.item-results-wrap,
|
||||
.search-results-wrap > div:first-child {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
|
|
@ -52,10 +52,10 @@
|
|||
[:div.has-help
|
||||
command-name
|
||||
(ui/tippy
|
||||
{:html doc
|
||||
:interactive true
|
||||
:fixed-position? true
|
||||
:position "right"}
|
||||
{:html doc
|
||||
:interactive true
|
||||
:fixed-position? true
|
||||
:position "right"}
|
||||
|
||||
[:small (svg/help-circle)])]
|
||||
|
||||
|
@ -148,7 +148,7 @@
|
|||
:tippy-distance 24
|
||||
:tippy-position (if sidebar? "left" "right")}
|
||||
page-name)])
|
||||
:empty-div [:div.text-gray-500.text-sm.px-4.py-2 "Search for a page"]
|
||||
:empty-placeholder [:div.text-gray-500.text-sm.px-4.py-2 "Search for a page"]
|
||||
:class "black"}))))))
|
||||
|
||||
(rum/defcs block-search-auto-complete < rum/reactive
|
||||
|
@ -170,7 +170,7 @@
|
|||
result
|
||||
{:on-chosen chosen-handler
|
||||
:on-enter non-exist-block-handler
|
||||
:empty-div [:div.text-gray-500.pl-4.pr-4 "Search for a block"]
|
||||
:empty-placeholder [:div.text-gray-500.pl-4.pr-4 "Search for a block"]
|
||||
:item-render (fn [{:block/keys [page uuid]}] ;; content returned from search engine is normalized
|
||||
(let [page (or (:block/original-name page)
|
||||
(:block/name page))
|
||||
|
@ -222,7 +222,7 @@
|
|||
matched-templates
|
||||
{:on-chosen (editor-handler/template-on-chosen-handler id)
|
||||
:on-enter non-exist-handler
|
||||
:empty-div [:div.text-gray-500.px-4.py-2.text-sm "Search for a template"]
|
||||
:empty-placeholder [:div.text-gray-500.px-4.py-2.text-sm "Search for a template"]
|
||||
:item-render (fn [[template _block-db-id]]
|
||||
template)
|
||||
:class "black"}))))))
|
||||
|
@ -441,23 +441,23 @@
|
|||
[:input.form-input.block.w-full.pl-2.sm:text-sm.sm:leading-5
|
||||
(merge
|
||||
(cond->
|
||||
{:key (str "modal-input-" (name id))
|
||||
:id (str "modal-input-" (name id))
|
||||
:type (or type "text")
|
||||
:on-change (fn [e]
|
||||
(swap! input-value assoc id (util/evalue e)))
|
||||
:auto-complete (if (util/chrome?) "chrome-off" "off")}
|
||||
placeholder
|
||||
(assoc :placeholder placeholder)
|
||||
autoFocus
|
||||
(assoc :auto-focus true))
|
||||
{:key (str "modal-input-" (name id))
|
||||
:id (str "modal-input-" (name id))
|
||||
:type (or type "text")
|
||||
:on-change (fn [e]
|
||||
(swap! input-value assoc id (util/evalue e)))
|
||||
:auto-complete (if (util/chrome?) "chrome-off" "off")}
|
||||
placeholder
|
||||
(assoc :placeholder placeholder)
|
||||
autoFocus
|
||||
(assoc :auto-focus true))
|
||||
(dissoc input-item :id))]])
|
||||
(ui/button
|
||||
"Submit"
|
||||
:on-click
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(on-submit command @input-value pos)))])))))
|
||||
"Submit"
|
||||
:on-click
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(on-submit command @input-value pos)))])))))
|
||||
|
||||
(rum/defc absolute-modal < rum/static
|
||||
[cp set-default-width? {:keys [top left rect]}]
|
||||
|
@ -501,7 +501,7 @@
|
|||
{:top (+ top offset-top (if (int? y-diff) y-diff 0))
|
||||
:max-height to-max-height
|
||||
:max-width 700
|
||||
;; TODO: auto responsive fixed size
|
||||
;; TODO: auto responsive fixed size
|
||||
:width "fit-content"
|
||||
:z-index 11}
|
||||
(when set-default-width?
|
||||
|
|
|
@ -12,45 +12,19 @@
|
|||
[frontend.handler.export :as export-handler]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.handler.web.nfs :as nfs-handler]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.modules.shortcut.core :as shortcut]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[frontend.fs :as fs]
|
||||
[frontend.version :as version]
|
||||
[reitit.frontend.easy :as rfe]
|
||||
[frontend.modules.outliner.file :as outliner-file]
|
||||
[rum.core :as rum]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.text :as text]
|
||||
[promesa.core :as p]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.extensions.srs :as srs]))
|
||||
|
||||
;; TODO: move to events
|
||||
(defn- open-repo-url [url]
|
||||
(repo-handler/push-if-auto-enabled! (state/get-current-repo))
|
||||
(state/set-current-repo! url)
|
||||
;; load config
|
||||
(common-handler/reset-config! url nil)
|
||||
(shortcut/refresh!)
|
||||
(when-not (= :draw (state/get-current-route))
|
||||
(route-handler/redirect-to-home!))
|
||||
(when-let [dir-name (config/get-repo-dir url)]
|
||||
(fs/watch-dir! dir-name))
|
||||
(srs/update-cards-due-count!))
|
||||
|
||||
(defn- switch-repo-if-writes-finished?
|
||||
[url]
|
||||
(if (outliner-file/writes-finished?)
|
||||
(open-repo-url url)
|
||||
(notification/show!
|
||||
"Please wait seconds until all changes are saved for the current graph."
|
||||
:warning)))
|
||||
[electron.ipc :as ipc]))
|
||||
|
||||
(rum/defc add-repo
|
||||
[args]
|
||||
|
@ -95,7 +69,7 @@
|
|||
(let [local-dir (config/get-local-dir url)
|
||||
graph-name (text/get-graph-name-from-path local-dir)]
|
||||
[:a {:title local-dir
|
||||
:on-click #(switch-repo-if-writes-finished? url)}
|
||||
:on-click #(state/pub-event! [:graph/switch url])}
|
||||
graph-name])
|
||||
[:a {:target "_blank"
|
||||
:href url}
|
||||
|
@ -239,7 +213,7 @@
|
|||
{:title short-repo-name
|
||||
:hover-detail repo-path ;; show full path on hover
|
||||
:options {:class "ml-1"
|
||||
:on-click #(switch-repo-if-writes-finished? url)}}))
|
||||
:on-click #(state/pub-event! [:graph/switch url])}}))
|
||||
switch-repos)
|
||||
links (->>
|
||||
(concat repo-links
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
(ns frontend.components.select
|
||||
"Generic component for fuzzy searching items to select an item. See
|
||||
select-config to add a new use or select-type for this component. To use the
|
||||
new select-type, set :ui/open-select to the select-type. See
|
||||
:select-graph/open command for an example."
|
||||
(:require [frontend.modules.shortcut.core :as shortcut]
|
||||
[frontend.context.i18n :as i18n]
|
||||
[frontend.search :as search]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[frontend.db :as db]
|
||||
[frontend.text :as text]
|
||||
[rum.core :as rum]
|
||||
[frontend.config :as config]
|
||||
[reitit.frontend.easy :as rfe]))
|
||||
|
||||
(rum/defc render-item
|
||||
[{:keys [id value]} chosen?]
|
||||
[:div.inline-grid.grid-cols-4.gap-x-4.w-full
|
||||
{:class (when chosen? "chosen")}
|
||||
[:span.col-span-3 value]
|
||||
[:div.col-span-1.justify-end.tip.flex
|
||||
(when id
|
||||
[:code.opacity-20.bg-transparent id])]])
|
||||
|
||||
(rum/defcs select <
|
||||
(shortcut/disable-all-shortcuts)
|
||||
(rum/local "" ::input)
|
||||
{:will-unmount (fn [state]
|
||||
(state/set-state! [:ui/open-select] nil)
|
||||
state)}
|
||||
[state {:keys [items limit on-chosen empty-placeholder prompt-key]
|
||||
:or {limit 100
|
||||
prompt-key :select/default-prompt}}]
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
(let [input (::input state)]
|
||||
[:div.cp__select.cp__select-main
|
||||
[:div.input-wrap
|
||||
[:input.cp__select-input.w-full
|
||||
{:type "text"
|
||||
:placeholder (t prompt-key)
|
||||
:auto-focus true
|
||||
:value @input
|
||||
:on-change (fn [e] (reset! input (util/evalue e)))}]]
|
||||
|
||||
[:div.item-results-wrap
|
||||
(ui/auto-complete
|
||||
(search/fuzzy-search items @input :limit limit :extract-fn :value)
|
||||
{:item-render render-item
|
||||
:class "cp__select-results"
|
||||
:on-chosen (fn [x]
|
||||
(state/close-modal!)
|
||||
(on-chosen x))
|
||||
:empty-placeholder (empty-placeholder t)})]])))
|
||||
|
||||
(defn select-config
|
||||
"Config that supports multiple types (uses) of this component. To add a new
|
||||
type, add a key with the value being a map with the following keys:
|
||||
|
||||
* :items-fn - fn that returns items with a :value key that are used for the
|
||||
fuzzy search and selection. Items can have an optional :id and are displayed
|
||||
lightly for a given item.
|
||||
* :on-chosen - fn that is given item when it is chosen.
|
||||
* :empty-placeholder - fn that returns hiccup html to render if no matched graphs found.
|
||||
* :prompt-key - dictionary keyword that prompts when components is first open.
|
||||
Defaults to :select/default-prompt."
|
||||
[]
|
||||
{:select-graph
|
||||
{:items-fn (fn []
|
||||
(->>
|
||||
(state/get-repos)
|
||||
(remove (fn [{:keys [url]}]
|
||||
(or (config/demo-graph? url)
|
||||
(= url (state/get-current-repo)))))
|
||||
(map (fn [{:keys [url]}]
|
||||
{:value (text/get-graph-name-from-path
|
||||
;; TODO: Use helper when a common one is refactored
|
||||
;; from components.repo
|
||||
(if (config/local-db? url)
|
||||
(config/get-local-dir url)
|
||||
(db/get-repo-path url)))
|
||||
:id (config/get-repo-dir url)
|
||||
:graph url}))))
|
||||
:prompt-key :select.graph/prompt
|
||||
:on-chosen #(state/pub-event! [:graph/switch (:graph %)])
|
||||
:empty-placeholder (fn [t]
|
||||
[:div.px-4.py-2
|
||||
[:div.mb-2 (t :select.graph/empty-placeholder-description)]
|
||||
(ui/button
|
||||
(t :select.graph/add-graph)
|
||||
:href (rfe/href :repo-add)
|
||||
:on-click state/close-modal!)])}})
|
||||
|
||||
(rum/defc select-modal < rum/reactive
|
||||
[]
|
||||
(when-let [select-type (state/sub [:ui/open-select])]
|
||||
(let [select-type-config (get (select-config) select-type)]
|
||||
(state/set-modal!
|
||||
#(select (-> select-type-config
|
||||
(select-keys [:on-chosen :empty-placeholder :prompt-key])
|
||||
(assoc :items ((:items-fn select-type-config)))))
|
||||
{:fullscreen? false
|
||||
:close-btn? false}))
|
||||
nil))
|
|
@ -10,6 +10,7 @@
|
|||
[frontend.components.theme :as theme]
|
||||
[frontend.components.widgets :as widgets]
|
||||
[frontend.components.plugins :as plugins]
|
||||
[frontend.components.select :as select]
|
||||
[frontend.config :as config]
|
||||
[frontend.context.i18n :as i18n]
|
||||
[frontend.db :as db]
|
||||
|
@ -545,6 +546,7 @@
|
|||
(ui/modal)
|
||||
(ui/sub-modal)
|
||||
(command-palette/command-palette-modal)
|
||||
(select/select-modal)
|
||||
(custom-context-menu)
|
||||
(plugins/custom-js-installer {:t t
|
||||
:current-repo current-repo
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
|
||||
:local
|
||||
[(rum/with-key (android-permission-alert)
|
||||
"andoird-permission-alert")
|
||||
"android-permission-alert")
|
||||
(rum/with-key (add-local-directory)
|
||||
"add-local-directory")]
|
||||
|
||||
|
|
|
@ -307,8 +307,10 @@
|
|||
(defonce local-repo "local")
|
||||
|
||||
(defn demo-graph?
|
||||
[]
|
||||
(= (state/get-current-repo) local-repo))
|
||||
([]
|
||||
(demo-graph? (state/get-current-repo)))
|
||||
([graph]
|
||||
(= graph local-repo)))
|
||||
|
||||
(defonce local-assets-dir "assets")
|
||||
(defonce recycle-dir ".recycle")
|
||||
|
|
|
@ -390,7 +390,11 @@
|
|||
|
||||
:tips/all-done "All Done"
|
||||
|
||||
:command-palette/prompt "Type a command"}
|
||||
:command-palette/prompt "Type a command"
|
||||
:select/default-prompt "Select one"
|
||||
:select.graph/prompt "Select a graph"
|
||||
:select.graph/empty-placeholder-description "No matched graphs. Do you want to add another one?"
|
||||
:select.graph/add-graph "Yes, add another graph"}
|
||||
|
||||
:de {:help/about "Über Logseq"
|
||||
:on-boarding/demo-graph "This is a demo graph, changes will not be saved until you open a local folder."
|
||||
|
@ -1958,7 +1962,12 @@
|
|||
:user/delete-your-account "Eliminar su cuenta"
|
||||
:user/delete-account-notice "Todas sus páginas publicadas en Logseq serán eliminadas."
|
||||
|
||||
:help/shortcut-page-title "Atajos personalizados"}
|
||||
:help/shortcut-page-title "Atajos personalizados"
|
||||
|
||||
:select/prompt "Seleccione uno"
|
||||
:select.graph/prompt "Seleccione un grafo"
|
||||
:select.graph/empty-placeholder-description "No encontramos un grafo. Queries añadir otro?"
|
||||
:select.graph/add-graph "Si, añadame otro grafo"}
|
||||
|
||||
:nb-NO {:on-boarding/title "Hei, og velkommen til Logseq!"
|
||||
:on-boarding/sharing "deling"
|
||||
|
|
|
@ -21,7 +21,10 @@
|
|||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.modules.shortcut.core :as st]
|
||||
[frontend.modules.outliner.file :as outliner-file]
|
||||
[frontend.commands :as commands]
|
||||
[frontend.spec :as spec]
|
||||
[frontend.state :as state]
|
||||
|
@ -32,7 +35,8 @@
|
|||
[frontend.modules.instrumentation.posthog :as posthog]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.encrypt :as encrypt]
|
||||
[promesa.core :as p]))
|
||||
[promesa.core :as p]
|
||||
[frontend.fs :as fs]))
|
||||
|
||||
;; TODO: should we move all events here?
|
||||
|
||||
|
@ -77,6 +81,25 @@
|
|||
(db/set-key-value repo :ast/version db-schema/ast-version)
|
||||
(srs/update-cards-due-count!)))
|
||||
|
||||
(defn- graph-switch [graph]
|
||||
(repo-handler/push-if-auto-enabled! (state/get-current-repo))
|
||||
(state/set-current-repo! graph)
|
||||
;; load config
|
||||
(common-handler/reset-config! graph nil)
|
||||
(st/refresh!)
|
||||
(when-not (= :draw (state/get-current-route))
|
||||
(route-handler/redirect-to-home!))
|
||||
(when-let [dir-name (config/get-repo-dir graph)]
|
||||
(fs/watch-dir! dir-name))
|
||||
(srs/update-cards-due-count!))
|
||||
|
||||
(defmethod handle :graph/switch [[_ graph]]
|
||||
(if (outliner-file/writes-finished?)
|
||||
(graph-switch graph)
|
||||
(notification/show!
|
||||
"Please wait seconds until all changes are saved for the current graph."
|
||||
:warning)))
|
||||
|
||||
(defmethod handle :graph/migrated [[_ _repo]]
|
||||
(js/alert "Graph migrated."))
|
||||
|
||||
|
|
|
@ -182,13 +182,11 @@
|
|||
|
||||
:editor/up {:desc "Move cursor up / Select up"
|
||||
:binding "up"
|
||||
:fn (editor-handler/shortcut-up-down :up)
|
||||
:force? true}
|
||||
:fn (editor-handler/shortcut-up-down :up)}
|
||||
|
||||
:editor/down {:desc "Move cursor down / Select down"
|
||||
:binding "down"
|
||||
:fn (editor-handler/shortcut-up-down :down)
|
||||
:force? true}
|
||||
:fn (editor-handler/shortcut-up-down :down)}
|
||||
|
||||
:editor/left {:desc "Move cursor left / Open selected block at beginning"
|
||||
:binding "left"
|
||||
|
@ -225,13 +223,11 @@
|
|||
|
||||
:editor/expand-block-children {:desc "Expand"
|
||||
:binding "mod+down"
|
||||
:fn editor-handler/expand!
|
||||
:force? true}
|
||||
:fn editor-handler/expand!}
|
||||
|
||||
:editor/collapse-block-children {:desc "Collapse"
|
||||
:binding "mod+up"
|
||||
:fn editor-handler/collapse!
|
||||
:force? true}
|
||||
:fn editor-handler/collapse!}
|
||||
|
||||
:editor/indent {:desc "Indent block"
|
||||
:binding "tab"
|
||||
|
@ -316,8 +312,11 @@
|
|||
|
||||
:command-palette/toggle {:desc "Toggle command palette"
|
||||
:binding "mod+shift+p"
|
||||
:fn (fn [] (state/toggle! :ui/command-palette-open?))
|
||||
:force? true}
|
||||
:fn (fn [] (state/toggle! :ui/command-palette-open?))}
|
||||
|
||||
:select-graph/open {:desc "Open select graph component"
|
||||
:fn (fn [] (state/set-state! :ui/open-select :select-graph))
|
||||
:binding "mod+shift+g"}
|
||||
|
||||
:command/run (when (util/electron?)
|
||||
{:desc "Run git command"
|
||||
|
@ -432,7 +431,7 @@
|
|||
:ui/toggle-cards {:desc "Toggle cards"
|
||||
:binding "t c"
|
||||
:fn ui-handler/toggle-cards!}
|
||||
;; :ui/toggle-between-page-and-file route-handler/toggle-between-page-and-file!
|
||||
;; :ui/toggle-between-page-and-file route-handler/toggle-between-page-and-file!
|
||||
|
||||
:git/commit {:desc "Git commit message"
|
||||
:binding "c"
|
||||
|
@ -499,6 +498,7 @@
|
|||
:shortcut.handler/editor-global
|
||||
(->
|
||||
(build-category-map [:command-palette/toggle
|
||||
:select-graph/open
|
||||
:editor/cycle-todo
|
||||
:editor/up
|
||||
:editor/down
|
||||
|
@ -680,6 +680,7 @@
|
|||
:pdf/next-page
|
||||
:command/run
|
||||
:command-palette/toggle
|
||||
:select-graph/open
|
||||
:sidebar/clear
|
||||
:sidebar/open-today-page
|
||||
:search/re-index
|
||||
|
|
|
@ -1216,7 +1216,8 @@
|
|||
:modal/label ""
|
||||
:modal/show? false
|
||||
:modal/fullscreen? false
|
||||
:modal/panel-content nil)))
|
||||
:modal/panel-content nil
|
||||
:ui/open-select nil)))
|
||||
|
||||
(defn get-db-batch-txs-chan
|
||||
[]
|
||||
|
|
|
@ -420,7 +420,7 @@
|
|||
{:keys [on-chosen
|
||||
on-shift-chosen
|
||||
get-group-name
|
||||
empty-div
|
||||
empty-placeholder
|
||||
item-render
|
||||
class]}]
|
||||
(let [current-idx (get state ::current-idx)]
|
||||
|
@ -452,8 +452,8 @@
|
|||
item-cp)
|
||||
|
||||
item-cp))])]
|
||||
(when empty-div
|
||||
empty-div))]))
|
||||
(when empty-placeholder
|
||||
empty-placeholder))]))
|
||||
|
||||
(def datepicker frontend.ui.date-picker/date-picker)
|
||||
|
||||
|
|
Loading…
Reference in New Issue