diff --git a/pkg/grid/package-lock.json b/pkg/grid/package-lock.json
index dae714ee3..09315fe17 100644
--- a/pkg/grid/package-lock.json
+++ b/pkg/grid/package-lock.json
@@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
+ "name": "landscape",
"version": "0.0.0",
"dependencies": {
"@radix-ui/react-dialog": "^0.0.20",
diff --git a/pkg/grid/src/nav/Nav.tsx b/pkg/grid/src/nav/Nav.tsx
index 94bf52f21..8afffc5de 100644
--- a/pkg/grid/src/nav/Nav.tsx
+++ b/pkg/grid/src/nav/Nav.tsx
@@ -46,9 +46,14 @@ export const useNavStore = create((set) => ({
set({ searchInput: input || '', selection })
}));
+function normalizePathEnding(path: string) {
+ const end = path.length - 1;
+ return path[end] === '/' ? path.substring(0, end - 1) : path;
+}
+
export function createNextPath(current: string, nextPart?: string): string {
let end = nextPart;
- const parts = current.split('/').reverse();
+ const parts = normalizePathEnding(current).split('/').reverse();
if (parts[1] === 'search') {
end = 'apps';
}
@@ -61,7 +66,7 @@ export function createNextPath(current: string, nextPart?: string): string {
}
export function createPreviousPath(current: string): string {
- const parts = current.split('/');
+ const parts = normalizePathEnding(current).split('/');
parts.pop();
if (parts[parts.length - 1] === 'leap') {
diff --git a/pkg/grid/src/nav/search/Apps.tsx b/pkg/grid/src/nav/search/Apps.tsx
index 198ff3039..397345d29 100644
--- a/pkg/grid/src/nav/search/Apps.tsx
+++ b/pkg/grid/src/nav/search/Apps.tsx
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect } from 'react';
import { useQuery, useQueryClient } from 'react-query';
import { Link, RouteComponentProps } from 'react-router-dom';
+import fuzzy from 'fuzzy';
import slugify from 'slugify';
import { ShipName } from '../../components/ShipName';
import { fetchProviderTreaties, treatyKey } from '../../state/docket';
@@ -11,12 +12,23 @@ type AppsProps = RouteComponentProps<{ ship: string }>;
export const Apps = ({ match }: AppsProps) => {
const queryClient = useQueryClient();
- const { select } = useNavStore();
+ const { searchInput, select } = useNavStore((state) => ({
+ searchInput: state.searchInput,
+ select: state.select
+ }));
const provider = match?.params.ship;
const { data } = useQuery(treatyKey([provider]), () => fetchProviderTreaties(provider), {
enabled: !!provider
});
- const count = data?.length;
+ const results = data
+ ? fuzzy
+ .filter(
+ searchInput,
+ data.map((t) => t.title)
+ )
+ .map((result) => data[result.index])
+ : undefined;
+ const count = results?.length;
useEffect(() => {
select(
@@ -43,9 +55,9 @@ export const Apps = ({ match }: AppsProps) => {
{count} result{count === 1 ? '' : 's'}
- {data && (
+ {results && (
- {data.map((app) => (
+ {results.map((app) => (
-
{
}, []);
const handleSearch = useCallback(
- debounce((input: string) => {
- push(match?.path.replace(':ship', input.trim()));
- }, 300),
+ debounce(
+ (input: string) => {
+ const normalizedValue = input.trim().replace(/(~?[\w^_-]{3,13})\//, '$1/apps');
+ push(match?.path.replace(':ship', normalizedValue));
+ },
+ 300,
+ { leading: true }
+ ),
[path]
);