datajunction-ui
Version:
DataJunction Metrics Platform UI
95 lines (87 loc) • 2.58 kB
JSX
import { useState, useEffect, useContext } from 'react';
import DJClientContext from '../providers/djclient';
import Fuse from 'fuse.js';
import './search.css';
export default function Search() {
const [fuse, setFuse] = useState();
const [searchValue, setSearchValue] = useState('');
const [searchResults, setSearchResults] = useState([]);
const djClient = useContext(DJClientContext).DataJunctionAPI;
const truncate = str => {
if (str === null) {
return '';
}
return str.length > 100 ? str.substring(0, 90) + '...' : str;
};
useEffect(() => {
const fetchNodes = async () => {
try {
const [data, tags] = await Promise.all([
djClient.nodeDetails(),
djClient.listTags(),
]);
const allEntities = data.concat(
(tags || []).map(tag => {
tag.type = 'tag';
return tag;
}),
);
const fuse = new Fuse(allEntities || [], {
keys: [
'name', // will be assigned a `weight` of 1
{ name: 'description', weight: 2 },
{ name: 'display_name', weight: 3 },
{ name: 'type', weight: 4 },
{ name: 'tag_type', weight: 5 },
],
});
setFuse(fuse);
} catch (error) {
console.error('Error fetching nodes or tags:', error);
}
};
fetchNodes();
}, []);
const handleChange = e => {
setSearchValue(e.target.value);
if (fuse) {
setSearchResults(fuse.search(e.target.value).map(result => result.item));
}
};
return (
<div>
<form
className="search-box"
onSubmit={e => {
e.preventDefault();
}}
>
<input
type="text"
placeholder="Search"
name="search"
value={searchValue}
onChange={handleChange}
/>
</form>
<div className="search-results">
{searchResults.map(item => {
const itemUrl =
item.type !== 'tag' ? `/nodes/${item.name}` : `/tags/${item.name}`;
return (
<a href={itemUrl}>
<div key={item.name} className="search-result-item">
<span className={`node_type__${item.type} badge node_type`}>
{item.type}
</span>
{item.display_name} (<b>{item.name}</b>){' '}
{item.description ? '- ' : ' '}
{truncate(item.description || '')}
</div>
</a>
);
})}
</div>
</div>
);
}