You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
2.8 KiB
JavaScript
126 lines
2.8 KiB
JavaScript
"use strict";
|
|
|
|
const React = require("react");
|
|
const classnames = require("classnames");
|
|
const axios = require("axios");
|
|
const syncpipe = require("syncpipe");
|
|
const matchValue = require("match-value");
|
|
|
|
const style = require("./datasheet-search.css");
|
|
|
|
function getSources(results) {
|
|
return syncpipe(results, [
|
|
(_) => _.map((result) => result.source),
|
|
// (_) => _.filter((source) => source != null),
|
|
(_) => _.map((source) => source != null ? source : "unknown"),
|
|
(_) => new Set(_),
|
|
(_) => Array.from(_),
|
|
(_) => _.map((source) => {
|
|
return matchValue(source, {
|
|
tme: "TME",
|
|
lcsc: "LCSC",
|
|
st: "STMicroelectronics",
|
|
unknown: "Unknown"
|
|
});
|
|
})
|
|
]);
|
|
}
|
|
|
|
function SearchResult({ isFirst, name, description, url, manufacturer }) {
|
|
// FIXME: Handle 'no datasheet available'
|
|
return (
|
|
<div className={classnames(style.result, { [style.first]: isFirst })}>
|
|
<a href={url} className={style.download} target="_blank">
|
|
Download datasheet
|
|
</a>
|
|
<div className={style.name}>
|
|
<span className={style.manufacturer}>
|
|
{manufacturer}
|
|
</span>
|
|
<span className={style.model}>
|
|
{name}
|
|
</span>
|
|
</div>
|
|
<div className={style.description}>
|
|
{description}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function NoResults() {
|
|
return (
|
|
<div className={style.noResults}>
|
|
No results.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
module.exports = function DatasheetSearch({}) {
|
|
let [ query, setQuery ] = React.useState(""); // FIXME
|
|
let [ results, setResults ] = React.useState([]);
|
|
let [ sources, setSources ] = React.useState([]);
|
|
let cancellationToken = React.useRef();
|
|
|
|
function updateQuery(event) {
|
|
setQuery(event.target.value.trim());
|
|
}
|
|
|
|
React.useEffect(() => {
|
|
let cancelled = false;
|
|
cancellationToken.current = axios.CancelToken.source();
|
|
|
|
if (query.length > 0) {
|
|
axios.post("/search", {}, {
|
|
params: { query: query }
|
|
})
|
|
.then((response) => {
|
|
if (!cancelled) {
|
|
setResults(response.data.results);
|
|
|
|
setSources(getSources(response.data.results));
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
if (!axios.isCancel()) {
|
|
throw error;
|
|
}
|
|
});
|
|
} else {
|
|
setResults([]);
|
|
}
|
|
|
|
return function () {
|
|
cancelled = true;
|
|
cancellationToken.current.cancel("Query input changed");
|
|
};
|
|
}, [ query ]);
|
|
|
|
return (
|
|
<div className="search">
|
|
<input type="text" className={style.query} placeholder="Start typing..." onChange={updateQuery} />
|
|
<div className={style.sources}>
|
|
{(results.length > 0)
|
|
? <>
|
|
<strong>Sources:</strong>
|
|
|
|
{sources.join(", ")}
|
|
</>
|
|
: null
|
|
}
|
|
</div>
|
|
<div className={style.results}>
|
|
{(results.length > 0)
|
|
? results.map((result, i) => {
|
|
return <SearchResult
|
|
isFirst={(i === 0)}
|
|
{...result}
|
|
/>;
|
|
})
|
|
: <NoResults />
|
|
}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|