add server (only with basic search for now)
This commit is contained in:
parent
99ad35f618
commit
8649abb725
|
@ -0,0 +1,78 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>electronic parts database explorer</title>
|
||||||
|
<script type='application/javascript'>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// the last search query
|
||||||
|
var last_search = null;
|
||||||
|
|
||||||
|
function search()
|
||||||
|
{
|
||||||
|
const terms = document.getElementById('terms');
|
||||||
|
if (terms && terms.value && terms.value.length >= 3) {
|
||||||
|
console.log(terms.value);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_search = '/search/' + terms.value;
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', last_search, true);
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (this.responseURL.endsWith(last_search)) {
|
||||||
|
populate(JSON.parse(this.response));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function() {
|
||||||
|
console.log("search call failed");
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function populate(parts)
|
||||||
|
{
|
||||||
|
const results = document.getElementById('results');
|
||||||
|
results.innerHTML = null;
|
||||||
|
for (const part of parts) {
|
||||||
|
console.log(part);
|
||||||
|
const tr = document.createElement('tr');
|
||||||
|
for (const key of ["name", "description"]) {
|
||||||
|
const td = document.createElement('td');
|
||||||
|
td.innerHTML = part[key];
|
||||||
|
tr.appendChild(td);
|
||||||
|
}
|
||||||
|
results.appendChild(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border: 1px #E1E3F2 solid;
|
||||||
|
width: 500px;
|
||||||
|
resize: both;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<form>
|
||||||
|
<input type="text" id="terms" name="terms" placeholder="search terms" oninput="search()"><br>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>name</th>
|
||||||
|
<th>description</th>
|
||||||
|
<th>stock</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="results"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# encoding: utf-8
|
||||||
|
# ruby: 3.0.2
|
||||||
|
=begin
|
||||||
|
server to query part database
|
||||||
|
|
||||||
|
to install sinatra
|
||||||
|
sudo pacman -S ruby-sinatra ruby-webrick
|
||||||
|
pikaur -S ruby-mysql2
|
||||||
|
=end
|
||||||
|
require 'set'
|
||||||
|
require 'mysql2'
|
||||||
|
require 'json'
|
||||||
|
require 'sinatra'
|
||||||
|
|
||||||
|
DEBUG = true
|
||||||
|
PARTS_LIMIT = 100
|
||||||
|
CREDENTIALS = "credentials.json"
|
||||||
|
raise "database information #{CREDENTIALS} do not exist" unless File.file? CREDENTIALS
|
||||||
|
|
||||||
|
# open server
|
||||||
|
configure do
|
||||||
|
if DEBUG then
|
||||||
|
set :show_exceptions, true
|
||||||
|
set :logging, true
|
||||||
|
else
|
||||||
|
set :show_exceptions, false
|
||||||
|
set :environment, :production
|
||||||
|
set :logging, false
|
||||||
|
end
|
||||||
|
set :protection, :except => :json_csrf
|
||||||
|
|
||||||
|
set :bind, 'localhost'
|
||||||
|
set :port, 4244
|
||||||
|
set :public_folder, "public"
|
||||||
|
set :static, true
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
|
response.headers["Access-Control-Allow-Headers"] = "Content-Type"
|
||||||
|
if request.request_method == 'OPTIONS'
|
||||||
|
response.headers["Access-Control-Allow-Methods"] = "GET,POST"
|
||||||
|
halt 200
|
||||||
|
end
|
||||||
|
|
||||||
|
# all replies are only JSON
|
||||||
|
content_type 'application/json'
|
||||||
|
# open database
|
||||||
|
credentials = {}
|
||||||
|
JSON.parse(IO.read(CREDENTIALS)).each {|key,value| credentials[key.to_sym] = value}
|
||||||
|
Mysql2::Client.default_query_options.merge!(:as => :hash)
|
||||||
|
@db = Mysql2::Client.new(credentials)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
|
response.headers["Access-Control-Allow-Headers"] = "Content-Type"
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/' do
|
||||||
|
redirect to('/index.html')
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_part_by_id(id)
|
||||||
|
statement = @db.prepare("SELECT part.name, part.description, part.datasheet, manufacturer.name AS manufacturer, package.name AS package, part.pincount AS pincount, part.page AS page, part.family AS family FROM part LEFT JOIN package ON package.id = part.package LEFT JOIN manufacturer ON manufacturer.id = part.manufacturer WHERE part.id = ?")
|
||||||
|
part = statement.execute(id, :as => :hash).to_a[0]
|
||||||
|
return nil unless part
|
||||||
|
# merge with family info
|
||||||
|
while part and part["family"] do
|
||||||
|
family = statement.execute(part["family"]).to_a[0]
|
||||||
|
part["family"] = nil # reset info
|
||||||
|
break unless family
|
||||||
|
family.each do |k,v|
|
||||||
|
part[k] ||= v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# clean up
|
||||||
|
delete = ["family"]
|
||||||
|
delete.each do |k|
|
||||||
|
part.delete k
|
||||||
|
end
|
||||||
|
return part
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_part_by_name(name)
|
||||||
|
statement = @db.prepare("SELECT id FROM part WHERE part.name = ?")
|
||||||
|
id = statement.execute(name).to_a[0]
|
||||||
|
if id then
|
||||||
|
return get_part_by_id(id["id"])
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/part/:name' do
|
||||||
|
part = get_part_by_name(params['name'])
|
||||||
|
halt 404 unless part
|
||||||
|
part.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
get '/search/:terms' do
|
||||||
|
terms = params['terms'].split(" ")
|
||||||
|
terms.keep_if {|term| term.length >= 3}
|
||||||
|
ids = Set.new
|
||||||
|
part_statement = @db.prepare("SELECT id FROM part WHERE name LIKE ?")
|
||||||
|
terms.each do |term|
|
||||||
|
part_statement.execute("%#{term}%").each do |row|
|
||||||
|
ids << row["id"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
puts ids
|
||||||
|
parts = ids.collect {|id| get_part_by_id(id)}
|
||||||
|
parts.compact!
|
||||||
|
parts = parts[0, PARTS_LIMIT]
|
||||||
|
parts.sort! {|x,y| x["name"] <=> y["name"]}
|
||||||
|
parts.to_json
|
||||||
|
end
|
Loading…
Reference in New Issue