diff --git a/frontend/resources/styles/main/partials/left-toolbar.scss b/frontend/resources/styles/main/partials/left-toolbar.scss index 2e82347e0..0de27c611 100644 --- a/frontend/resources/styles/main/partials/left-toolbar.scss +++ b/frontend/resources/styles/main/partials/left-toolbar.scss @@ -7,9 +7,6 @@ .left-toolbar { background-color: $color-gray-50; -} - -.left-toolbar-inside { align-items: center; border-right: 1px solid $color-gray-60; display: flex; @@ -25,44 +22,47 @@ margin: 0; li { - align-items: center; - background-color: transparent; - border: 1px solid transparent; - cursor: pointer; - display: flex; - flex-shrink: 0; - height: 48px; - justify-content: center; position: relative; - width: 48px; color: $color-gray-20; - - svg { - fill: $color-gray-20; - height: 16px; - width: 16px; - } - - &:hover { - background-color: $color-primary; - color: $color-gray-50; + button { + background-color: transparent; + border: none; + cursor: pointer; + height: 48px; + width: 48px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: inherit; svg { - fill: $color-gray-50; + fill: $color-gray-20; + height: 16px; + width: 16px; } - } - &.selected { - background-color: $color-gray-60; - color: $color-primary; + &:hover { + background-color: $color-primary; + color: $color-gray-50; - svg { - fill: $color-primary; + svg { + fill: $color-gray-50; + } } - } - &.separator { - border-top: 1px solid $color-gray-60; + &.selected { + background-color: $color-gray-60; + color: $color-primary; + + svg { + fill: $color-primary; + } + } + + &.separator { + border-top: 1px solid $color-gray-60; + } } } diff --git a/frontend/resources/styles/main/partials/sidebar.scss b/frontend/resources/styles/main/partials/sidebar.scss index ff0817f6b..8ecf0266e 100644 --- a/frontend/resources/styles/main/partials/sidebar.scss +++ b/frontend/resources/styles/main/partials/sidebar.scss @@ -305,6 +305,12 @@ button.collapse-sidebar { justify-content: center; align-items: center; flex-grow: 1; + svg { + height: 18px; + width: 18px; + transform: rotate(45deg); + fill: $color-gray-20; + } } .shortcuts-close-button { display: flex; @@ -380,6 +386,7 @@ button.collapse-sidebar { cursor: pointer; margin-top: 4px; font-size: $fs12; + .section-name { color: $color-white; } @@ -408,6 +415,20 @@ button.collapse-sidebar { } } + .section-title, + .subsection-title { + &:hover { + background-color: $color-primary; + .subsection-name, + .section-name { + color: $color-gray-60; + } + svg { + fill: $color-gray-60; + } + } + } + .shortcut-name { border: 1px solid $color-gray-60; border-radius: 4px; @@ -441,4 +462,13 @@ button.collapse-sidebar { } } } + .not-found { + background-color: $color-gray-60; + padding: 4px 0; + color: $color-white; + display: flex; + justify-content: center; + margin-top: 4px; + font-size: $fs12; + } } diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index 106e6f775..4b27f56ad 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -47,16 +47,17 @@ :position (gpt/point x y)}] (st/emit! (dwm/upload-media-workspace params)))))] - [:li.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) - :on-click on-click} - [:* - i/image - [:& file-uploader {:input-id "image-upload" - :accept cm/str-image-types - :multi true - :ref ref - :on-selected on-files-selected}]]])) + [:li + [:button.tooltip.tooltip-right + {:alt (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) + :on-click on-click} + [:* + i/image + [:& file-uploader {:input-id "image-upload" + :accept cm/str-image-types + :multi true + :ref ref + :on-selected on-files-selected}]]]])) (mf/defc left-toolbar {::mf/wrap [mf/memo] @@ -67,61 +68,69 @@ select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %)) edition (mf/deref refs/selected-edition)] [:aside.left-toolbar - [:div.left-toolbar-inside - [:ul.left-toolbar-options - [:li.tooltip.tooltip-right + [:ul.left-toolbar-options + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.move" (sc/get-tooltip :move)) :class (when (and (nil? selected-drawtool) (not edition)) "selected") :on-click #(st/emit! :interrupt)} - i/pointer-inner] - [:li.tooltip.tooltip-right + i/pointer-inner]] + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame)) :class (when (= selected-drawtool :frame) "selected") :on-click (partial select-drawtool :frame) :data-test "artboard-btn"} - i/artboard] - [:li.tooltip.tooltip-right + i/artboard]] + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect)) :class (when (= selected-drawtool :rect) "selected") :on-click (partial select-drawtool :rect) :data-test "rect-btn"} - i/box] - [:li.tooltip.tooltip-right + i/box]] + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse)) :class (when (= selected-drawtool :circle) "selected") :on-click (partial select-drawtool :circle) :data-test "ellipse-btn"} - i/circle] - [:li.tooltip.tooltip-right + i/circle]] + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text)) :class (when (= selected-drawtool :text) "selected") :on-click (partial select-drawtool :text)} - i/text] + i/text]] - [:& image-upload] + [:& image-upload] - [:li.tooltip.tooltip-right + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve)) :class (when (= selected-drawtool :curve) "selected") :on-click (partial select-drawtool :curve) :data-test "curve-btn"} - i/pencil] - [:li.tooltip.tooltip-right + i/pencil]] + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path)) :class (when (= selected-drawtool :path) "selected") :on-click (partial select-drawtool :path) :data-test "path-btn"} - i/pen] + i/pen]] - [:li.tooltip.tooltip-right + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment)) :class (when (= selected-drawtool :comments) "selected") :on-click (partial select-drawtool :comments)} - i/chat]] + i/chat]]] - [:ul.left-toolbar-options.panels - [:li.tooltip.tooltip-right + [:ul.left-toolbar-options.panels + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette)) :class (when (contains? layout :textpalette) "selected") :on-click (fn [] @@ -130,9 +139,10 @@ (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :colorpalette) (-> (dw/toggle-layout-flag :textpalette) (vary-meta assoc ::ev/origin "workspace-left-toolbar")))))} - "Ag"] + "Ag"]] - [:li.tooltip.tooltip-right + [:li + [:button.tooltip.tooltip-right {:alt (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette)) :class (when (contains? layout :colorpalette) "selected") :on-click (fn [] @@ -141,8 +151,9 @@ (ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette) (-> (dw/toggle-layout-flag :colorpalette) (vary-meta assoc ::ev/origin "workspace-left-toolbar")))))} - i/palette] - [:li.tooltip.tooltip-right.separator + i/palette]] + [:li + [:button.tooltip.tooltip-right.separator {:alt (tr "workspace.toolbar.shortcuts" (sc/get-tooltip :show-shortcuts)) :class (when (contains? layout :shortcuts) "selected") :on-click (fn [] diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs index 1d0a56efa..6ba7c6bb7 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs @@ -19,6 +19,7 @@ [app.util.dom :as dom] [app.util.i18n :refer [tr]] [app.util.strings :refer [matches-search]] + [clojure.set :as set] [clojure.string] [cuerdas.core :as str] [rumext.alpha :as mf])) @@ -40,12 +41,24 @@ :esc "\u238B" :enter "\u23CE"} is-macos? (cf/check-platform? :macos) - char (if (contains? modified-keys (keyword key)) ((keyword char) modified-keys) char) + char (if (contains? modified-keys (keyword char)) ((keyword char) modified-keys) char) char (if (and is-macos? (contains? macos-keys (keyword char))) ((keyword char) macos-keys) char) unique-key (str (d/name command) "-" char)] [:* [:span.char-box {:key unique-key} char]])) +(defn translation-keyname + [type keyname] + (let [translat-pre (case type + :sc "shortcuts." + :sec "shortcut-section." + :sub-sec "shortcut-subsection.")] + (tr (str translat-pre (d/name keyname))))) + +(defn add-translation + [type item] + (map (fn [[k v]] [k (assoc v :translation (translation-keyname type k))]) item)) + (defn shortcuts->subsections "A function to obtain the list of subsections and their associated shortcus from the general map of shortcuts" @@ -53,24 +66,24 @@ (let [subsections (into #{} (mapcat :subsections) (vals shortcuts)) get-sc-by-subsection (fn [subsection [k v]] - (when (some #(= subsection %) (:subsections v)) k)) + (when (some #(= subsection %) (:subsections v)) {k v})) reduce-sc (fn [acc subsection] - (let [shortcuts-by-subsection (keep (partial get-sc-by-subsection subsection) shortcuts)] - (assoc acc subsection shortcuts-by-subsection)))] + (let [shortcuts-by-subsection (into {} (keep (partial get-sc-by-subsection subsection) shortcuts))] + (assoc acc subsection {:children shortcuts-by-subsection})))] (reduce reduce-sc {} subsections))) (mf/defc shortcuts-keys [{:keys [content command] :as props}] - (let [managed-list (if (coll? content) - content - (conj () content)) - split-sc (fn [sc] - (let [sc (cond-> sc (str/includes? sc "++") - (str/replace "++" "+plus"))] - (if (= (count sc) 1) - [sc] - (str/split sc #"\+| ")))) + (let [managed-list (if (coll? content) + content + (conj () content)) + split-sc (fn [sc] + (let [sc (cond-> sc (str/includes? sc "++") + (str/replace "++" "+plus"))] + (if (= (count sc) 1) + [sc] + (str/split sc #"\+| ")))) chars-list (map split-sc managed-list) last-element (last chars-list) short-char-list (if (= 1 (count chars-list)) @@ -82,175 +95,230 @@ [:* (for [char chars] [:& converted-chars {:char char :command command}]) - (when (not= chars penultimate) [:span.space ","])]) (when (not= last-element penultimate) [:* - [:span.space " or "] + [:span.space (tr "shortcuts.or")] (for [char last-element] [:& converted-chars {:char char :command command}])])])) (mf/defc shortcut-row - [{:keys [shortcuts elements filter-term match-section? match-subsection?] :as props}] - (let [reduce-translation (fn [acc element] (assoc acc element (tr (str "shortcuts." (d/name element))))) - translations (reduce reduce-translation {} elements) - filtered (if (or match-section? match-subsection?) - (vals translations) - (filter #(matches-search % (:term @filter-term)) (vals translations))) - sorted-filtered (sort filtered)] + [{:keys [elements filter-term match-section? match-subsection?] :as props}] + (let [shortcut-name (keys elements) + shortcut-translations (map #(translation-keyname :sc %) shortcut-name) + match-shortcut? (some #(matches-search % @filter-term) shortcut-translations) + filtered (if (and (or match-section? match-subsection?) (not match-shortcut?)) + shortcut-translations + (filter #(matches-search % @filter-term) shortcut-translations)) + sorted-filtered (sort filtered)] [:ul.sub-menu (for [command-translate sorted-filtered] - (let [command (first (filter (comp #{command-translate} translations) (keys translations))) - content (:command (command shortcuts)) - name (tr (str "shortcuts." (d/name command)))] - [:li.shortcut-name {:key command} - [:span.command-name name] + (let [sc-by-translate (first (filter #(= (:translation (second %)) command-translate) elements)) + [command comand-info] sc-by-translate + content (:command comand-info)] + [:li.shortcut-name {:key command-translate} + [:span.command-name command-translate] [:& shortcuts-keys {:content content :command command}]]))])) (mf/defc section-title - [{:keys [is-visible? section elem-n] :as props}] - (let [name (tr (str "shortcut-section." (d/name section)))] - [:div.section-title - [:span.collapesed-shortcuts {:class (when is-visible? "open")} i/arrow-slide] - [:span.section-name name] - [:span.shortcut-count "(" elem-n ")"]])) - - -(mf/defc subsection-title - [{:keys [subsection-name elements open-sections] :as props}] - (let [subsection-name2 (tr (str "shortcut-subsection." (d/name subsection-name)))] - [:div.subsection-title - [:span.collapesed-shortcuts {:class (when (some #(= % subsection-name) (:subsection @open-sections)) "open")} i/arrow-slide] - [:span.subsection-name subsection-name2] - [:span.shortcut-count "(" elements ")"]])) + [{:keys [is-visible? name is-sub?] :as props}] + [:div {:class (if is-sub? "subsection-title" "section-title")} + [:span.collapesed-shortcuts {:class (when is-visible? "open")} i/arrow-slide] + [:span {:class (if is-sub? "subsection-name" "section-name")} name]]) (mf/defc shortcut-subsection - [{:keys [shortcuts-by-group manage-sections shortcuts filter-term match-section? open-sections] :as props}] - (let [reduce-translation (fn [acc subsection] (assoc acc subsection (tr (str "shortcut-subsection." (d/name subsection))))) - translations (reduce reduce-translation {} (keys shortcuts-by-group)) - sorted-translations (sort (vals translations))] - [:ul.subsection-menu - (for [sub-translate sorted-translations] - (let [subsection (first (filter (comp #{sub-translate} translations) (keys translations))) - elements (subsection shortcuts-by-group) - visible? (some #(= % subsection) (:subsection @open-sections)) - match-subsection? (matches-search sub-translate (:term @filter-term)) + [{:keys [subsections manage-sections filter-term match-section? open-sections] :as props}] + (let [subsections-names (keys subsections) + subsection-translations (if (= :none (first subsections-names)) + (map #(translation-keyname :sc %) subsections-names) + (map #(translation-keyname :sub-sec %) subsections-names)) + sorted-translations (sort subsection-translations)] + ;; Basics section is treated different because it has no sub sections + (if (= :none (first subsections-names)) + (let [basic-shortcuts (:none subsections)] + [:& shortcut-row {:elements (:children basic-shortcuts) + :filter-term filter-term + :match-section? match-section? + :match-subsection? true}]) - keywords (subsection shortcuts-by-group) - matched-map (into {} (map (fn [element] {element (:translation (element shortcuts))}) keywords)) - translations (vals matched-map) - match-shortcut-in-sub? (some #(matches-search % (:term @filter-term)) translations) - shortcut-count (count (filter #(matches-search % (:term @filter-term)) translations))] - (when (and (or match-section? match-subsection? match-shortcut-in-sub?) (not= subsection :basics)) - [:li {:key subsection - :on-click (manage-sections subsection true)} - [:& subsection-title {:subsection-name subsection - :open-sections open-sections - :elements shortcut-count}] - [:div {:style {:display (if visible? "initial" "none")}} - [:& shortcut-row {:shortcuts shortcuts - :elements elements - :filter-term filter-term - :match-section? match-section? - :match-subsection? match-subsection?}]]])))])) + [:ul.subsection-menu + (for [sub-translated sorted-translations] + (let [sub-by-translate (first (filter #(= (:translation (second %)) sub-translated) subsections)) + [sub-name sub-info] sub-by-translate + visible? (some #(= % (:id sub-info)) @open-sections) + match-subsection? (matches-search (translation-keyname :sub-sec sub-name) @filter-term) + shortcut-names (map #(translation-keyname :sc %) (keys (:children sub-info))) + match-shortcuts? (some #(matches-search % @filter-term) shortcut-names)] + (when (or match-subsection? match-shortcuts? match-section?) + [:li {:key sub-translated + :on-click (manage-sections (:id sub-info))} + [:& section-title {:name sub-translated + :is-sub? true + :is-visible? visible?}] + + [:div {:style {:display (if visible? "initial" "none")}} + [:& shortcut-row {:elements (:children sub-info) + :filter-term filter-term + :match-section? match-section? + :match-subsection? match-subsection?}]]])))]))) (mf/defc shortcut-section - [{:keys [section shortcuts shortcuts-by-group manage-sections filter-term open-sections] :as props}] - (let [section-name (d/name section) - visible? (some #(= % section) (:section @open-sections)) - section-translation (tr (str "shortcut-section." section-name)) - match-section? (matches-search section-translation (:term @filter-term)) - subsections (map (fn [subsection] (tr (str "shortcut-subsection." (d/name subsection)))) (filter #(not= % :basics) (keys shortcuts-by-group))) - match-subsection? (some #(matches-search % (:term @filter-term)) subsections) - keywords (keys shortcuts) - matched-map (into {} (map (fn [element] {element (:translation (element shortcuts))}) keywords)) - translations (vals matched-map) - match-shortcut? (some #(matches-search % (:term @filter-term)) translations) - filtered-shortcuts (count (filter #(matches-search % (:term @filter-term)) translations))] + [{:keys [section manage-sections open-sections filter-term] :as props}] + (let [[section-key section-info] section + section-id (:id section-info) + section-translation (translation-keyname :sec section-key) + match-section? (matches-search section-translation @filter-term) + subsections (:children section-info) + subs-names (keys subsections) + subs-bodys (reduce #(conj %1 (:children (%2 subsections))) {} subs-names) + sub-trans (map #(if (= "none" (d/name %)) + nil + (translation-keyname :sub-sec %)) subs-names) + match-subsection? (some #(matches-search % @filter-term) sub-trans) + translations (map #(translation-keyname :sc %) (keys subs-bodys)) + match-shortcut? (some #(matches-search % @filter-term) translations) + visible? (some #(= % section-id) @open-sections)] (when (or match-section? match-subsection? match-shortcut?) - [:div {:on-click (manage-sections section false)} + [:div {:on-click (manage-sections section-id)} [:& section-title {:is-visible? visible? - :section section - :elem-n filtered-shortcuts}] - [:div {:style {:display (if visible? "initial" "none")}} - [:& shortcut-subsection {:shortcuts-by-group shortcuts-by-group - :manage-sections manage-sections - :match-section? match-section? - :open-sections open-sections - :filter-term filter-term - :shortcuts shortcuts}]]]))) + :is-sub? false + :name section-translation}] -(defn add-translation-to-shorcuts - [shortcuts] - (map (fn [[k v]] [k (assoc v :translation (tr (str "shortcuts." (d/name k))))]) shortcuts)) + [:div {:style {:display (if visible? "initial" "none")}} + [:& shortcut-subsection {:subsections subsections + :open-sections open-sections + :manage-sections manage-sections + :match-section? match-section? + :filter-term filter-term}]]]))) (mf/defc shortcuts-container [] (let [workspace-shortcuts app.main.data.workspace.shortcuts/shortcuts path-shortcuts app.main.data.workspace.path.shortcuts/shortcuts all-workspace-shortcuts (->> (d/deep-merge path-shortcuts workspace-shortcuts) - (add-translation-to-shorcuts) + (add-translation :sc) (into {})) dashboard-shortcuts (->> app.main.data.dashboard.shortcuts/shortcuts - (add-translation-to-shorcuts) + (add-translation :sc) (into {})) viewer-shortcuts (->> app.main.data.viewer.shortcuts/shortcuts - (add-translation-to-shorcuts) + (add-translation :sc) (into {})) - - all-shortcuts (d/deep-merge all-workspace-shortcuts dashboard-shortcuts viewer-shortcuts) - - workspace-sc-by-subsections (shortcuts->subsections all-workspace-shortcuts) - dashboard-sc-by-subsections (shortcuts->subsections dashboard-shortcuts) - viewer-sc-by-subsections (shortcuts->subsections viewer-shortcuts) - - ;; The basics section is treated separately because these elements - ;; are obtained from the rest of the listings of shortcuts. - basics-elements (concat (:basics workspace-sc-by-subsections) - (:basics dashboard-sc-by-subsections) - (:basics viewer-sc-by-subsections)) - reduce-translation (fn [acc sc] (assoc acc sc (tr (str "shortcuts." (d/name sc))))) - basics-translations (reduce reduce-translation {} basics-elements) - open-sections (mf/use-state {:section [:workspace] :subsection []}) - basics-open? (some #(= % :basics) (:section @open-sections)) - - search-term (mf/use-state {:term ""}) - search-match-basics-items? (some #(matches-search % (:term @search-term)) (vals basics-translations)) - search-match-basics? (matches-search :basics (:term @search-term)) + open-sections (mf/use-state [[1]]) + filter-term (mf/use-state "") close-fn #(st/emit! (dw/toggle-layout-flag :shortcuts)) + walk (fn walk [element parent-id] + (if (nil? element) + element + (let [rec-fn (fn [index [k item]] + (let [item-id (if (nil? parent-id) + [index] + (conj parent-id index))] + [k (assoc item :id item-id :children (walk (:children item) item-id))]))] + (into {} (map-indexed (partial rec-fn) element))))) + + workspace-sc-by-subsections (->> (shortcuts->subsections all-workspace-shortcuts) + (add-translation :sub-sec) + (into {})) + dashboard-sc-by-subsections (->> (shortcuts->subsections dashboard-shortcuts) + (add-translation :sub-sec) + (into {})) + viewer-sc-by-subsections (->> (shortcuts->subsections viewer-shortcuts) + (add-translation :sub-sec) + (into {})) + basics-elements (into {} (concat (:children (:basics workspace-sc-by-subsections)) + (:children (:basics dashboard-sc-by-subsections)) + (:children (:basics viewer-sc-by-subsections)))) + + workspace-sc-by-subsections (dissoc workspace-sc-by-subsections :basics) + dashboard-sc-by-subsections (dissoc dashboard-sc-by-subsections :basics) + viewer-sc-by-subsections (dissoc viewer-sc-by-subsections :bassics) + + all-shortcuts {:basics {:id [1] + :children {:none {:children basics-elements}} + :translation (tr "shortcut-section.basics")} + :workspace {:id [2] + :children workspace-sc-by-subsections + :translation (tr "shortcut-section.workspace")} + :dashboard {:id [3] + :children dashboard-sc-by-subsections + :translation (tr "shortcut-section.dashboard")} + :viewer {:id [4] + :children viewer-sc-by-subsections + :translation (tr "shortcut-section.viewer")}} + all-shortcuts (walk all-shortcuts nil) + + all-sc-names (map #(translation-keyname :sc %) (concat + (keys all-workspace-shortcuts) + (keys dashboard-shortcuts) + (keys viewer-shortcuts))) + + all-sub-names (map #(translation-keyname :sub-sec %) (concat + (keys workspace-sc-by-subsections) + (keys dashboard-sc-by-subsections) + (keys viewer-sc-by-subsections))) + all-section-names (map #(translation-keyname :sec %) (keys all-shortcuts)) + all-item-names (concat all-sc-names all-sub-names all-section-names) + match-any? (some #(matches-search % @filter-term) all-item-names) + + manage-sections + (fn [item] + (fn [event] + (dom/stop-propagation event) + (let [is-present? (some #(= % item) @open-sections) + new-value (if is-present? + (filterv (fn [element] (not= element item)) @open-sections) + (conj @open-sections item))] + (reset! open-sections new-value)))) + + add-ids (fn [acc node] + (let [id (:id node) + addition (case (count id) + 1 id + 2 [[(first id)] id] + 3 [[(first id)] [(first id) (second id)]] + "default" nil)] + (if (= 1 (count addition)) + (conj acc addition) + (into [] (concat acc addition))))) + + manage-section-on-search + (fn [section term] + (let [node-seq (tree-seq :children #(vals (:children %)) (get all-shortcuts section))] + (reduce (fn [acc node] + (if (matches-search (:translation node) term) + (add-ids acc node) + acc)) + [] + node-seq))) + + manage-sections-on-search + (fn [term] + (if (= term "") + (reset! open-sections [[1]]) + (let [ids (set/union (manage-section-on-search :basics term) + (manage-section-on-search :workspace term) + (manage-section-on-search :dashboard term) + (manage-section-on-search :viewer term))] + (reset! open-sections ids)))) + on-search-term-change (mf/use-callback (fn [event] (let [value (dom/get-target-val event)] - (swap! search-term assoc :term value)))) + (manage-sections-on-search value) + (reset! filter-term value)))) on-search-clear-click (mf/use-callback (fn [_] - (swap! search-term assoc :term ""))) - - manage-sections - (fn [item is-sub?] - (fn [event] - (dom/stop-propagation event) - (let [modify-atom - (fn [is-sub? item atom-name] - (let [keyword-name (if is-sub? - :subsection - :section) - is-present? (some #(= % item) (keyword-name atom-name)) - value-vector (get atom-name keyword-name) - new-value (if is-present? - (filterv (fn [element] (not= element item)) value-vector) - (conj value-vector item))] - (assoc atom-name keyword-name new-value)))] - - (reset! open-sections (modify-atom is-sub? item @open-sections)))))] + (reset! open-sections [[1]]) + (reset! filter-term "")))] [:div.shortcuts [:div.shortcuts-header @@ -263,48 +331,22 @@ {:id "shortcut-search" :placeholder (tr "shortcuts.search-placeholder") :type "text" - :value (:term @search-term) + :value @filter-term :on-change on-search-term-change :auto-complete "off"}] - (if (str/empty? (:term @search-term)) + (if (str/empty? @filter-term) [:span.icon-wrapper i/search] [:span.icon-wrapper.close {:on-click on-search-clear-click} i/close])]] + (if match-any? + [:div.shortcut-list + (for [section all-shortcuts] + [:& shortcut-section + {:section section + :manage-sections manage-sections + :open-sections open-sections + :filter-term filter-term}])] - [:div.shortcut-list - (when (or search-match-basics-items? search-match-basics?) - [:div {:on-click (manage-sections :basics false)} - [:& section-title {:section :basics - :is-visible? basics-open? - :elem-n (count basics-elements)}] - [:div {:style {:display (if basics-open? "initial" "none")}} - [:& shortcut-row {:shortcuts all-shortcuts - :elements basics-elements - :filter-term search-term - :match-section? search-match-basics?}]]]) - - [:& shortcut-section - {:shortcuts-by-group workspace-sc-by-subsections - :manage-sections manage-sections - :open-sections open-sections - :filter-term search-term - :shortcuts all-workspace-shortcuts - :section :workspace}] - - [:& shortcut-section - {:shortcuts-by-group dashboard-sc-by-subsections - :manage-sections manage-sections - :open-sections open-sections - :filter-term search-term - :shortcuts dashboard-shortcuts - :section :dashboard}] - - [:& shortcut-section - {:shortcuts-by-group viewer-sc-by-subsections - :manage-sections manage-sections - :open-sections open-sections - :filter-term search-term - :shortcuts viewer-shortcuts - :section :viewer}]]])) + [:div.not-found (tr "shortcuts.not-found")])])) diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 89d4f668c..628e35997 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -4152,3 +4152,12 @@ msgstr "Update" msgid "workspace.viewport.click-to-close-path" msgstr "Click to close the path" + +msgid "shortcut-subsection.zoom-viewer" +msgstr "Zoom" + +msgid "shortcuts.or" +msgstr " or " + +msgid "shortcuts.not-found" +msgstr "No shortcuts found" \ No newline at end of file diff --git a/frontend/translations/es.po b/frontend/translations/es.po index c99409728..17a5d933d 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -4335,3 +4335,12 @@ msgstr "Actualizar" msgid "workspace.viewport.click-to-close-path" msgstr "Pulsar para cerrar la ruta" + +msgid "shortcut-subsection.zoom-viewer" +msgstr "Zoom" + +msgid "shortcuts.or" +msgstr " o " + +msgid "shortcuts.not-found" +msgstr "No hay resultados" \ No newline at end of file