From 486c85ce9d5c78c7631501fc13452536a150061d Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 12 Apr 2018 09:17:05 -0700 Subject: [PATCH 1/8] Bring fuse.js back --- ui/package.json | 1 + ui/yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/ui/package.json b/ui/package.json index 3ca526e16876..649c495a33eb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -67,6 +67,7 @@ "ember-welcome-page": "^3.0.0", "eslint": "^4.13.1", "flat": "^4.0.0", + "fuse.js": "~3.2.0", "husky": "^0.14.3", "json-formatter-js": "^2.2.0", "lint-staged": "^6.0.0", diff --git a/ui/yarn.lock b/ui/yarn.lock index 7b9e912dccf3..6a6de9496597 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -4280,6 +4280,10 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" +fuse.js@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.2.0.tgz#f0448e8069855bf2a3e683cdc1d320e7e2a07ef4" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" From a7f6af958ed74f59a325079b12cb0931b233144a Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 12 Apr 2018 09:18:33 -0700 Subject: [PATCH 2/8] Add optional fuzzy search support to the searchable mixin This time around fuzzy, exact, and regex can all be toggled. Additionally, each search type gets its own set of keys to search for. This means fuzzy search can only look at name while regex and exact match will still look at ID. --- ui/app/mixins/searchable.js | 53 ++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/ui/app/mixins/searchable.js b/ui/app/mixins/searchable.js index 26557f75a468..958dc7ab830c 100644 --- a/ui/app/mixins/searchable.js +++ b/ui/app/mixins/searchable.js @@ -1,5 +1,7 @@ import Mixin from '@ember/object/mixin'; import { get, computed } from '@ember/object'; +import { reads } from '@ember/object/computed'; +import Fuse from 'npm:fuse.js'; /** Searchable mixin @@ -17,17 +19,65 @@ import { get, computed } from '@ember/object'; export default Mixin.create({ searchTerm: '', listToSearch: computed(() => []), + searchProps: null, + exactMatchSearchProps: reads('searchProps'), + regexSearchProps: reads('searchProps'), + fuzzySearchProps: reads('searchprops'), + + // Three search modes + exactMatchEnabled: true, + fuzzySearchEnabled: false, + regexEnabled: true, + + fuse: computed('listToSearch.[]', 'fuzzySearchProps.[]', function() { + return new Fuse(this.get('listToSearch'), { + shouldSort: true, + threshold: 0.6, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + keys: this.get('fuzzySearchProps') || [], + getFn(item, key) { + return get(item, key); + }, + }); + }), listSearched: computed('searchTerm', 'listToSearch.[]', 'searchProps.[]', function() { const searchTerm = this.get('searchTerm'); if (searchTerm && searchTerm.length) { - return regexSearch(searchTerm, this.get('listToSearch'), this.get('searchProps')); + const results = []; + if (this.get('exactMatchEnabled')) { + results.push( + ...exactMatchSearch( + searchTerm, + this.get('listToSearch'), + this.get('exactMatchSearchProps') + ) + ); + } + if (this.get('fuzzySearchEnabled')) { + results.push(...this.get('fuse').search(searchTerm)); + } + if (this.get('regexEnabled')) { + results.push( + ...regexSearch(searchTerm, this.get('listToSearch'), this.get('regexSearchProps')) + ); + } + return results.uniq(); } return this.get('listToSearch'); }), }); +function exactMatchSearch(term, list, keys) { + if (term.length) { + return list.filter(item => keys.some(key => get(item, key) === term)); + } +} + function regexSearch(term, list, keys) { if (term.length) { try { @@ -38,5 +88,6 @@ function regexSearch(term, list, keys) { } catch (e) { // Swallow the error; most likely due to an eager search of an incomplete regex } + return []; } } From 15a7f2c012fd0daf315e1fb6b56a8b80499c9db4 Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 12 Apr 2018 09:20:47 -0700 Subject: [PATCH 3/8] Apply new search features to the job index page --- ui/app/controllers/jobs/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/app/controllers/jobs/index.js b/ui/app/controllers/jobs/index.js index 4df1f084c3f3..769b48115bd2 100644 --- a/ui/app/controllers/jobs/index.js +++ b/ui/app/controllers/jobs/index.js @@ -25,6 +25,8 @@ export default Controller.extend(Sortable, Searchable, { sortDescending: true, searchProps: computed(() => ['id', 'name']), + fuzzySearchProps: computed(() => ['name']), + fuzzySearchEnabled: true, /** Filtered jobs are those that match the selected namespace and aren't children From 3fc73d15a91344d02c56df4081cde5d3b76ba001 Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 12 Apr 2018 09:21:38 -0700 Subject: [PATCH 4/8] Show how many jobs exist but are being hidden by the serach term --- ui/app/templates/jobs/index.hbs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/app/templates/jobs/index.hbs b/ui/app/templates/jobs/index.hbs index 34e24c33a224..8767c2355ab3 100644 --- a/ui/app/templates/jobs/index.hbs +++ b/ui/app/templates/jobs/index.hbs @@ -38,6 +38,9 @@