mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
Consolidated search (#289)
* Update search widget to support consolidated search API endpoint * Finer control over global search * Update release notes * remove unused variable
This commit is contained in:
parent
9543490c21
commit
d7f2c3939b
@ -6,6 +6,7 @@
|
||||
|
||||
- Adds support for proper currency rendering
|
||||
- Fix icon for supplier part detail widget
|
||||
- Support global search API endpoint
|
||||
|
||||
### 0.10.1 - February 2023
|
||||
---
|
||||
|
@ -279,6 +279,9 @@ class InvenTreeAPI {
|
||||
// Company attachments require API v95 or newer
|
||||
bool get supportCompanyAttachments => isConnected() && apiVersion >= 95;
|
||||
|
||||
// Consolidated search request API v102 or newer
|
||||
bool get supportsConsolidatedSearch => isConnected() && apiVersion >= 102;
|
||||
|
||||
// Are plugins enabled on the server?
|
||||
bool _pluginsEnabled = false;
|
||||
|
||||
|
@ -69,27 +69,34 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
|
||||
Timer? debounceTimer;
|
||||
|
||||
/*
|
||||
* Decrement the number of pending / outstanding search queries
|
||||
*/
|
||||
void decrementPendingSearches() {
|
||||
if (nPendingSearches > 0) {
|
||||
nPendingSearches--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the search is still running
|
||||
*/
|
||||
bool isSearching() {
|
||||
|
||||
if (searchController.text.isEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nSearchResults < 5;
|
||||
return nPendingSearches > 0;
|
||||
}
|
||||
|
||||
int nSearchResults = 0;
|
||||
|
||||
// Individual search result count (for legacy search API)
|
||||
int nPendingSearches = 0;
|
||||
int nPartResults = 0;
|
||||
|
||||
int nCategoryResults = 0;
|
||||
|
||||
int nStockResults = 0;
|
||||
|
||||
int nLocationResults = 0;
|
||||
|
||||
int nSupplierResults = 0;
|
||||
|
||||
int nPurchaseOrderResults = 0;
|
||||
|
||||
late FocusNode _focusNode;
|
||||
@ -114,6 +121,32 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the 'result count' for a particular query from the results map
|
||||
* e.g.
|
||||
* {
|
||||
* "part": {
|
||||
* "count": 102,
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
int getSearchResultCount(Map <String, dynamic> results, String key) {
|
||||
|
||||
dynamic result = results[key];
|
||||
|
||||
if (result == null || result is! Map) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dynamic count = result["count"];
|
||||
|
||||
if (count == null || count is! int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate multiple search requests to the server.
|
||||
* Each request returns at *some point* in the future,
|
||||
@ -122,7 +155,6 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
* So, each request only causes an update *if* the search term is still the same when it completes
|
||||
*/
|
||||
Future<void> search(String term) async {
|
||||
|
||||
var api = InvenTreeAPI();
|
||||
|
||||
if (!mounted) {
|
||||
@ -138,21 +170,95 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
nSupplierResults = 0;
|
||||
nPurchaseOrderResults = 0;
|
||||
|
||||
nSearchResults = 0;
|
||||
nPendingSearches = 0;
|
||||
});
|
||||
|
||||
if (term.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Consolidated search allows us to perform *all* searches in a single query
|
||||
if (api.supportsConsolidatedSearch) {
|
||||
Map<String, dynamic> body = {
|
||||
"limit": 1,
|
||||
"search": term,
|
||||
};
|
||||
|
||||
// Part search
|
||||
if (api.checkPermission("part", "view")) {
|
||||
body["part"] = {};
|
||||
}
|
||||
|
||||
// PartCategory search
|
||||
if (api.checkPermission("part_category", "view")) {
|
||||
body["partcategory"] = {};
|
||||
}
|
||||
|
||||
// StockItem search
|
||||
if (api.checkPermission("stock", "view")) {
|
||||
body["stockitem"] = {
|
||||
"in_stock": true,
|
||||
};
|
||||
}
|
||||
|
||||
// StockLocation search
|
||||
if (api.checkPermission("stock_location", "view")) {
|
||||
body["stocklocation"] = {};
|
||||
}
|
||||
|
||||
// PurchaseOrder search
|
||||
if (api.checkPermission("purchase_order", "view")) {
|
||||
body["purchaseorder"] = {
|
||||
"outstanding": true
|
||||
};
|
||||
}
|
||||
|
||||
if (body.isNotEmpty) {
|
||||
nPendingSearches++;
|
||||
|
||||
api.post(
|
||||
"search/",
|
||||
body: body,
|
||||
expectedStatusCode: 200).then((APIResponse response) {
|
||||
decrementPendingSearches();
|
||||
|
||||
Map<String, dynamic> results = {};
|
||||
|
||||
if (response.data is Map<String, dynamic>) {
|
||||
results = response.data as Map<String, dynamic>;
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
nPartResults = getSearchResultCount(results, "part");
|
||||
nCategoryResults = getSearchResultCount(results, "partcategory");
|
||||
nStockResults = getSearchResultCount(results, "stockitem");
|
||||
nLocationResults = getSearchResultCount(results, "stocklocation");
|
||||
nSupplierResults = 0; //getSearchResultCount(results, "")
|
||||
nPurchaseOrderResults = getSearchResultCount(results, "purchaseorder");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
legacySearch(term);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform "legacy" search (without consolidated search API endpoint
|
||||
*/
|
||||
Future<void> legacySearch(String term) async {
|
||||
|
||||
// Search parts
|
||||
if (api.checkPermission("part", "view")) {
|
||||
nPendingSearches++;
|
||||
InvenTreePart().count(searchQuery: term).then((int n) {
|
||||
if (term == searchController.text) {
|
||||
if (mounted) {
|
||||
decrementPendingSearches();
|
||||
setState(() {
|
||||
nPartResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -161,12 +267,13 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
|
||||
// Search part categories
|
||||
if (api.checkPermission("part_category", "view")) {
|
||||
nPendingSearches++;
|
||||
InvenTreePartCategory().count(searchQuery: term,).then((int n) {
|
||||
if (term == searchController.text) {
|
||||
if (mounted) {
|
||||
decrementPendingSearches();
|
||||
setState(() {
|
||||
nCategoryResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -175,12 +282,13 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
|
||||
// Search stock items
|
||||
if (api.checkPermission("stock", "view")) {
|
||||
nPendingSearches++;
|
||||
InvenTreeStockItem().count(searchQuery: term).then((int n) {
|
||||
if (term == searchController.text) {
|
||||
if (mounted) {
|
||||
decrementPendingSearches();
|
||||
setState(() {
|
||||
nStockResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -189,35 +297,22 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
|
||||
// Search stock locations
|
||||
if (api.checkPermission("stock_location", "view")) {
|
||||
nPendingSearches++;
|
||||
InvenTreeStockLocation().count(searchQuery: term).then((int n) {
|
||||
if (term == searchController.text) {
|
||||
if (mounted) {
|
||||
decrementPendingSearches();
|
||||
setState(() {
|
||||
nLocationResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TDOO: Re-implement this once display for companies has been fixed
|
||||
/*
|
||||
// Search suppliers
|
||||
InvenTreeCompany().count(searchQuery: term,
|
||||
filters: {
|
||||
"is_supplier": "true",
|
||||
},
|
||||
).then((int n) {
|
||||
setState(() {
|
||||
nSupplierResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
// Search purchase orders
|
||||
if (api.checkPermission("purchase_order", "view")) {
|
||||
nPendingSearches++;
|
||||
InvenTreePurchaseOrder().count(
|
||||
searchQuery: term,
|
||||
filters: {
|
||||
@ -226,9 +321,9 @@ class _SearchDisplayState extends RefreshableState<SearchWidget> {
|
||||
).then((int n) {
|
||||
if (term == searchController.text) {
|
||||
if (mounted) {
|
||||
decrementPendingSearches();
|
||||
setState(() {
|
||||
nPurchaseOrderResults = n;
|
||||
nSearchResults++;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user