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>
This commit is contained in:
Gabriel Horner
2022-01-24 21:24:14 -05:00
committed by GitHub
parent ca755f2605
commit ec513a54d2
12 changed files with 192 additions and 74 deletions

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