mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
Adds search results
This commit is contained in:
parent
9cf8559569
commit
d1e612698e
@ -84,21 +84,15 @@ class InvenTreeModel {
|
||||
// Return the API detail endpoint for this Model object
|
||||
String get url => "${URL}/${pk}/";
|
||||
|
||||
/*
|
||||
|
||||
// Search this Model type in the database
|
||||
Future<List<InvenTreeModel>> search(String searchTerm) async {
|
||||
Future<List<InvenTreeModel>> search(BuildContext context, String searchTerm) async {
|
||||
|
||||
String addr = url + "?search=" + search;
|
||||
final results = list(context, filters: {"cascade": "true", "search": searchTerm});
|
||||
|
||||
print("Searching endpoint: $url");
|
||||
|
||||
// TODO - Add "timeout"
|
||||
// TODO - Add error catching
|
||||
|
||||
var response =
|
||||
return results;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
Map<String, String> defaultListFilters() { return Map<String, String>(); }
|
||||
|
||||
|
@ -36,7 +36,13 @@ class InvenTreeDrawer extends StatelessWidget {
|
||||
|
||||
void _search() {
|
||||
_closeDrawer();
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget()));
|
||||
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: PartSearchDelegate()
|
||||
);
|
||||
|
||||
//Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget()));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -101,62 +107,59 @@ class InvenTreeDrawer extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
child: new ListView(
|
||||
child: ListView(
|
||||
children: ListTile.divideTiles(
|
||||
context: context,
|
||||
tiles: <Widget>[
|
||||
new ListTile(
|
||||
leading: new Image.asset(
|
||||
ListTile(
|
||||
leading: Image.asset(
|
||||
"assets/image/icon.png",
|
||||
fit: BoxFit.scaleDown,
|
||||
width: 40,
|
||||
),
|
||||
title: new Text(I18N.of(context).appTitle),
|
||||
title: Text(I18N.of(context).appTitle),
|
||||
onTap: _home,
|
||||
),
|
||||
/*
|
||||
// TODO - Add search functionality!
|
||||
new ListTile(
|
||||
title: new Text("Search"),
|
||||
leading: new FaIcon(FontAwesomeIcons.search),
|
||||
ListTile(
|
||||
title: Text(I18N.of(context).scanBarcode),
|
||||
onTap: _scan,
|
||||
leading: FaIcon(FontAwesomeIcons.barcode),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(I18N.of(context).search),
|
||||
leading: FaIcon(FontAwesomeIcons.search),
|
||||
onTap: _search,
|
||||
),
|
||||
*/
|
||||
new ListTile(
|
||||
title: new Text(I18N.of(context).scanBarcode),
|
||||
onTap: _scan,
|
||||
leading: new FaIcon(FontAwesomeIcons.barcode),
|
||||
),
|
||||
new ListTile(
|
||||
title: new Text(I18N.of(context).parts),
|
||||
leading: new Icon(Icons.category),
|
||||
ListTile(
|
||||
title: Text(I18N.of(context).parts),
|
||||
leading: Icon(Icons.category),
|
||||
onTap: _showParts,
|
||||
),
|
||||
new ListTile(
|
||||
title: new Text(I18N.of(context).stock),
|
||||
leading: new FaIcon(FontAwesomeIcons.boxes),
|
||||
ListTile(
|
||||
title: Text(I18N.of(context).stock),
|
||||
leading: FaIcon(FontAwesomeIcons.boxes),
|
||||
onTap: _showStock,
|
||||
),
|
||||
/*
|
||||
new ListTile(
|
||||
title: new Text("Suppliers"),
|
||||
leading: new FaIcon(FontAwesomeIcons.building),
|
||||
ListTile(
|
||||
title: Text("Suppliers"),
|
||||
leading: FaIcon(FontAwesomeIcons.building),
|
||||
onTap: _showSuppliers,
|
||||
),
|
||||
new ListTile(
|
||||
ListTile(
|
||||
title: Text("Manufacturers"),
|
||||
leading: new FaIcon(FontAwesomeIcons.industry),
|
||||
leading: FaIcon(FontAwesomeIcons.industry),
|
||||
onTap: _showManufacturers,
|
||||
),
|
||||
new ListTile(
|
||||
title: new Text("Customers"),
|
||||
leading: new FaIcon(FontAwesomeIcons.users),
|
||||
ListTile(
|
||||
title: Text("Customers"),
|
||||
leading: FaIcon(FontAwesomeIcons.users),
|
||||
onTap: _showCustomers,
|
||||
),
|
||||
*/
|
||||
new ListTile(
|
||||
title: new Text(I18N.of(context).settings),
|
||||
leading: new Icon(Icons.settings),
|
||||
ListTile(
|
||||
title: Text(I18N.of(context).settings),
|
||||
leading: Icon(Icons.settings),
|
||||
onTap: _settings,
|
||||
),
|
||||
]
|
||||
|
@ -43,8 +43,10 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
||||
void _search() {
|
||||
if (!InvenTreeAPI().checkConnection(context)) return;
|
||||
|
||||
Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget()));
|
||||
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: PartSearchDelegate()
|
||||
);
|
||||
}
|
||||
|
||||
void _scan(BuildContext context) {
|
||||
@ -204,13 +206,11 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
||||
appBar: AppBar(
|
||||
title: Text(I18N.of(context).appTitle),
|
||||
actions: <Widget>[
|
||||
/*
|
||||
IconButton(
|
||||
icon: FaIcon(FontAwesomeIcons.search),
|
||||
tooltip: 'Search',
|
||||
tooltip: I18N.of(context).search,
|
||||
onPressed: _search,
|
||||
),
|
||||
*/
|
||||
],
|
||||
),
|
||||
drawer: new InvenTreeDrawer(context),
|
||||
|
@ -1,4 +1,7 @@
|
||||
|
||||
import 'package:InvenTree/widget/part_detail.dart';
|
||||
import 'package:InvenTree/widget/progress.dart';
|
||||
import 'package:InvenTree/widget/snacks.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
@ -7,6 +10,156 @@ import 'package:InvenTree/widget/refreshable_state.dart';
|
||||
import 'package:InvenTree/inventree/part.dart';
|
||||
import 'package:InvenTree/inventree/stock.dart';
|
||||
|
||||
import '../api.dart';
|
||||
|
||||
|
||||
class PartSearchDelegate extends SearchDelegate<InvenTreePart> {
|
||||
|
||||
final key = GlobalKey<ScaffoldState>();
|
||||
|
||||
bool _searching = false;
|
||||
|
||||
// List of part results
|
||||
List<InvenTreePart> partResults = [];
|
||||
|
||||
Future<void> search(BuildContext context) async {
|
||||
|
||||
// Search string too short!
|
||||
if (query.length < 3) {
|
||||
partResults.clear();
|
||||
showResults(context);
|
||||
return;
|
||||
}
|
||||
|
||||
_searching = true;
|
||||
|
||||
print("Searching...");
|
||||
|
||||
showResults(context);
|
||||
|
||||
final results = await InvenTreePart().search(context, query);
|
||||
|
||||
partResults.clear();
|
||||
|
||||
for (int idx = 0; idx < results.length; idx++) {
|
||||
if (results[idx] is InvenTreePart) {
|
||||
partResults.add(results[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
print("Searching complete! Results: ${partResults.length}");
|
||||
_searching = false;
|
||||
|
||||
// TODO: Show a snackbar detailing number of results...
|
||||
//showSnackIcon("Found ${partResults.length} parts", context: context);
|
||||
|
||||
// For some reason, need to toggle between suggestions and results here...
|
||||
showSuggestions(context);
|
||||
showResults(context);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Widget> buildActions(BuildContext context) {
|
||||
return [
|
||||
IconButton(
|
||||
icon: FaIcon(FontAwesomeIcons.search),
|
||||
onPressed: () {
|
||||
search(context);
|
||||
}
|
||||
),
|
||||
IconButton(
|
||||
icon: FaIcon(FontAwesomeIcons.backspace),
|
||||
onPressed: () {
|
||||
query = '';
|
||||
search(context);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildLeading(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
this.close(context, null);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Widget _partResult(BuildContext context, int index) {
|
||||
|
||||
InvenTreePart part = partResults[index];
|
||||
|
||||
return ListTile(
|
||||
title: Text(part.fullname),
|
||||
subtitle: Text(part.description),
|
||||
leading: InvenTreeAPI().getImage(
|
||||
part.thumbnail,
|
||||
width: 40,
|
||||
height: 40
|
||||
),
|
||||
onTap: () {
|
||||
InvenTreePart().get(context, part.pk).then((var prt) {
|
||||
if (prt is InvenTreePart) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => PartDetailWidget(prt))
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildResults(BuildContext context) {
|
||||
|
||||
print("Build results called...");
|
||||
|
||||
if (_searching) {
|
||||
return progressIndicator();
|
||||
}
|
||||
|
||||
if (query.length < 3) {
|
||||
return ListTile(
|
||||
title: Text("Query too short"),
|
||||
subtitle: Text("Enter a query of at least three characters")
|
||||
);
|
||||
}
|
||||
|
||||
if (partResults.length == 0) {
|
||||
return ListTile(
|
||||
title: Text("No Results"),
|
||||
subtitle: Text("No results matching query")
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: ClampingScrollPhysics(),
|
||||
separatorBuilder: (_, __) => const Divider(height: 3),
|
||||
itemBuilder: _partResult,
|
||||
itemCount: partResults.length,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildSuggestions(BuildContext context) {
|
||||
// TODO - Implement
|
||||
return Column();
|
||||
}
|
||||
|
||||
// Ensure the search theme matches the app theme
|
||||
@override
|
||||
ThemeData appBarTheme(BuildContext context) {
|
||||
assert(context != null);
|
||||
final ThemeData theme = Theme.of(context);
|
||||
assert(theme != null);
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SearchWidget extends StatefulWidget {
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user