mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
Implementing a generic "ordering" option configuration for paginated list widget
This commit is contained in:
parent
9c4f6710ff
commit
c878f37ec2
@ -1,8 +1,9 @@
|
||||
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/api_form.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/inventree/bom.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
@ -15,6 +16,7 @@ import "package:inventree/widget/part_detail.dart";
|
||||
import "package:inventree/widget/refreshable_state.dart";
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Widget for displaying a list of BomItems for the specified 'parent' Part instance
|
||||
*/
|
||||
@ -30,7 +32,7 @@ class BomList extends StatefulWidget {
|
||||
}
|
||||
|
||||
|
||||
class _BomListState extends RefreshableState<BomList> {
|
||||
class _BomListState extends PaginatedState<BomList> {
|
||||
|
||||
_BomListState(this.parent);
|
||||
|
||||
@ -39,6 +41,15 @@ class _BomListState extends RefreshableState<BomList> {
|
||||
@override
|
||||
String getAppBarTitle(BuildContext context) => L10().billOfMaterials;
|
||||
|
||||
@override
|
||||
String get prefix => "bom_";
|
||||
|
||||
@override
|
||||
Map<String, String> get orderingOptions => {
|
||||
"quantity": L10().quantity,
|
||||
"part": L10().part,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget getBody(BuildContext context) {
|
||||
return PaginatedBomList({
|
||||
|
@ -3,9 +3,129 @@ import "package:flutter/material.dart";
|
||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||
import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart";
|
||||
|
||||
import "package:inventree/api_form.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
|
||||
import "package:inventree/inventree/model.dart";
|
||||
import "package:inventree/inventree/sentry.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
import "package:inventree/preferences.dart";
|
||||
|
||||
import "package:inventree/widget/refreshable_state.dart";
|
||||
|
||||
|
||||
/*
|
||||
* Generic widget class for displaying a "paginated list".
|
||||
* Provides some basic functionality for adjusting ordering and filtering options
|
||||
*/
|
||||
abstract class PaginatedState<T extends StatefulWidget> extends RefreshableState<T> {
|
||||
|
||||
// Prefix for storing and loading pagination options
|
||||
String get prefix => "prefix_";
|
||||
|
||||
// Ordering options for this paginated state (override in implementing class)
|
||||
Map<String, String> get orderingOptions => {};
|
||||
|
||||
@override
|
||||
List<Widget> getAppBarActions(BuildContext context) {
|
||||
List<Widget> actions = [];
|
||||
|
||||
// If ordering options have been provided
|
||||
if (orderingOptions.isNotEmpty) {
|
||||
actions.add(IconButton(
|
||||
icon: FaIcon(FontAwesomeIcons.sort),
|
||||
onPressed: () => _updateFilters(context),
|
||||
));
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
// Return the selected ordering "field" for this list widget
|
||||
Future<String> orderingField() async {
|
||||
dynamic field = await InvenTreeSettingsManager().getValue("${prefix}ordering_field", null);
|
||||
|
||||
if (field != null) {
|
||||
return field.toString();
|
||||
} else if (orderingOptions.isNotEmpty) {
|
||||
// By default, return the first specified key
|
||||
return orderingOptions.keys.first;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Return the selected ordering "order" ("+" or "-") for this list widget
|
||||
Future<String> orderingOrder() async {
|
||||
dynamic order = await InvenTreeSettingsManager().getValue("${prefix}ordering_order", "+");
|
||||
|
||||
return order == "+" ? "+" : "-";
|
||||
}
|
||||
|
||||
// Update the (configurable) filters for this paginated list
|
||||
Future<void> _updateFilters(BuildContext context) async {
|
||||
|
||||
// Retrieve stored setting
|
||||
dynamic _field = await orderingField();
|
||||
dynamic _order = await orderingOrder();
|
||||
|
||||
// Construct the 'ordering' options
|
||||
List<Map<String, dynamic>> _opts = [];
|
||||
|
||||
orderingOptions.forEach((k, v) => _opts.add({
|
||||
"value": k.toString(),
|
||||
"display_name": v.toString()
|
||||
}));
|
||||
|
||||
if (_field == null && _opts.isNotEmpty) {
|
||||
_field = _opts.first["value"];
|
||||
}
|
||||
|
||||
Map<String, dynamic> fields = {
|
||||
"ordering_field": {
|
||||
"type": "choice",
|
||||
"label": "Ordering Field",
|
||||
"required": true,
|
||||
"choices": _opts,
|
||||
"value": _field,
|
||||
},
|
||||
"ordering_order": {
|
||||
"type": "choice",
|
||||
"label": "Ordering Direction",
|
||||
"required": true,
|
||||
"value": _order,
|
||||
"choices": [
|
||||
{
|
||||
"value": "+",
|
||||
"display_name": "Ascending",
|
||||
},
|
||||
{
|
||||
"value": "-",
|
||||
"display_name": "Descending",
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
launchApiForm(
|
||||
context,
|
||||
"...filtering...",
|
||||
"",
|
||||
fields,
|
||||
icon: FontAwesomeIcons.checkCircle,
|
||||
onSuccess: (Map<String, dynamic> data) async {
|
||||
|
||||
// Extract data from the processed form
|
||||
String f = (data["ordering_field"] ?? _field) as String;
|
||||
String o = (data["ordering_order"] ?? _order) as String;
|
||||
|
||||
// Save values to settings
|
||||
await InvenTreeSettingsManager().setValue("${prefix}ordering_field", f);
|
||||
await InvenTreeSettingsManager().setValue("${prefix}ordering_order", o);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class PaginatedSearchState<T extends StatefulWidget> extends State<T> {
|
||||
@ -21,6 +141,10 @@ class PaginatedSearchState<T extends StatefulWidget> extends State<T> {
|
||||
|
||||
int resultCount = 0;
|
||||
|
||||
// List of variables by which the list can be "ordered".
|
||||
// Override in any implementing sub-class
|
||||
List<String> orderingFilters = [];
|
||||
|
||||
// Text controller
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
|
12
pubspec.yaml
12
pubspec.yaml
@ -10,11 +10,11 @@ dependencies:
|
||||
|
||||
audioplayers: ^0.20.1 # Play audio files
|
||||
cached_network_image: ^3.2.0 # Download and cache remote images
|
||||
camera: ^0.9.4 # Camera
|
||||
camera: ^0.9.4 # Camera
|
||||
cupertino_icons: ^1.0.3
|
||||
datetime_picker_formfield: ^2.0.0 # Date / time picker
|
||||
device_info_plus: ^3.2.2 # Information about the device
|
||||
dropdown_search: ^0.6.3 # Dropdown autocomplete form fields
|
||||
dropdown_search: ^0.6.3 # Dropdown autocomplete form fields
|
||||
file_picker: ^4.5.1 # Select files from the device
|
||||
flutter:
|
||||
sdk: flutter
|
||||
@ -28,14 +28,14 @@ dependencies:
|
||||
infinite_scroll_pagination: ^3.1.0 # Let the server do all the work!
|
||||
intl: ^0.17.0
|
||||
one_context: ^1.1.0 # Dialogs without requiring context
|
||||
open_file: ^3.2.1 # Open local files
|
||||
open_file: ^3.2.1 # Open local files
|
||||
package_info_plus: ^1.0.4 # App information introspection
|
||||
path: ^1.8.0
|
||||
path_provider: ^2.0.2 # Local file storage
|
||||
path_provider: ^2.0.2 # Local file storage
|
||||
qr_code_scanner: ^0.7.0 # Barcode scanning
|
||||
sembast: ^3.1.0+2 # NoSQL data storage
|
||||
sentry_flutter: ^6.4.0 # Error reporting
|
||||
url_launcher: ^6.0.9 # Open link in system browser
|
||||
sentry_flutter: ^6.4.0 # Error reporting
|
||||
url_launcher: ^6.0.9 # Open link in system browser
|
||||
|
||||
dev_dependencies:
|
||||
flutter_launcher_icons: ^0.9.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user