Replace fuzzy with fuse and stricter options (#6132)

* Replace fuzzy with fuse and stricter options

* Fix performance issue on jquery-ui autocompleter

https://bugs.jqueryui.com/ticket/15082

[ci skip]
pull/6134/head
Oliver Günther 7 years ago committed by GitHub
parent e1e5aa7ff1
commit 8945430cf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      frontend/app/components/common/autocomplete/lazyloaded/lazyloaded-autocompleter.ts
  2. 1
      frontend/app/components/projects/project-menu-autocomplete/project-menu-autocomplete.component.ts
  3. 8
      frontend/app/helpers/debug_output.ts
  4. 2
      frontend/app/vendors.js
  5. 15
      frontend/npm-shrinkwrap.json
  6. 4
      frontend/package.json
  7. 4
      spec/features/projects/project_autocomplete_spec.rb

@ -1,4 +1,5 @@
import * as fuzzy from 'fuzzy';
import * as Fuse from 'fuse.js';
import {timeOutput} from '../../../../helpers/debug_output';
export interface IAutocompleteItem<T> {
label:string;
@ -13,6 +14,9 @@ export abstract class ILazyAutocompleterBridge<T> {
// Input autocomplete element
public input:JQuery;
// Fuzzy instance for the results
public fuseInstance:any;
public constructor(public widgetName:string) {
LazyLoadedAutocompleter.register(widgetName, this);
}
@ -55,9 +59,7 @@ export abstract class ILazyAutocompleterBridge<T> {
return items;
}
const options = { extract: (i:IAutocompleteItem<T>) => i.label };
const results = fuzzy.filter(term, items, options);
return results.map(el => el.original);
return this.fuseInstance.search(term) as any;
}
/**
@ -85,13 +87,25 @@ export abstract class ILazyAutocompleterBridge<T> {
this.currentPage = 0;
this.input = input;
this.input[this.widgetName].call(this.input, this.setupParams(items));
const options = {
shouldSort: true,
tokenize: true,
threshold: 0.2,
location: 0,
distance: 100,
maxPatternLength: 16,
minMatchCharLength: 2,
keys: ['label']
};
this.fuseInstance = new Fuse(items, options);
}
protected setupParams(autocompleteValues:IAutocompleteItem<T>[]) {
const ctrl = this;
return {
delay: 0,
delay: 50,
source: function (request:any, response:any) {
const fuzzyResults = ctrl.fuzzySearch(autocompleteValues, request.term);
response(ctrl.augmentedResultSet(autocompleteValues, fuzzyResults));

@ -180,6 +180,7 @@ export class ProjectMenuAutocompleteController extends ILazyAutocompleterBridge<
*/
protected augmentedResultSet(items:ProjectAutocompleteItem[], matched:ProjectAutocompleteItem[]) {
const matches = matched.map(el => el.object.identifier);
console.log(matches);
const matchedParents = _.flatten(matched.map(el => el.object.parents));
const results:ProjectAutocompleteItem[] = [];

@ -16,15 +16,17 @@ export function debugLog(...args:any[]) {
whenDebugging(() => console.log('[DEBUG] ', args.join('-- ')));
}
export function timeOutput(msg:string, cb:() => void) {
export function timeOutput(msg:string, cb:() => void):any {
if (DEBUG) {
var t0 = performance.now();
cb();
var results = cb();
var t1 = performance.now();
console.log(`%c${msg} [completed in ${(t1 - t0)} milliseconds.`, 'color:#00A093;');
return results;
} else {
cb();
return cb();
}
}

@ -81,7 +81,7 @@ require('jquery.caret');
// Text highlight for autocompleter
require('mark.js/dist/jquery.mark.min.js');
// Micro Text fuzzy search library
require('fuzzy');
require('fuse.js');
require('at.js/jquery.atwho.min.js');

@ -3178,10 +3178,10 @@
}
}
},
"fuzzy": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz",
"integrity": "sha1-THbsL/CsGjap3M+aAN+GIweNTtg="
"fuse.js": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.2.0.tgz",
"integrity": "sha1-8ESOgGmFW/Kj5oPNwdMg5+KgfvQ="
},
"generate-function": {
"version": "2.0.0",
@ -3742,9 +3742,10 @@
}
},
"jquery-ui": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz",
"integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE="
"version": "git://github.com/jquery/jquery-ui.git#74f8a0ac952f6f45f773312292baef1c26d81300",
"requires": {
"jquery": "3.1.1"
}
},
"jquery-ujs": {
"version": "1.2.2",

@ -81,12 +81,12 @@
"file-loader": "^0.8.1",
"fork-ts-checker-webpack-plugin": "^0.2.8",
"foundation-apps": "1.1.0",
"fuzzy": "^0.1.3",
"fuse.js": "^3.2.0",
"glob": "^4.5.3",
"happypack": "^4.0.0",
"html-loader": "^0.2.3",
"jquery": "^3.1.1",
"jquery-ui": "^1.12.1",
"jquery-ui": "git://github.com/jquery/jquery-ui#74f8a0ac952f6f45f773312292baef1c26d81300",
"jquery-ujs": "^1.2.2",
"jquery.caret": "^0.3.1",
"json5": "^0.5.0",

@ -91,9 +91,9 @@ describe 'Projects autocomplete page', type: :feature, js: true do
top_menu.search 'Plain other project'
within(top_menu.search_results) do
expect(page).to have_no_selector('.ui-menu-item-wrapper', text: 'Plain project')
expect(page).to have_selector('.ui-state-disabled .ui-menu-item-wrapper', text: '<strong>foobar</strong>')
expect(page).to have_selector('.ui-menu-item-wrapper', text: '» Plain other project')
expect(page).to have_selector('.ui-menu-item-wrapper.ui-state-active', text: '» Plain other project')
expect(page).to have_selector('.ui-menu-item-wrapper', text: 'Plain project')
end
# Visit a project

Loading…
Cancel
Save