/* frontend for the part database * Copyright (C) 2023 King Kévin * SPDX-License-Identifier: GPL-3.0-or-later */ "use strict"; // the last search query var last_search = null; // the collection of parts var parts = null; // part field to populate const fields = ["name", "description", "details", "package", "pincount", "manufacturer", "mpn", "family", "datasheet", "page", "location", "stock"]; // URLs to set const urls = ["page","datasheet"]; function search() { const terms = document.getElementById('terms'); if (terms && terms.value && terms.value.length >= 3) { } 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)) { parts = JSON.parse(this.response) results(); } }; xhr.onerror = function() { console.log("search call failed"); }; xhr.send(); } function results() { const results = document.getElementById('results'); let part_id = -1; if (results.selectedIndex >= 0) { part_id = parseInt(results.options[results.selectedIndex].value); } results.innerHTML = null; for (const part of parts) { const option = document.createElement('option'); option.setAttribute('value', part.id); option.innerHTML = part.name; if (part.description) { option.innerHTML += " (" + part.description + ")"; if (part_id == part.id) { option.selected = "selected"; } } results.appendChild(option); } select_part(); // in case we reselected } function clear() { // clear part fields for (const field of fields) { const input = document.getElementById('part_' + field); if (input.tagName == "INPUT") { input.value = ""; } else if (input.tagName == "TEXTAREA") { input.innerHTML = null; } } // clear URLs for (const field of urls) { const a = document.getElementById('url_' + field); a.href = null; } // clear distributors const distributors = document.getElementById('distributors'); distributors.innerHTML = null; // clear properties const properties = document.getElementById('properties'); properties.innerHTML = null; // clear attachments const attachments = document.getElementById('attachments'); attachments.innerHTML = null; } function select_part() { const results = document.getElementById('results'); if (results.selectedIndex >= 0) { let part_selected = parseInt(results.options[results.selectedIndex].value); for (const part of parts) { if (part.id == part_selected) { //console.log(part); // populate part fields for (const field of fields) { const input = document.getElementById('part_' + field); if (input.tagName == "INPUT") { if (undefined === part[field]) { input.value = ""; } else { input.value = part[field]; } } else if (input.tagName == "TEXTAREA") { if (undefined === part[field]) { input.innerHTML = null; } else { input.innerHTML = part[field]; } } } // set URLs for (const field of urls) { const span = document.getElementById('url_' + field); const text = span.innerText; span.innerHTML = null; if (undefined === part[field] || null == part[field]) { span.innerHTML = text; } else { const a = document.createElement('a'); a.href = part[field]; a.innerText = text; span.appendChild(a); } } // set distributors const distributors = document.getElementById('distributors'); distributors.innerHTML = null; for (const distributor of part["distributors"]) { const tr = document.createElement('tr'); const td_name = document.createElement('td'); td_name.innerText = distributor.name; tr.appendChild(td_name); const td_sku = document.createElement('td'); const input = document.createElement('input'); input.type = "text"; input.style.width = "95%"; if (distributor.sku) { input.value = distributor.sku; } td_sku.appendChild(input); tr.appendChild(td_sku); const td_url = document.createElement('td'); if (distributor.url) { td_url.innerHTML = "link"; } tr.appendChild(td_url); distributors.appendChild(tr); } // add properties const properties = document.getElementById('properties'); properties.innerHTML = null; for (const prop in part["properties"]) { const tr = document.createElement('tr'); let td = document.createElement('td'); let input = document.createElement('input'); input.type = "text"; input.style.width = "95%"; input.value = prop; td.appendChild(input); tr.appendChild(td); td = document.createElement('td'); input = document.createElement('input'); input.type = "text"; input.style.width = "95%"; input.value = part["properties"][prop].join(","); td.appendChild(input); tr.appendChild(td); properties.appendChild(tr); } // add empty property field let tr = document.createElement('tr'); let td = document.createElement('td'); let input = document.createElement('input'); input.type = "text"; input.style.width = "95%"; td.appendChild(input); tr.appendChild(td); td = document.createElement('td'); input = document.createElement('input'); input.type = "text"; input.style.width = "95%"; td.appendChild(input); tr.appendChild(td); properties.appendChild(tr); // add attachments const attachments = document.getElementById('attachments'); attachments.innerHTML = null; for (const attachment of part["attachments"]) { const a = document.createElement('a'); a.href = attachment; const img = document.createElement('img'); img.alt = attachment.split("/").slice(-1); img.src = attachment; a.appendChild(img); attachments.appendChild(a); } } } } } function delete_part() { if (null == parts) { return; } const results = document.getElementById('results'); if (results.selectedIndex < 0) { return; } const part_selected = parseInt(results.options[results.selectedIndex].value); const xhr = new XMLHttpRequest(); xhr.open('GET', '/delete/' + part_selected, true); xhr.onload = function() { clear(); search(); // refresh search }; xhr.onerror = function() { console.log("delete part failed"); }; xhr.send(); } function update_part() { // the part to update let part = {}; // its id const results = document.getElementById('results'); if (results.selectedIndex >= 0) { part.id = parseInt(results.options[results.selectedIndex].value); } // the fields for (const field of fields) { const input = document.getElementById('part_' + field); if (input.tagName == "INPUT") { part[field] = input.value; } else if (input.tagName == "TEXTAREA") { part[field] = input.innerHTML; } } if (part["name"].length == 0) { return; } // get distributors part.distributors = []; const distributors = document.getElementById('distributors'); for (const distributor of distributors.rows) { part.distributors.push({"distributor": distributor.cells[0].innerText, "sku": distributor.cells[1].firstChild.value}); } // get properties part.properties = {}; const properties = document.getElementById('properties'); for (const prop of properties.rows) { const name = prop.cells[0].firstChild.value; const value = prop.cells[1].firstChild.value; if (name && name.length > 0 && value && value.length > 0) { part.properties[name] = value.split(","); } } console.log(part); var post = new XMLHttpRequest(); post.open("POST", "part"); post.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); post.onload = function() { clear(); search(); // refresh search }; post.onerror = function() { console.log("update part failed"); }; post.send(JSON.stringify(part)); }