From bff7d4adf2c8726c35403eb74352628197ed062d Mon Sep 17 00:00:00 2001 From: Bryce Covert Date: Sun, 30 May 2021 09:16:56 -0700 Subject: [PATCH] Added new typeahead approach --- dev.cljs.edn | 7 ++++- package-lock.json | 11 ++++++++ package.json | 1 + project.clj | 4 +-- src/cljs/auto_ap/subs.cljs | 26 ++++++++++++------- .../auto_ap/views/components/typeahead.cljs | 18 +++++-------- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/dev.cljs.edn b/dev.cljs.edn index 145a36f1..1ab2394f 100644 --- a/dev.cljs.edn +++ b/dev.cljs.edn @@ -6,9 +6,14 @@ :infer-externs true :closure-defines {cljs.core/*global* "window"} + :npm-deps true + :foreign-libs [{:file "node_modules/minisearch/dist/es/index.js" + :provides ["minisearch"] + :global-exports {minisearch MiniSearch}}] :bundle-cmd {:none ["npx" "webpack" "--mode=development" :output-to "--output-path" :final-output-dir "--output-filename" :final-output-filename] :default ["npx" "webpack" "--mode=production" :output-to "--output-path" :final-output-dir - "--output-filename" :final-output-filename]}} + "--output-filename" :final-output-filename]} + } diff --git a/package-lock.json b/package-lock.json index 55d1a41b..09e02390 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "downshift": "^6.1.3", "dropzone": "^4.3.0", + "minisearch": "^3.0.2", "prop-types": "^15.7.2", "react": "^17.0.1", "react-datepicker": "^2.1.0", @@ -1217,6 +1218,11 @@ "node": ">=6" } }, + "node_modules/minisearch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-3.0.2.tgz", + "integrity": "sha512-7rTrJEzovKNi5LSwiIr5aCfJNNo6Lk4O9HTVzjFTMdp+dSr6UisUnEqdwj4rBgNcAcaWW5ClpXnpgTurv8PGqA==" + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -3160,6 +3166,11 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "minisearch": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-3.0.2.tgz", + "integrity": "sha512-7rTrJEzovKNi5LSwiIr5aCfJNNo6Lk4O9HTVzjFTMdp+dSr6UisUnEqdwj4rBgNcAcaWW5ClpXnpgTurv8PGqA==" + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", diff --git a/package.json b/package.json index 3ec39f69..65e22378 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dependencies": { "downshift": "^6.1.3", "dropzone": "^4.3.0", + "minisearch": "^3.0.2", "prop-types": "^15.7.2", "react": "^17.0.1", "react-datepicker": "^2.1.0", diff --git a/project.clj b/project.clj index 7bc5a5a8..ef6132ca 100644 --- a/project.clj +++ b/project.clj @@ -86,9 +86,7 @@ ;; needed for java 11 - [javax.xml.bind/jaxb-api "2.4.0-b180830.0359"] - - [coderafting/memsearch "0.1.0"]] + [javax.xml.bind/jaxb-api "2.4.0-b180830.0359"]] :managed-dependencies [;; explicit dependencies to get to latest versions for above [com.fasterxml.jackson.core/jackson-core "2.12.0"] [com.fasterxml.jackson.core/jackson-databind "2.12.0"] diff --git a/src/cljs/auto_ap/subs.cljs b/src/cljs/auto_ap/subs.cljs index c9085009..623aef23 100644 --- a/src/cljs/auto_ap/subs.cljs +++ b/src/cljs/auto_ap/subs.cljs @@ -3,7 +3,10 @@ [auto-ap.utils :refer [by]] [clojure.string :as str] [goog.crypt.base64 :as base64] - [memsearch.core :as ms])) + [minisearch :as ms])) +(set! *warn-on-infer* true) + +(def MiniSearch (aget ms "default")) (re-frame/reg-sub ::client @@ -65,10 +68,13 @@ ::accounts-index :<- [::accounts] (fn [accounts] - (ms/text-index (map (fn [v] {:id (:id v) - :content (str (:numeric-code v) " " (:name v))}) - accounts) - {:maintain-actual? true}))) + (doto (MiniSearch. #js {:fields #js ["numeric-code" "name" "content"] + :storeFields #js ["id" "numeric-code" "name" "content"]}) + (.addAll (clj->js (map (fn [v] {:id (:id v) + :name (:name v) + :numeric-code (:numeric-code v) + :content (str (:numeric-code v) " " (:name v))}) + accounts)))))) @@ -217,10 +223,12 @@ ::searchable-vendors-index :<- [::searchable-vendors] (fn [searchable-vendors] - (ms/text-index (map (fn [v] {:id (:id v) - :content (:name v)}) - searchable-vendors) - {:maintain-actual? true}))) + (doto (MiniSearch. #js {:fields #js ["name" "content"] + :storeFields #js ["id" "name" "content"]}) + (.addAll (clj->js (map (fn [v] {:id (:id v) + :name (:name v) + :content (:name v)}) + searchable-vendors)))))) (re-frame/reg-sub ::all-vendors diff --git a/src/cljs/auto_ap/views/components/typeahead.cljs b/src/cljs/auto_ap/views/components/typeahead.cljs index a447e39b..05fd05b6 100644 --- a/src/cljs/auto_ap/views/components/typeahead.cljs +++ b/src/cljs/auto_ap/views/components/typeahead.cljs @@ -3,9 +3,9 @@ [reagent.ratom :as ra] [clojure.string :as str] [clojure.set :as set] - [memsearch.core :as ms] [downshift :as ds :refer [useCombobox]] [react])) + (set! *warn-on-infer* true) ;; TODO: This avoids the use of inferred externs by using aget. You could just use the ^js tag though @@ -21,7 +21,7 @@ :else (aget actions-and-changes "changes"))) -(defn typeahead-v3-internal [{:keys [class style disabled entities entity->text entities-by-id entity-index on-change disabled value name auto-focus] :or {disabled false} :as i}] +(defn typeahead-v3-internal [{:keys [class style disabled entities ^js entity->text entities-by-id entity-index on-change disabled value name auto-focus] :or {disabled false} :as i}] (let [[items set-items] (react/useState (map clj->js entities)) [getLabelProps getMenuProps getComboboxProps getToggleButtonProps getInputProps getItemProps isOpen highlightedIndex selectItem selectedItem setInputValue] (as-> (useCombobox (clj->js {:items items @@ -29,15 +29,11 @@ :defaultSelectedItem value :onInputValueChange (fn [input] (if entities-by-id - (->> (ms/text-search (aget input "inputValue") entity-index) - (sort-by (fn [[k v]] - (- (:score v)))) - (map (fn [[x]] - (entities-by-id x) - )) - (take 5) - clj->js - set-items) + (do + (->> (.search entity-index (or (aget input "inputValue") "") #js {:fuzzy 0.2} ) + clj->js + (take 10) + (set-items))) (set-items (map clj->js (take 5 (filter (fn [x] (str/includes? (or (some-> (entity->text x) str/lower-case) "") (or (some-> (aget input "inputValue") str/lower-case) "")))