Search for snippet by title, description and language

This commit is contained in:
unknown
2021-10-04 15:01:18 +02:00
parent 966db73238
commit 3b22cd9442
11 changed files with 93 additions and 17 deletions

View File

@@ -1,7 +1,9 @@
import { useRef, useEffect, KeyboardEvent } from 'react';
import { useRef, useEffect, KeyboardEvent, useContext } from 'react';
import { SnippetsContext } from '../store';
import { searchParser } from '../utils';
export const SearchBar = (): JSX.Element => {
const { searchSnippets } = useContext(SnippetsContext);
const inputRef = useRef<HTMLInputElement>(document.createElement('input'));
useEffect(() => {
@@ -9,7 +11,11 @@ export const SearchBar = (): JSX.Element => {
}, [inputRef]);
const inputHandler = (e: KeyboardEvent<HTMLInputElement>) => {
const rawQuery = searchParser(inputRef.current.value);
const query = searchParser(inputRef.current.value);
if (e.key === 'Enter') {
searchSnippets(query);
}
};
return (

View File

@@ -5,7 +5,7 @@ import { SnippetGrid } from '../components/Snippets/SnippetGrid';
import { SearchBar } from '../components/SearchBar';
export const Home = (): JSX.Element => {
const { snippets, getSnippets } = useContext(SnippetsContext);
const { snippets, getSnippets, searchResults } = useContext(SnippetsContext);
useEffect(() => {
getSnippets();
@@ -19,9 +19,9 @@ export const Home = (): JSX.Element => {
<Fragment>
<PageHeader title='Search' />
<SearchBar />
{/* <div className='col-12 mb-4'>
<SnippetGrid snippets={snippets.filter(s => s.isPinned)} />
</div> */}
<div className='col-12 mb-4'>
<SnippetGrid snippets={searchResults} />
</div>
{snippets.some(s => s.isPinned) && (
<Fragment>

View File

@@ -6,11 +6,13 @@ import {
Snippet,
Response,
TagCount,
NewSnippet
NewSnippet,
SearchQuery
} from '../typescript/interfaces';
export const SnippetsContext = createContext<Context>({
snippets: [],
searchResults: [],
currentSnippet: null,
tagCount: [],
getSnippets: () => {},
@@ -20,7 +22,8 @@ export const SnippetsContext = createContext<Context>({
updateSnippet: (snippet: NewSnippet, id: number, isLocal?: boolean) => {},
deleteSnippet: (id: number) => {},
toggleSnippetPin: (id: number) => {},
countTags: () => {}
countTags: () => {},
searchSnippets: (query: SearchQuery) => {}
});
interface Props {
@@ -29,6 +32,7 @@ interface Props {
export const SnippetsContextProvider = (props: Props): JSX.Element => {
const [snippets, setSnippets] = useState<Snippet[]>([]);
const [searchResults, setSearchResults] = useState<Snippet[]>([]);
const [currentSnippet, setCurrentSnippet] = useState<Snippet | null>(null);
const [tagCount, setTagCount] = useState<TagCount[]>([]);
@@ -139,8 +143,19 @@ export const SnippetsContextProvider = (props: Props): JSX.Element => {
.catch(err => redirectOnError());
};
const searchSnippets = (query: SearchQuery): void => {
axios
.post<Response<Snippet[]>>('/api/snippets/search', query)
.then(res => {
setSearchResults(res.data.data);
console.log(res.data.data);
})
.catch(err => console.log(err));
};
const context = {
snippets,
searchResults,
currentSnippet,
tagCount,
getSnippets,
@@ -150,7 +165,8 @@ export const SnippetsContextProvider = (props: Props): JSX.Element => {
updateSnippet,
deleteSnippet,
toggleSnippetPin,
countTags
countTags,
searchSnippets
};
return (

View File

@@ -1,7 +1,8 @@
import { TagCount, NewSnippet, Snippet } from '.';
import { TagCount, NewSnippet, Snippet, SearchQuery } from '.';
export interface Context {
snippets: Snippet[];
searchResults: Snippet[];
currentSnippet: Snippet | null;
tagCount: TagCount[];
getSnippets: () => void;
@@ -12,4 +13,5 @@ export interface Context {
deleteSnippet: (id: number) => void;
toggleSnippetPin: (id: number) => void;
countTags: () => void;
searchSnippets: (query: SearchQuery) => void;
}

View File

@@ -0,0 +1,5 @@
export interface SearchQuery {
query: string;
tags: string[];
languages: string[];
}

View File

@@ -4,3 +4,4 @@ export * from './Route';
export * from './Response';
export * from './Context';
export * from './Statistics';
export * from './SearchQuery';

View File

@@ -1,14 +1,16 @@
export const searchParser = (rawQuery: string): void => {
// const rawQuery = 'my search tags:ui,react lang:typescript';
import { SearchQuery } from '../typescript/interfaces';
export const searchParser = (rawQuery: string): SearchQuery => {
// Extract filters from query
const tags = extractFilters(rawQuery, 'tags');
const languages = extractFilters(rawQuery, 'lang');
const query = rawQuery.replaceAll(/(tags|lang):[a-zA-Z]+(,[a-zA-Z]+)*/g, '');
console.log(tags);
console.log(languages);
console.log(query);
return {
query: query.trim(),
tags,
languages
};
};
const extractFilters = (query: string, filter: string): string[] => {