diff --git a/ui/package-lock.json b/ui/package-lock.json index e45b75a04..b8411fcfa 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -19,6 +19,7 @@ "@start9labs/emver": "0.1.5", "ajv": "^6.12.6", "core-js": "^3.17.2", + "fuse.js": "^6.4.6", "json-pointer": "^0.6.1", "jsonpointerx": "^1.1.4", "marked": "3.0.2", @@ -6842,6 +6843,14 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/fuse.js": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", + "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==", + "engines": { + "node": ">=10" + } + }, "node_modules/gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -16942,7 +16951,9 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "dev": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "core-js": { "version": "3.16.0", @@ -17089,7 +17100,9 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "dev": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "json-schema-traverse": { "version": "1.0.0", @@ -17133,7 +17146,9 @@ "integrity": "sha512-Brah4Uo5/U8v76c6euTwtjVFFaVishwnJrQBYpev1JRh4vjA1F4HY3UzQez41YUCszUCXKagG8v6eVRBHV1gkw==", "dev": true, "peer": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "json-schema-traverse": { "version": "1.0.0", @@ -17186,7 +17201,9 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "dev": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "json-schema-traverse": { "version": "1.0.0", @@ -17264,7 +17281,9 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "dev": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "json-schema-traverse": { "version": "1.0.0", @@ -18908,7 +18927,9 @@ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", "dev": true, - "requires": {} + "requires": { + "ajv": "^8.0.0" + } }, "json-schema-traverse": { "version": "1.0.0", @@ -21949,6 +21970,11 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "fuse.js": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", + "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==" + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", diff --git a/ui/package.json b/ui/package.json index e1feea04e..f5c5e044a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -23,6 +23,7 @@ "@start9labs/emver": "0.1.5", "ajv": "^6.12.6", "core-js": "^3.17.2", + "fuse.js": "^6.4.6", "json-pointer": "^0.6.1", "jsonpointerx": "^1.1.4", "marked": "3.0.2", diff --git a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html index 1e91da67e..e14e1eb54 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html +++ b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.html @@ -74,6 +74,13 @@ +
+

👏👏👏 Up to date! 👏👏👏

+
diff --git a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts index 8f97731ca..41943ad53 100644 --- a/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts +++ b/ui/src/app/pages/marketplace-routes/marketplace-list/marketplace-list.page.ts @@ -8,6 +8,7 @@ import { Subscription } from 'rxjs' import { ErrorToastService } from 'src/app/services/error-toast.service' import { MarketplaceService } from '../marketplace.service' import { PatchDbService } from 'src/app/services/patch-db/patch-db.service' +import Fuse from 'fuse.js/dist/fuse.min.js' @Component({ selector: 'marketplace-list', @@ -103,23 +104,60 @@ export class MarketplaceListPage { const { id, version } = pkg.manifest return this.localPkgs[id] && version !== this.localPkgs[id].manifest.version }) + } else if (this.query) { + const options = { + isCaseSensitive: false, + includeScore: true, + shouldSort: true, + includeMatches: false, + findAllMatches: false, + minMatchCharLength: 1, + location: 0, + threshold: 0.6, + distance: 100, + useExtendedSearch: false, + ignoreLocation: false, + ignoreFieldNorm: false, + keys: [ + 'manifest.id', + 'manifest.title', + 'manifest.description.short', + 'manifest.description.long', + ], + } + const fuse = new Fuse(this.marketplaceService.pkgs, options) + this.pkgs = fuse.search(this.query).map(p => p.item) + } else { - this.pkgs = this.marketplaceService.pkgs.filter(pkg => { - const { id, title, description } = pkg.manifest - if (this.query) { - const query = this.query.toUpperCase() - return id.toUpperCase().includes(query) || - title.toUpperCase().includes(query) || - description.short.toUpperCase().includes(query) || - description.long.toUpperCase().includes(query) - } else { - if (this.category === 'all' || !this.category) { - return true - } else { - return pkg.categories.includes(this.category) - } - } + const options = { + isCaseSensitive: false, + includeScore: true, + shouldSort: true, + includeMatches: false, + findAllMatches: false, + minMatchCharLength: 1, + location: 0, + threshold: 1, + distance: 100, + useExtendedSearch: false, + ignoreLocation: false, + ignoreFieldNorm: false, + keys: [ + 'manifest.id', + 'manifest.title', + 'manifest.description.short', + 'manifest.description.long', + ], + } + + + const pkgsToSort = this.marketplaceService.pkgs.filter(p => { + if (this.category === 'all') return true + return p.categories.includes(this.category) }) + + const fuse = new Fuse(pkgsToSort, options) + this.pkgs = fuse.search(this.category !== 'all' ? this.category : 'bit').map(p => p.item) } } }