Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP Add fuzzy search to popup menu and search #367

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/base/Modeler.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
BpmnPropertiesProviderModule as bpmnPropertiesProviderModule
} from 'bpmn-js-properties-panel';

import fuzzySearchModule from './features/fuzzy-search';

/**
* @typedef {import('bpmn-js/lib/BaseViewer').BaseViewerOptions} BaseViewerOptions
*
Expand Down Expand Up @@ -57,7 +59,8 @@ Modeler.prototype._extensionModules = [
minimapModule,
executableFixModule,
propertiesPanelModule,
bpmnPropertiesProviderModule
bpmnPropertiesProviderModule,
fuzzySearchModule
];

Modeler.prototype._modules = [].concat(
Expand Down
120 changes: 120 additions & 0 deletions lib/base/features/fuzzy-search/fuzzySearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Fuse from 'fuse.js/basic';

/**
* @typedef { {
* index: number;
* match: boolean;
* value: string;
* } } Token
*
* @typedef {Token[]} Tokens
*/

/**
* @template R
*
* @typedef { {
* item: R,
* tokens: Record<string, Tokens>
* } } SearchResult
*/

/**
* Search items using fuzzy search.
*
* @template T
*
* @param {T[]} items
* @param {string} pattern
* @param { {
* keys: string[];
* } } options
*
* @returns {SearchResult<T>[]}
*/
export default function fuzzySearch(items, pattern, options) {
const fuse = new Fuse(items, {

Check warning on line 36 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L36

Added line #L36 was not covered by tests
includeScore: true,
ignoreLocation: true,
includeMatches: true,
threshold: 0.25,
keys: options.keys
});

const result = fuse.search(pattern);

Check warning on line 44 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L44

Added line #L44 was not covered by tests

console.log(result);

Check warning on line 46 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L46

Added line #L46 was not covered by tests

return result.map(({ item, matches }) => {
let tokens = {};

Check warning on line 49 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L48-L49

Added lines #L48 - L49 were not covered by tests

for (const key of options.keys) {

Check warning on line 51 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L51

Added line #L51 was not covered by tests

if (item[key] && item[key].length) {
tokens = {

Check warning on line 54 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L53-L54

Added lines #L53 - L54 were not covered by tests
...tokens,
[key]: matchesToTokens(matches, key, item[key])
};
} else {
tokens = {

Check warning on line 59 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L59

Added line #L59 was not covered by tests
...tokens,
[key]: []
};
}
}

return {

Check warning on line 66 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L66

Added line #L66 was not covered by tests
item,
tokens
};
});
};

function matchesToTokens(matches, key, value) {
const match = matches.find((match) => match.key === key);

Check warning on line 74 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L74

Added line #L74 was not covered by tests

if (!match) {
return [

Check warning on line 77 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L76-L77

Added lines #L76 - L77 were not covered by tests
{
index: 0,
value
}
];
}

const { indices } = match;

Check warning on line 85 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L85

Added line #L85 was not covered by tests

const tokensMatch = indices.map(([ start, end ]) => {
return {

Check warning on line 88 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L87-L88

Added lines #L87 - L88 were not covered by tests
index: start,
match: true,
value: match.value.slice(start, end + 1)
};
});

const tokens = [];

Check warning on line 95 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L95

Added line #L95 was not covered by tests

let lastIndex = 0;

Check warning on line 97 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L97

Added line #L97 was not covered by tests

tokensMatch.forEach((token, index) => {
if (token.index !== lastIndex) {
tokens.push({

Check warning on line 101 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L99-L101

Added lines #L99 - L101 were not covered by tests
index: lastIndex,
value: match.value.slice(lastIndex, token.index)
});
}

tokens.push(token);

Check warning on line 107 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L107

Added line #L107 was not covered by tests

lastIndex = token.index + token.value.length;

Check warning on line 109 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L109

Added line #L109 was not covered by tests

if (index === tokensMatch.length - 1 && lastIndex !== match.value.length) {
tokens.push({

Check warning on line 112 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L111-L112

Added lines #L111 - L112 were not covered by tests
index: lastIndex,
value: match.value.slice(lastIndex)
});
}
});

return tokens;

Check warning on line 119 in lib/base/features/fuzzy-search/fuzzySearch.js

View check run for this annotation

Codecov / codecov/patch

lib/base/features/fuzzy-search/fuzzySearch.js#L119

Added line #L119 was not covered by tests
}
5 changes: 5 additions & 0 deletions lib/base/features/fuzzy-search/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import fuzzySearch from './fuzzySearch';

export default {
search: [ 'value', fuzzySearch ]
};
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"diagram-js-grid": "^1.1.0",
"diagram-js-minimap": "^5.2.0",
"diagram-js-origin": "^1.4.0",
"fuse.js": "^7.0.0",
"inherits-browser": "^0.1.0",
"min-dash": "^4.2.2",
"zeebe-bpmn-moddle": "^1.7.0"
Expand Down