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.

127 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",
farnell: "Farnell",
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 a part number..." onChange={updateQuery} />
<div className={style.sources}>
{(results.length > 0)
? <>
<strong>Sources:</strong>
&nbsp;
{sources.join(", ")}
</>
: null
}
</div>
<div className={style.results}>
{(results.length > 0)
? results.map((result, i) => {
return <SearchResult
isFirst={(i === 0)}
{...result}
/>;
})
: <NoResults />
}
</div>
</div>
);
};