From a6de7d619a9143014f00261f82fecf012f5e046d Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 5 Mar 2021 21:07:58 +1100 Subject: [PATCH] Refactor search --- lib/widget/category_display.dart | 43 ++++--------- lib/widget/location_display.dart | 100 ++++++++++++++----------------- lib/widget/paginator.dart | 26 +++++--- lib/widget/part_detail.dart | 25 +------- 4 files changed, 77 insertions(+), 117 deletions(-) diff --git a/lib/widget/category_display.dart b/lib/widget/category_display.dart index 513ae45a..63c2fe4d 100644 --- a/lib/widget/category_display.dart +++ b/lib/widget/category_display.dart @@ -46,6 +46,7 @@ class _CategoryDisplayState extends RefreshableState { List actions = []; + /* actions.add( IconButton( icon: FaIcon(FontAwesomeIcons.search), @@ -64,6 +65,7 @@ class _CategoryDisplayState extends RefreshableState { } ) ); + */ if ((category != null) && InvenTreeAPI().checkPermission('part_category', 'change')) { actions.add( @@ -361,7 +363,7 @@ class _PaginatedPartListState extends State { static const _pageSize = 25; - String _searchTerm; + String _searchTerm = ""; Function onTotalChanged; @@ -393,9 +395,7 @@ class _PaginatedPartListState extends State { Map params = filters; - if (_searchTerm != null && _searchTerm.isNotEmpty) { - params["search"] = _searchTerm; - } + params["search"] = _searchTerm ?? ""; final bool cascade = await InvenTreeSettingsManager().getValue("partSubcategory", false); params["cascade"] = "${cascade}"; @@ -459,8 +459,13 @@ class _PaginatedPartListState extends State { ); } - void updateSearchTerm(String searchTerm) { - _searchTerm = searchTerm; + final TextEditingController searchController = TextEditingController(); + + void updateSearchTerm() { + + print("Search Term: '${_searchTerm}'"); + + _searchTerm = searchController.text; _pagingController.refresh(); } @@ -469,10 +474,7 @@ class _PaginatedPartListState extends State { return Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - PaginatedSearch( - callback: updateSearchTerm, - results: resultCount - ), + PaginatedSearchWidget(searchController, updateSearchTerm, resultCount), Expanded( child: CustomScrollView( shrinkWrap: true, @@ -496,26 +498,5 @@ class _PaginatedPartListState extends State { ) ], ); - return CustomScrollView( - shrinkWrap: true, - physics: ClampingScrollPhysics(), - scrollDirection: Axis.vertical, - slivers: [ - // TODO: Introduce searching within the list - PaginatedSearch(callback: updateSearchTerm), - PagedSliverList.separated( - pagingController: _pagingController, - builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (context, item, index) { - return _buildPart(context, item); - }, - noItemsFoundIndicatorBuilder: (context) { - return NoResultsWidget("No parts found"); - } - ), - separatorBuilder: (context, index) => const Divider(height: 1), - ), - ] - ); } } diff --git a/lib/widget/location_display.dart b/lib/widget/location_display.dart index ed786a27..30ecf99a 100644 --- a/lib/widget/location_display.dart +++ b/lib/widget/location_display.dart @@ -46,6 +46,7 @@ class _LocationDisplayState extends RefreshableState { List actions = []; + /* actions.add( IconButton( icon: FaIcon(FontAwesomeIcons.search), @@ -64,6 +65,7 @@ class _LocationDisplayState extends RefreshableState { } ), ); + */ if ((location != null) && (InvenTreeAPI().checkPermission('stock_location', 'change'))) { actions.add( @@ -247,30 +249,7 @@ class _LocationDisplayState extends RefreshableState { children: detailTiles(), ); case 1: - return Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - locationDescriptionCard(includeActions: false), - ListTile( - title: Text( - I18N.of(context).stockItems, - style: TextStyle(fontWeight: FontWeight.bold), - ), - trailing: Text("${stockItemCount}") - ), - Divider(height: 3), - Expanded( - child: PaginatedStockList( - filters, - onTotalChanged: (int total) { - setState(() { - stockItemCount = total; - }); - } - ), - ) - ] - ); + return PaginatedStockList(filters); case 2: return ListView( children: ListTile.divideTiles( @@ -414,12 +393,10 @@ class PaginatedStockList extends StatefulWidget { final Map filters; - Function onTotalChanged; - - PaginatedStockList(this.filters, {this.onTotalChanged}); + PaginatedStockList(this.filters); @override - _PaginatedStockListState createState() => _PaginatedStockListState(filters, onTotalChanged); + _PaginatedStockListState createState() => _PaginatedStockListState(filters); } @@ -427,13 +404,11 @@ class _PaginatedStockListState extends State { static const _pageSize = 25; - String _searchTerm; + String _searchTerm = ""; final Map filters; - Function onTotalChanged; - - _PaginatedStockListState(this.filters, this.onTotalChanged); + _PaginatedStockListState(this.filters); final PagingController _pagingController = PagingController(firstPageKey: 0); @@ -452,14 +427,14 @@ class _PaginatedStockListState extends State { super.dispose(); } + int resultCount = 0; + Future _fetchPage(int pageKey) async { try { Map params = this.filters; - if (_searchTerm != null && _searchTerm.isNotEmpty) { - params["search"] = "${_searchTerm}"; - } + params["search"] = "${_searchTerm}"; // Do we include stock items from sub-locations? final bool cascade = await InvenTreeSettingsManager().getValue("stockSublocation", false); @@ -484,9 +459,9 @@ class _PaginatedStockListState extends State { _pagingController.appendPage(items, nextPageKey); } - if (onTotalChanged != null) { - onTotalChanged(page.count); - } + setState(() { + resultCount = page.count; + }); } catch (error) { _pagingController.error = error; @@ -519,25 +494,40 @@ class _PaginatedStockListState extends State { ); } + final TextEditingController searchController = TextEditingController(); + + void updateSearchTerm() { + _searchTerm = searchController.text; + _pagingController.refresh(); + } + @override Widget build (BuildContext context) { - return CustomScrollView( - shrinkWrap: true, - physics: ClampingScrollPhysics(), - scrollDirection: Axis.vertical, - slivers: [ - // TODO - Search input - PagedSliverList.separated( - pagingController: _pagingController, - builderDelegate: PagedChildBuilderDelegate( - itemBuilder: (context, item, index) { - return _buildItem(context, item); - }, - noItemsFoundIndicatorBuilder: (context) { - return NoResultsWidget("No stock items found"); - } - ), - separatorBuilder: (context, item) => const Divider(height: 1), + return Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + PaginatedSearchWidget(searchController, updateSearchTerm, resultCount), + Expanded( + child: CustomScrollView( + shrinkWrap: true, + physics: ClampingScrollPhysics(), + scrollDirection: Axis.vertical, + slivers: [ + // TODO - Search input + PagedSliverList.separated( + pagingController: _pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (context, item, index) { + return _buildItem(context, item); + }, + noItemsFoundIndicatorBuilder: (context) { + return NoResultsWidget("No stock items found"); + } + ), + separatorBuilder: (context, item) => const Divider(height: 1), + ) + ] + ) ) ] ); diff --git a/lib/widget/paginator.dart b/lib/widget/paginator.dart index 4b710983..62387b25 100644 --- a/lib/widget/paginator.dart +++ b/lib/widget/paginator.dart @@ -5,22 +5,34 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -class PaginatedSearch extends StatelessWidget { +class PaginatedSearchWidget extends StatelessWidget { - Function callback; + Function onChanged; int results = 0; - PaginatedSearch({this.callback, this.results}); + TextEditingController controller; + + PaginatedSearchWidget(this.controller, this.onChanged, this.results); @override Widget build(BuildContext context) { return ListTile( - leading: FaIcon(FontAwesomeIcons.search), - title: TextField( + leading: GestureDetector( + child: FaIcon(controller.text.isEmpty ? FontAwesomeIcons.search : FontAwesomeIcons.backspace), + onTap: () { + if (onChanged != null) { + controller.clear(); + onChanged(); + } + }, + ), + title: TextFormField( + controller: controller, onChanged: (value) { - if (callback != null) { - callback(value); + + if (onChanged != null) { + onChanged(); } }, decoration: InputDecoration( diff --git a/lib/widget/part_detail.dart b/lib/widget/part_detail.dart index 72f8a24a..040bca7c 100644 --- a/lib/widget/part_detail.dart +++ b/lib/widget/part_detail.dart @@ -441,30 +441,7 @@ class _PartDisplayState extends RefreshableState { ), ); case 1: - return Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - headerTile(), - ListTile( - title: Text( - I18N.of(context).stockItems, - style: TextStyle(fontWeight: FontWeight.bold), - ), - trailing: Text("${stockItemCount}") - ), - Divider(height: 3), - Expanded( - child: PaginatedStockList( - {"part": "${part.pk}"}, - onTotalChanged: (int total) { - setState(() { - stockItemCount = total; - }); - }, - ) - ) - ], - ); + return PaginatedStockList({"part": "${part.pk}"}); case 2: return Center( child: ListView(