mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 13:36:50 +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
|
// Return the API detail endpoint for this Model object
|
||||||
String get url => "${URL}/${pk}/";
|
String get url => "${URL}/${pk}/";
|
||||||
|
|
||||||
/*
|
|
||||||
// Search this Model type in the database
|
// 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");
|
return results;
|
||||||
|
|
||||||
// TODO - Add "timeout"
|
|
||||||
// TODO - Add error catching
|
|
||||||
|
|
||||||
var response =
|
|
||||||
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
Map<String, String> defaultListFilters() { return Map<String, String>(); }
|
Map<String, String> defaultListFilters() { return Map<String, String>(); }
|
||||||
|
|
||||||
|
@ -36,7 +36,13 @@ class InvenTreeDrawer extends StatelessWidget {
|
|||||||
|
|
||||||
void _search() {
|
void _search() {
|
||||||
_closeDrawer();
|
_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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Drawer(
|
return Drawer(
|
||||||
child: new ListView(
|
child: ListView(
|
||||||
children: ListTile.divideTiles(
|
children: ListTile.divideTiles(
|
||||||
context: context,
|
context: context,
|
||||||
tiles: <Widget>[
|
tiles: <Widget>[
|
||||||
new ListTile(
|
ListTile(
|
||||||
leading: new Image.asset(
|
leading: Image.asset(
|
||||||
"assets/image/icon.png",
|
"assets/image/icon.png",
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
width: 40,
|
width: 40,
|
||||||
),
|
),
|
||||||
title: new Text(I18N.of(context).appTitle),
|
title: Text(I18N.of(context).appTitle),
|
||||||
onTap: _home,
|
onTap: _home,
|
||||||
),
|
),
|
||||||
/*
|
ListTile(
|
||||||
// TODO - Add search functionality!
|
title: Text(I18N.of(context).scanBarcode),
|
||||||
new ListTile(
|
onTap: _scan,
|
||||||
title: new Text("Search"),
|
leading: FaIcon(FontAwesomeIcons.barcode),
|
||||||
leading: new FaIcon(FontAwesomeIcons.search),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(I18N.of(context).search),
|
||||||
|
leading: FaIcon(FontAwesomeIcons.search),
|
||||||
onTap: _search,
|
onTap: _search,
|
||||||
),
|
),
|
||||||
*/
|
ListTile(
|
||||||
new ListTile(
|
title: Text(I18N.of(context).parts),
|
||||||
title: new Text(I18N.of(context).scanBarcode),
|
leading: Icon(Icons.category),
|
||||||
onTap: _scan,
|
|
||||||
leading: new FaIcon(FontAwesomeIcons.barcode),
|
|
||||||
),
|
|
||||||
new ListTile(
|
|
||||||
title: new Text(I18N.of(context).parts),
|
|
||||||
leading: new Icon(Icons.category),
|
|
||||||
onTap: _showParts,
|
onTap: _showParts,
|
||||||
),
|
),
|
||||||
new ListTile(
|
ListTile(
|
||||||
title: new Text(I18N.of(context).stock),
|
title: Text(I18N.of(context).stock),
|
||||||
leading: new FaIcon(FontAwesomeIcons.boxes),
|
leading: FaIcon(FontAwesomeIcons.boxes),
|
||||||
onTap: _showStock,
|
onTap: _showStock,
|
||||||
),
|
),
|
||||||
/*
|
/*
|
||||||
new ListTile(
|
ListTile(
|
||||||
title: new Text("Suppliers"),
|
title: Text("Suppliers"),
|
||||||
leading: new FaIcon(FontAwesomeIcons.building),
|
leading: FaIcon(FontAwesomeIcons.building),
|
||||||
onTap: _showSuppliers,
|
onTap: _showSuppliers,
|
||||||
),
|
),
|
||||||
new ListTile(
|
ListTile(
|
||||||
title: Text("Manufacturers"),
|
title: Text("Manufacturers"),
|
||||||
leading: new FaIcon(FontAwesomeIcons.industry),
|
leading: FaIcon(FontAwesomeIcons.industry),
|
||||||
onTap: _showManufacturers,
|
onTap: _showManufacturers,
|
||||||
),
|
),
|
||||||
new ListTile(
|
ListTile(
|
||||||
title: new Text("Customers"),
|
title: Text("Customers"),
|
||||||
leading: new FaIcon(FontAwesomeIcons.users),
|
leading: FaIcon(FontAwesomeIcons.users),
|
||||||
onTap: _showCustomers,
|
onTap: _showCustomers,
|
||||||
),
|
),
|
||||||
*/
|
*/
|
||||||
new ListTile(
|
ListTile(
|
||||||
title: new Text(I18N.of(context).settings),
|
title: Text(I18N.of(context).settings),
|
||||||
leading: new Icon(Icons.settings),
|
leading: Icon(Icons.settings),
|
||||||
onTap: _settings,
|
onTap: _settings,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -43,8 +43,10 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
|||||||
void _search() {
|
void _search() {
|
||||||
if (!InvenTreeAPI().checkConnection(context)) return;
|
if (!InvenTreeAPI().checkConnection(context)) return;
|
||||||
|
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) => SearchWidget()));
|
showSearch(
|
||||||
|
context: context,
|
||||||
|
delegate: PartSearchDelegate()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _scan(BuildContext context) {
|
void _scan(BuildContext context) {
|
||||||
@ -204,13 +206,11 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(I18N.of(context).appTitle),
|
title: Text(I18N.of(context).appTitle),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
/*
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: FaIcon(FontAwesomeIcons.search),
|
icon: FaIcon(FontAwesomeIcons.search),
|
||||||
tooltip: 'Search',
|
tooltip: I18N.of(context).search,
|
||||||
onPressed: _search,
|
onPressed: _search,
|
||||||
),
|
),
|
||||||
*/
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
drawer: new InvenTreeDrawer(context),
|
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/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.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/part.dart';
|
||||||
import 'package:InvenTree/inventree/stock.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 {
|
class SearchWidget extends StatefulWidget {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user