Initial commit
commit
3f67beaaa6
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
config.json
|
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
|
||||
const Promise = require("bluebird");
|
||||
const budoExpress = require("budo-express");
|
||||
const path = require("path");
|
||||
|
||||
return Promise.try(() => {
|
||||
return require("../src/app");
|
||||
}).then((app) => {
|
||||
budoExpress({
|
||||
// port: 3000,
|
||||
// port: 3100,
|
||||
port: 3500,
|
||||
allowUnsafeHost: true,
|
||||
expressApp: app,
|
||||
basePath: path.join(__dirname, ".."),
|
||||
entryFiles: "src/frontend/index.jsx",
|
||||
staticPath: "public",
|
||||
bundlePath: "js/bundle.js",
|
||||
livereloadPattern: "**/*.{css,html,js}",
|
||||
browserify: {
|
||||
extensions: [".jsx"],
|
||||
plugin: [
|
||||
[ "icssify", {
|
||||
before: [
|
||||
// require('postcss-import')(),
|
||||
require('postcss-mixins')(),
|
||||
require("postcss-nested")(),
|
||||
require('postcss-simple-vars')(),
|
||||
require('postcss-color-function')(),
|
||||
require('autoprefixer')()
|
||||
]
|
||||
}] // FIXME: css-extract
|
||||
],
|
||||
transform: [
|
||||
["babelify", {
|
||||
presets: ["@babel/preset-env", "@babel/preset-react"],
|
||||
}],
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
const config = require("./config.json");
|
||||
|
||||
module.exports = {
|
||||
client: "pg",
|
||||
connection: {
|
||||
host: config.database.socketPath,
|
||||
database: config.database.database
|
||||
}
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
Note: text_pattern_ops index is needed for prefix LIKE to be guaranteed-fast
|
||||
|
||||
CREATE INDEX search_index ON items ((lower(data ->> 'name'::text)) text_pattern_ops);
|
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "ui",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"repository": "git@git.cryto.net:seekseek/ui.git",
|
||||
"author": "Sven Slootweg <admin@cryto.net>",
|
||||
"license": "WTFPL OR CC0-1.0",
|
||||
"scripts": {
|
||||
"dev": "NODE_ENV=development nodemon --ext js,jsx,mjs,json,ftl --ignore node_modules --ignore public/js --ignore src/frontend bin/server.js",
|
||||
"dev-css": "postcss --watch src/css/style.css -o public/css/style.css"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.9",
|
||||
"@babel/preset-env": "^7.12.7",
|
||||
"@babel/preset-react": "^7.12.7",
|
||||
"@joepie91/eslint-config": "^1.1.0",
|
||||
"autoprefixer": "^9.0.0",
|
||||
"babelify": "^10.0.0",
|
||||
"budo-express": "^1.0.6",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"icssify": "^1.2.1",
|
||||
"nodemon": "^2.0.6",
|
||||
"postcss": "^8.2.1",
|
||||
"postcss-cli": "^8.3.1",
|
||||
"postcss-color-function": "^4.1.0",
|
||||
"postcss-mixins": "^6",
|
||||
"postcss-nested": "^4",
|
||||
"postcss-simple-vars": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joepie91/express-react-views": "^1.0.1",
|
||||
"axios": "^0.21.1",
|
||||
"bluebird": "^3.7.2",
|
||||
"classnames": "^2.2.6",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"knex": "^0.95.2",
|
||||
"match-value": "^1.1.0",
|
||||
"pg": "^8.5.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"syncpipe": "^1.0.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('postcss-mixins')(),
|
||||
require("postcss-nested")(),
|
||||
require('postcss-simple-vars')(),
|
||||
require('postcss-color-function')(),
|
||||
require('autoprefixer')()
|
||||
]
|
||||
};
|
@ -0,0 +1,62 @@
|
||||
html, body {
|
||||
/* background-color: rgb(248, 249, 236); */
|
||||
background-color: #f9f9f9ff;
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 900px;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-top: 1em;
|
||||
margin-left: 0.5em;
|
||||
margin-right: 0.5em;
|
||||
padding-bottom: .7em;
|
||||
border-bottom: 2px solid black;
|
||||
}
|
||||
|
||||
.contents {
|
||||
margin-bottom: 2em;
|
||||
padding: .7em 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0.5em;
|
||||
right: 0.5em;
|
||||
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid black;
|
||||
height: 2em;
|
||||
padding: 0.2em;
|
||||
background-color: #f9f9f9ff;
|
||||
}
|
||||
|
||||
.footer .wrapper {
|
||||
margin-left: calc(1em - 0.5em);
|
||||
}
|
||||
|
||||
.logoContainer {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.logoContainer .logo {
|
||||
height: 5em;
|
||||
}
|
||||
|
||||
.logoContainer .siteTag {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
color: teal;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="624.12909"
|
||||
height="149.9104"
|
||||
viewBox="0 0 165.13416 39.663792"
|
||||
version="1.1"
|
||||
id="svg851"
|
||||
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:export-filename="/home/sven/magnifier.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96">
|
||||
<defs
|
||||
id="defs845" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="290.07278"
|
||||
inkscape:cy="-52.014372"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata848">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-137.20652,-103.9911)">
|
||||
<g
|
||||
aria-label="seekseek"
|
||||
id="text905"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;line-height:36.6346px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">
|
||||
<path
|
||||
d="m 197.21016,126.62008 q 0,2.1082 -1.4986,3.2512 -1.4732,1.1176 -4.4196,1.1176 -1.4478,0 -2.4892,-0.2032 -1.0414,-0.1778 -2.0828,-0.6096 v -3.1242 q 1.1176,0.508 2.413,0.8382 1.2954,0.3302 2.286,0.3302 1.1176,0 1.5748,-0.3302 0.4826,-0.3302 0.4826,-0.8636 0,-0.3556 -0.2032,-0.635 -0.1778,-0.2794 -0.8128,-0.635 -0.635,-0.3556 -1.9812,-0.9144 -1.2954,-0.5588 -2.1336,-1.0922 -0.8382,-0.5588 -1.2446,-1.3208 -0.4064,-0.7874 -0.4064,-1.9558 0,-1.9304 1.4986,-2.8956 1.4986,-0.9652 3.9878,-0.9652 1.2954,0 2.4638,0.254 1.1684,0.254 2.413,0.8382 l -1.143,2.7178 q -1.016,-0.4318 -1.9304,-0.7112 -0.9144,-0.3048 -1.8542,-0.3048 -1.6764,0 -1.6764,0.9144 0,0.3302 0.2032,0.6096 0.2286,0.254 0.8382,0.5588 0.635,0.3048 1.8542,0.8128 1.1938,0.4826 2.0574,1.016 0.8636,0.508 1.3208,1.2954 0.4826,0.762 0.4826,2.0066 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1512" />
|
||||
<path
|
||||
d="m 205.87155,116.61248 q 2.8702,0 4.5466,1.651 1.6764,1.6256 1.6764,4.6482 v 1.8288 h -8.9408 q 0.0508,1.6002 0.9398,2.5146 0.9144,0.9144 2.5146,0.9144 1.3462,0 2.4384,-0.254 1.0922,-0.2794 2.2606,-0.8382 v 2.921 q -1.016,0.508 -2.159,0.7366 -1.1176,0.254 -2.7178,0.254 -2.0828,0 -3.683,-0.762 -1.6002,-0.7874 -2.5146,-2.3622 -0.9144,-1.5748 -0.9144,-3.9624 0,-2.4384 0.8128,-4.0386 0.8382,-1.6256 2.3114,-2.4384 1.4732,-0.8128 3.429,-0.8128 z m 0.0254,2.6924 q -1.0922,0 -1.8288,0.7112 -0.7112,0.7112 -0.8382,2.2098 h 5.3086 q -0.0254,-1.27 -0.6604,-2.0828 -0.635,-0.8382 -1.9812,-0.8382 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1514" />
|
||||
<path
|
||||
d="m 220.88294,116.61248 q 2.8702,0 4.5466,1.651 1.6764,1.6256 1.6764,4.6482 v 1.8288 h -8.9408 q 0.0508,1.6002 0.9398,2.5146 0.9144,0.9144 2.5146,0.9144 1.3462,0 2.4384,-0.254 1.0922,-0.2794 2.2606,-0.8382 v 2.921 q -1.016,0.508 -2.159,0.7366 -1.1176,0.254 -2.7178,0.254 -2.0828,0 -3.683,-0.762 -1.6002,-0.7874 -2.5146,-2.3622 -0.9144,-1.5748 -0.9144,-3.9624 0,-2.4384 0.8128,-4.0386 0.8382,-1.6256 2.3114,-2.4384 1.4732,-0.8128 3.429,-0.8128 z m 0.0254,2.6924 q -1.0922,0 -1.8288,0.7112 -0.7112,0.7112 -0.8382,2.2098 h 5.3086 q -0.0254,-1.27 -0.6604,-2.0828 -0.635,-0.8382 -1.9812,-0.8382 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1516" />
|
||||
<path
|
||||
d="m 233.96393,111.43088 v 8.636 q 0,0.7874 -0.0762,1.5748 -0.0508,0.762 -0.127,1.5494 h 0.0508 q 0.381,-0.5334 0.7874,-1.0668 0.4064,-0.5588 0.8636,-1.0414 l 3.8862,-4.2164 h 4.2672 l -5.5118,6.0198 5.842,7.8486 h -4.3688 l -3.9878,-5.6134 -1.6256,1.2954 v 4.318 h -3.7846 v -19.304 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1518" />
|
||||
<path
|
||||
d="m 255.60471,126.62008 q 0,2.1082 -1.4986,3.2512 -1.4732,1.1176 -4.4196,1.1176 -1.4478,0 -2.4892,-0.2032 -1.0414,-0.1778 -2.0828,-0.6096 v -3.1242 q 1.1176,0.508 2.413,0.8382 1.2954,0.3302 2.286,0.3302 1.1176,0 1.5748,-0.3302 0.4826,-0.3302 0.4826,-0.8636 0,-0.3556 -0.2032,-0.635 -0.1778,-0.2794 -0.8128,-0.635 -0.635,-0.3556 -1.9812,-0.9144 -1.2954,-0.5588 -2.1336,-1.0922 -0.8382,-0.5588 -1.2446,-1.3208 -0.4064,-0.7874 -0.4064,-1.9558 0,-1.9304 1.4986,-2.8956 1.4986,-0.9652 3.9878,-0.9652 1.2954,0 2.4638,0.254 1.1684,0.254 2.413,0.8382 l -1.143,2.7178 q -1.016,-0.4318 -1.9304,-0.7112 -0.9144,-0.3048 -1.8542,-0.3048 -1.6764,0 -1.6764,0.9144 0,0.3302 0.2032,0.6096 0.2286,0.254 0.8382,0.5588 0.635,0.3048 1.8542,0.8128 1.1938,0.4826 2.0574,1.016 0.8636,0.508 1.3208,1.2954 0.4826,0.762 0.4826,2.0066 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1520" />
|
||||
<path
|
||||
d="m 264.2661,116.61248 q 2.8702,0 4.5466,1.651 1.6764,1.6256 1.6764,4.6482 v 1.8288 h -8.9408 q 0.0508,1.6002 0.9398,2.5146 0.9144,0.9144 2.5146,0.9144 1.3462,0 2.4384,-0.254 1.0922,-0.2794 2.2606,-0.8382 v 2.921 q -1.016,0.508 -2.159,0.7366 -1.1176,0.254 -2.7178,0.254 -2.0828,0 -3.683,-0.762 -1.6002,-0.7874 -2.5146,-2.3622 -0.9144,-1.5748 -0.9144,-3.9624 0,-2.4384 0.8128,-4.0386 0.8382,-1.6256 2.3114,-2.4384 1.4732,-0.8128 3.429,-0.8128 z m 0.0254,2.6924 q -1.0922,0 -1.8288,0.7112 -0.7112,0.7112 -0.8382,2.2098 h 5.3086 q -0.0254,-1.27 -0.6604,-2.0828 -0.635,-0.8382 -1.9812,-0.8382 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1522" />
|
||||
<path
|
||||
d="m 279.27749,116.61248 q 2.8702,0 4.5466,1.651 1.6764,1.6256 1.6764,4.6482 v 1.8288 h -8.9408 q 0.0508,1.6002 0.9398,2.5146 0.9144,0.9144 2.5146,0.9144 1.3462,0 2.4384,-0.254 1.0922,-0.2794 2.2606,-0.8382 v 2.921 q -1.016,0.508 -2.159,0.7366 -1.1176,0.254 -2.7178,0.254 -2.0828,0 -3.683,-0.762 -1.6002,-0.7874 -2.5146,-2.3622 -0.9144,-1.5748 -0.9144,-3.9624 0,-2.4384 0.8128,-4.0386 0.8382,-1.6256 2.3114,-2.4384 1.4732,-0.8128 3.429,-0.8128 z m 0.0254,2.6924 q -1.0922,0 -1.8288,0.7112 -0.7112,0.7112 -0.8382,2.2098 h 5.3086 q -0.0254,-1.27 -0.6604,-2.0828 -0.635,-0.8382 -1.9812,-0.8382 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1524" />
|
||||
<path
|
||||
d="m 292.35848,111.43088 v 8.636 q 0,0.7874 -0.0762,1.5748 -0.0508,0.762 -0.127,1.5494 h 0.0508 q 0.381,-0.5334 0.7874,-1.0668 0.4064,-0.5588 0.8636,-1.0414 l 3.8862,-4.2164 h 4.2672 l -5.5118,6.0198 5.842,7.8486 h -4.3688 l -3.9878,-5.6134 -1.6256,1.2954 v 4.318 h -3.7846 v -19.304 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';stroke-width:0.264583px"
|
||||
id="path1526" />
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:0.99;fill:#333333;stroke-width:0.175183;paint-order:markers stroke fill"
|
||||
id="rect1418"
|
||||
width="5.357511"
|
||||
height="22.925625"
|
||||
x="195.92026"
|
||||
y="-21.044689"
|
||||
transform="rotate(45)" />
|
||||
<path
|
||||
id="path1414"
|
||||
style="opacity:0.99;fill:#000000;stroke-width:0.175183;paint-order:markers stroke fill"
|
||||
d="m 162.88237,103.99118 a 13.521487,13.521487 0 0 0 -9.51545,3.96032 13.521487,13.521487 0 0 0 0,19.12234 13.521487,13.521487 0 0 0 19.12235,0 13.521487,13.521487 0 0 0 0,-19.12234 13.521487,13.521487 0 0 0 -9.6069,-3.96032 z m 0.0151,4.51556 a 9.0058318,9.0058318 0 0 1 6.39856,2.6377 9.0058318,9.0058318 0 0 1 0,12.73615 9.0058318,9.0058318 0 0 1 -12.73616,0 9.0058318,9.0058318 0 0 1 0,-12.73615 9.0058318,9.0058318 0 0 1 6.3376,-2.6377 z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.5 KiB |
@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
|
||||
const Promise = require("bluebird");
|
||||
const express = require("express");
|
||||
const path = require("path");
|
||||
|
||||
const knex = require("knex")(require("../knexfile"));
|
||||
|
||||
let app = express();
|
||||
|
||||
app.set("views", path.join(__dirname, "views"));
|
||||
app.set("view engine", "jsx");
|
||||
app.engine("jsx", require("@joepie91/express-react-views").createEngine());
|
||||
|
||||
app.use(express.static(path.join(__dirname, "../public")));
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.redirect("/datasheets");
|
||||
});
|
||||
|
||||
app.get("/datasheets", (req, res) => {
|
||||
res.render("index");
|
||||
});
|
||||
|
||||
app.post("/search", (req, res) => {
|
||||
return Promise.try(() => {
|
||||
return knex.raw(`
|
||||
SELECT
|
||||
data->>'manufacturer' AS manufacturer,
|
||||
data->>'name' AS name,
|
||||
data->>'url' AS url,
|
||||
data->>'description' AS description,
|
||||
data->>'source' AS source
|
||||
FROM items WHERE
|
||||
id LIKE 'datasheet:%'
|
||||
AND lower(data->>'name') LIKE :query
|
||||
ORDER BY name
|
||||
LIMIT 20
|
||||
`, {
|
||||
query: req.query.query.toLowerCase() + "%"
|
||||
});
|
||||
}).then((result) => {
|
||||
res.json({ results: result.rows });
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = app;
|
@ -0,0 +1,65 @@
|
||||
$pagePadding: 0.5em;
|
||||
$background: #f9f9f9ff;
|
||||
|
||||
html, body {
|
||||
/* background-color: rgb(248, 249, 236); */
|
||||
background-color: $background;
|
||||
font-family: sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
max-width: 900px;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-top: 1em;
|
||||
margin-left: $pagePadding;
|
||||
margin-right: $pagePadding;
|
||||
padding-bottom: .7em;
|
||||
border-bottom: 2px solid black;
|
||||
}
|
||||
|
||||
.contents {
|
||||
margin-bottom: 2em;
|
||||
padding: .7em 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: $pagePadding;
|
||||
right: $pagePadding;
|
||||
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid black;
|
||||
height: 2em;
|
||||
padding: 0.2em;
|
||||
background-color: $background;
|
||||
|
||||
.wrapper {
|
||||
margin-left: calc(1em - $pagePadding);
|
||||
}
|
||||
}
|
||||
|
||||
.logoContainer {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
.logo {
|
||||
height: 5em;
|
||||
}
|
||||
|
||||
.siteTag {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
color: teal;
|
||||
font-size: 1.3em;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
.query {
|
||||
font-size: 1.3em;
|
||||
background-color: white;
|
||||
color: black;
|
||||
border: 1px solid teal;
|
||||
border-radius: 5px;
|
||||
padding: .4em .8em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.noResults {
|
||||
padding: .6em 1em;
|
||||
}
|
||||
|
||||
.results {
|
||||
border: 1px solid teal;
|
||||
border-radius: 5px;
|
||||
/* margin-top: 1em; */
|
||||
|
||||
.result {
|
||||
border-top: 1px solid teal;
|
||||
padding: .6em 1em;
|
||||
font-size: .8em;
|
||||
|
||||
&.first {
|
||||
border-top: 0;
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 1.3em;
|
||||
|
||||
.manufacturer {
|
||||
color: #4f4e4e;
|
||||
margin-right: .3em;
|
||||
}
|
||||
|
||||
.model {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
color: #4f4e4e;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
.download {
|
||||
float: right;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
padding: .3em .8em;
|
||||
|
||||
margin-top: -.3em;
|
||||
margin-right: -.7em;
|
||||
|
||||
border: 1px solid #006262;
|
||||
background-color: #039f9f;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sources {
|
||||
color: gray;
|
||||
font-size: 0.8em;
|
||||
margin-top: 1em;
|
||||
margin-bottom: .3em;
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
"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>
|
||||
);
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
|
||||
const DatasheetSearch = require("./components/datasheet-search");
|
||||
|
||||
ReactDOM.render(<DatasheetSearch />, document.querySelector("#datasheetSearch"));
|
@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
const React = require("react");
|
||||
|
||||
module.exports = function Index() {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>seekseek</title>
|
||||
<link rel="stylesheet" href="/css/style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div className="header">
|
||||
<div className="wrapper">
|
||||
<div className="logoContainer">
|
||||
<img src="/images/logo.svg" alt="seekseek logo" className="logo"/>
|
||||
<div className="siteTag">datasheets</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="contents">
|
||||
<div className="wrapper">
|
||||
<div id="datasheetSearch">
|
||||
Loading, please wait...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
<div className="wrapper">
|
||||
<a href="https://matrix.to/#/#seekseek:pixie.town?via=pixie.town&via=matrix.org&via=librepush.net" className="chat">
|
||||
Come chat with us!
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue