Compare commits

...

2 Commits

Author SHA1 Message Date
137da0e31e Added helper logger 2023-06-27 20:54:47 +02:00
db0e8c2047 Added search api endpoint / Implemented search 2023-06-27 20:54:27 +02:00
5 changed files with 137 additions and 20 deletions

View File

@ -14,12 +14,30 @@
<div class="" id="navbarSupportedContent"> <div class="" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul> <ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<form class="d-flex" role="search"> <form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" id="SearchBox" data-bs-trigger="focus" autocomplete="false" data-bs-toggle="popover" data-bs-title="Search" data-bs-content="Please type a little more" data-bs-placement="bottom" /> <button type="button" class="btn btn-primary" data-bs-toggle="modal"
<div class="autocomplete-items bg-secondary border-primary me-2 p-2" id="autocomplete-items"></div> data-bs-target="#search_modal"><i class="bi bi-search"></i></button>
</form> </form>
</div> </div>
</div> </div>
</nav> </nav>
<div class="modal" id="search_modal">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="modalSearchBar">
<div class="input-group mb-3">
<form id="searchForm">
<input type="text" id="SearchBoxInput" class="form-control focus" placeholder="Start typing to search..." aria-label="Search" autocomplete="off">
</form>
</div>
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="autocompletBody">
</div>
</div>
</div>
</div>
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" id="masterToast" style="z-index: 2000"> <div class="toast" role="alert" aria-live="assertive" aria-atomic="true" id="masterToast" style="z-index: 2000">
<div class="d-flex"> <div class="d-flex">

View File

@ -20,14 +20,15 @@ const logger_settings = {
logLevel: 'info', logLevel: 'info',
scope: 'Core', scope: 'Core',
stream: process.stdout, stream: process.stdout,
displayFilename: true displayFilename: false
}; };
const coreLogger = new Signale(logger_settings); const coreLogger = new Signale(logger_settings);
export const log = { export const log = {
core: coreLogger, core: coreLogger,
db: coreLogger.scope('DB'), db: coreLogger.scope('DB'),
web: coreLogger.scope('WEB') web: coreLogger.scope('WEB'),
helper: coreLogger.scope('HELPER')
}; };
// Create a new config instance. // Create a new config instance.

View File

@ -7,6 +7,9 @@ import categoryRoute from './categories.js';
import storageUnitRoute from './storageUnits.js'; import storageUnitRoute from './storageUnits.js';
import storageLocationRoute from './storageLocations.js'; import storageLocationRoute from './storageLocations.js';
import search_routes from './search/index.js';
// Router base is '/api/v1' // Router base is '/api/v1'
const Router = express.Router({ strict: false }); const Router = express.Router({ strict: false });
@ -16,6 +19,8 @@ Router.route('/categories').get(categoryRoute.get).post(categoryRoute.post).patc
Router.route('/storageUnits').get(storageUnitRoute.get).post(storageUnitRoute.post).patch(storageUnitRoute.patch).delete(storageUnitRoute.del); Router.route('/storageUnits').get(storageUnitRoute.get).post(storageUnitRoute.post).patch(storageUnitRoute.patch).delete(storageUnitRoute.del);
Router.route('/storageLocations').get(storageLocationRoute.get).post(storageLocationRoute.post).patch(storageLocationRoute.patch).delete(storageLocationRoute.del); Router.route('/storageLocations').get(storageLocationRoute.get).post(storageLocationRoute.post).patch(storageLocationRoute.patch).delete(storageLocationRoute.del);
Router.use('/search', search_routes);
Router.route('/test').get(testRoute.get); Router.route('/test').get(testRoute.get);
export default Router; export default Router;

View File

@ -0,0 +1,9 @@
import express from 'express';
import sku from './sku.js';
// Router base is '/api/v1'
const Router = express.Router({ strict: false });
Router.route('/sku').get(sku.get);
export default Router;

View File

@ -1,29 +1,113 @@
document.getElementById("SearchBox").addEventListener("keyup", handleSearchChange); document.getElementById('SearchBoxInput').addEventListener('keyup', handleSearchChange);
const autocompleteBox = document.getElementById("autocomplete-items"); document.getElementById('searchForm').addEventListener('submit', handleSearchSubmit);
autocompleteBox.style.display = "none"; document.addEventListener('keyup', handleHotKey)
const autocompleteBox = document.getElementById('autocompletBody');
autocompleteBox.style.display = 'none';
currentBestGuessCommand = '';
function handleSearchChange(e) { function handleSearchChange(e) {
console.log(e.target.value); console.log(e.target.value);
// document.getElementById("SearchBox").setAttribute("data-bs-content", "Search results will show up here soon") // document.getElementById("SearchBox").setAttribute("data-bs-content", "Search results will show up here soon")
// return; // No you won't. I'm not done yet.
return; // No you won't. I'm not done yet.
// Check if known prefix is used (either > or #) // Check if known prefix is used (either > or #)
if(e.target.value != "" ) { if (e.target.value != '') {
autocompleteBox.style.display = "block"; autocompleteBox.style.display = 'block';
autocompleteBox.innerHTML = "Search results will show up here soon <br> Trust me <br> Results"; autocompleteBox.innerHTML = 'Search results will show up here soon <br> Trust me <br> Results';
} else { } else {
autocompleteBox.style.display = "none"; autocompleteBox.style.display = 'none';
} }
if (e.target.value[0] == ">") { if (e.target.value[0] == '>') {
autocompleteBox.innerHTML = "Start typing to search for commands <br> >goto items"; // List of valid routes
if(e.target.value == ">goto items") { urlList = {
autocompleteBox.innerHTML = "<a href='/allItems'>Goto Items</a>"; items: { url: '/items?page=1', alias: ['item'] },
'storage locations': { url: '/manage/storages', alias: ['locations', 'storage'] },
'storage units': { url: '/manage/storages#storage-unit-tab', alias: ['units'] },
categories: { url: '/manage/categories', alias: ['category'] }
};
autocompleteBox.innerHTML = 'Start typing to search for commands <br> >goto items';
const args = e.target.value.split(' ');
console.log(args);
if (args.length > 1) {
if (args[0] == '>goto' || args[0] == '>g') {
console.log('Handling >goto');
autocompleteBox.innerHTML = 'Start typing to search for commands <br>' + Object.keys(urlList).join('<br>') + '<br>';
if (args.length >= 2) {
console.log("Autocomplete for 'goto' command with " + args[1] + " as the second argument")
// Check if the second argument matches the urlList or any of its aliases
for (const [key, value] of Object.entries(urlList)) {
console.log(key, value)
if (args[1] == key || value.alias.includes(args[1])) {
// Match found
console.log('Match found');
autocompleteBox.innerHTML = `Go to <a href="${value.url}">${key}</a>`;
currentBestGuessCommand = "open;" + value.url;
break;
} else {
currentBestGuessCommand = '';
}
}
}
}
} }
} else if (e.target.value[0] == "#") { } else if (e.target.value[0] == '#') {
// Search for SKU // Search for SKU
autocompleteBox.innerHTML = "Start typing to search for items by SKU"; const searchedSKU = e.target.value.substring(1);
if(searchedSKU == '') {
autocompleteBox.innerHTML = 'Start typing to search for commands <br> #SKU';
return;
}
const baseURI = window.location.origin;
const url = baseURI + '/api/v1/search/sku?sku=' + searchedSKU;
$.ajax({
type: 'get',
url: url,
success: function (data) {
let result = JSON.parse(data);
let htmlResult = ""
result.forEach(element => {
console.log(element);
htmlResult += `<a href="/${element.SKU}">${element.name}</a><br>`
});
autocompleteBox.innerHTML = htmlResult;
},
error: function (data) {
createNewToast('<i class="bi bi-exclamation-triangle-fill"></i> Something went wrong while searching...', "text-bg-danger", autoHideTime = 3000, autoReload = false)
}
});
} else { } else {
// Search for name // Search for name
} }
} }
function handleSearchSubmit(e) {
console.log('Search submitted');
if(currentBestGuessCommand != '') {
console.log('Submitting command ' + currentBestGuessCommand);
cmdArgs = currentBestGuessCommand.split(';');
if(cmdArgs[0] == 'open') {
// Open the url in the current tab
setTimeout(() => {
window.location.replace(cmdArgs[1]);
}, 200);
return false;
}
}
return false;
}
function handleHotKey(e) {
// If c is pressed, focus on the search box
if(e.key == 'c') {
// Show search_modal modal
bootstrap.Modal.getOrCreateInstance($('#search_modal')).show()
document.getElementById('SearchBoxInput').focus();
}
}