Compare commits
	
		
			2 Commits
		
	
	
		
			efe36fc60a
			...
			137da0e31e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 137da0e31e | |||
| db0e8c2047 | 
@@ -14,12 +14,30 @@
 | 
			
		||||
		<div class="" id="navbarSupportedContent">
 | 
			
		||||
			<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
 | 
			
		||||
			<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" />
 | 
			
		||||
				<div class="autocomplete-items bg-secondary border-primary me-2 p-2" id="autocomplete-items"></div>
 | 
			
		||||
				<button type="button" class="btn btn-primary" data-bs-toggle="modal"
 | 
			
		||||
				data-bs-target="#search_modal"><i class="bi bi-search"></i></button>
 | 
			
		||||
			</form>
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
</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="d-flex">
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,15 @@ const logger_settings = {
 | 
			
		||||
	logLevel: 'info',
 | 
			
		||||
	scope: 'Core',
 | 
			
		||||
	stream: process.stdout,
 | 
			
		||||
	displayFilename: true
 | 
			
		||||
	displayFilename: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const coreLogger = new Signale(logger_settings);
 | 
			
		||||
export const log = {
 | 
			
		||||
	core: coreLogger,
 | 
			
		||||
	db: coreLogger.scope('DB'),
 | 
			
		||||
	web: coreLogger.scope('WEB')
 | 
			
		||||
	web: coreLogger.scope('WEB'),
 | 
			
		||||
	helper: coreLogger.scope('HELPER')
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Create a new config instance.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,9 @@ import categoryRoute from './categories.js';
 | 
			
		||||
import storageUnitRoute from './storageUnits.js';
 | 
			
		||||
import storageLocationRoute from './storageLocations.js';
 | 
			
		||||
 | 
			
		||||
import search_routes from './search/index.js';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Router base is '/api/v1'
 | 
			
		||||
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('/storageLocations').get(storageLocationRoute.get).post(storageLocationRoute.post).patch(storageLocationRoute.patch).delete(storageLocationRoute.del);
 | 
			
		||||
 | 
			
		||||
Router.use('/search', search_routes);
 | 
			
		||||
 | 
			
		||||
Router.route('/test').get(testRoute.get);
 | 
			
		||||
 | 
			
		||||
export default Router;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								src/routes/api/v1/search/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/routes/api/v1/search/index.ts
									
									
									
									
									
										Normal 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;
 | 
			
		||||
@@ -1,29 +1,113 @@
 | 
			
		||||
document.getElementById("SearchBox").addEventListener("keyup", handleSearchChange);
 | 
			
		||||
const autocompleteBox = document.getElementById("autocomplete-items");
 | 
			
		||||
autocompleteBox.style.display = "none";
 | 
			
		||||
document.getElementById('SearchBoxInput').addEventListener('keyup', handleSearchChange);
 | 
			
		||||
document.getElementById('searchForm').addEventListener('submit', handleSearchSubmit);
 | 
			
		||||
document.addEventListener('keyup', handleHotKey)
 | 
			
		||||
const autocompleteBox = document.getElementById('autocompletBody');
 | 
			
		||||
autocompleteBox.style.display = 'none';
 | 
			
		||||
 | 
			
		||||
currentBestGuessCommand = '';
 | 
			
		||||
 | 
			
		||||
function handleSearchChange(e) {
 | 
			
		||||
	console.log(e.target.value);
 | 
			
		||||
	// 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 #)
 | 
			
		||||
	if(e.target.value != "" ) {
 | 
			
		||||
		autocompleteBox.style.display = "block";
 | 
			
		||||
		autocompleteBox.innerHTML = "Search results will show up here soon <br> Trust me <br> Results";
 | 
			
		||||
	if (e.target.value != '') {
 | 
			
		||||
		autocompleteBox.style.display = 'block';
 | 
			
		||||
		autocompleteBox.innerHTML = 'Search results will show up here soon <br> Trust me <br> Results';
 | 
			
		||||
	} else {
 | 
			
		||||
		autocompleteBox.style.display = "none";
 | 
			
		||||
		autocompleteBox.style.display = 'none';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (e.target.value[0] == ">") {
 | 
			
		||||
		autocompleteBox.innerHTML = "Start typing to search for commands <br> >goto items";
 | 
			
		||||
		if(e.target.value == ">goto items") {
 | 
			
		||||
			autocompleteBox.innerHTML = "<a href='/allItems'>Goto Items</a>";
 | 
			
		||||
	if (e.target.value[0] == '>') {
 | 
			
		||||
		// List of valid routes
 | 
			
		||||
		urlList = {
 | 
			
		||||
			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
 | 
			
		||||
		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 {
 | 
			
		||||
		// 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();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user