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
Gabriel Horner 2022-01-24 21:24:14 -05:00 committed by GitHub
parent ca755f2605
commit ec513a54d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 192 additions and 74 deletions

View File

@ -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;

View File

@ -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?

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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")]

View File

@ -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")

View File

@ -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"

View File

@ -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."))

View File

@ -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

View File

@ -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
[]

View File

@ -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)