2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-06-12 02:05:29 +00:00

Stock display (#379)

* Display stock quantity more prominently

* Cleanup search widget

* Update for stock_detail widget

* More tweaks

* Change bottom bar icon

* Display boolean parameters appropriately

* Adds ability to edit part parameters

* Bump icon size a bit

* Improvements to filter options

- Allow filtering by "option" type
- To start with, filter stock by status code

* Remove debug message

* Remove getTriState method

- No longer needed
- Remove associated unit tests

* Adjust filters based on server API version

* Muted colors
This commit is contained in:
Oliver
2023-06-24 11:34:42 +10:00
committed by GitHub
parent 8076887e39
commit e9eb84eace
20 changed files with 278 additions and 167 deletions

View File

@ -38,44 +38,39 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
// Override in implementing class
String get prefix => "prefix_";
// Return a map of boolean filtering options available for this list
// Should be overridden by an implementing subclass
Map<String, Map<String, dynamic>> get filterOptions => {};
// Return the boolean value of a particular boolean filter
Future<bool?> getBooleanFilterValue(String key) async {
key = "${prefix}bool_${key}";
Future<dynamic> getFilterValue(String key) async {
key = "${prefix}filter_${key}";
Map<String, dynamic> opts = filterOptions[key] ?? {};
dynamic backup = opts["default"];
final result = await InvenTreeSettingsManager().getValue(key, backup);
bool? backup;
dynamic v = opts["default"];
if (v is bool) {
backup = v;
}
final result = await InvenTreeSettingsManager().getTriState(key, backup);
return result;
}
// Set the boolean value of a particular boolean filter
Future<void> setBooleanFilterValue(String key, bool? value) async {
key = "${prefix}bool_${key}";
Future<void> setFilterValue(String key, dynamic value) async {
key = "${prefix}filter_${key}";
await InvenTreeSettingsManager().setValue(key, value);
}
// Construct the boolean filter options for this list
Future<Map<String, String>> constructBooleanFilters() async {
Future<Map<String, String>> constructFilters() async {
Map<String, String> f = {};
for (String k in filterOptions.keys) {
bool? value = await getBooleanFilterValue(k);
dynamic value = await getFilterValue(k);
if (value is bool) {
f[k] = value ? "true" : "false";
// Skip null values
if (value == null) {
continue;
}
f[k] = value.toString();
}
return f;
@ -164,7 +159,7 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
}
};
// Add in boolean filter options
// Add in selected filter options
for (String key in filterOptions.keys) {
Map<String, dynamic> opts = filterOptions[key] ?? {};
@ -172,17 +167,18 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
String label = (opts["label"] ?? key) as String;
String? help_text = opts["help_text"] as String?;
List<dynamic> choices = (opts["choices"] ?? []) as List<dynamic>;
bool tristate = (opts["tristate"] ?? true) as bool;
bool? v = await getBooleanFilterValue(key);
dynamic v = await getFilterValue(key);
// Prevent null value if not tristate
if (!tristate && v == null) {
v = false;
}
// Add in the particular field
fields[key] = {
Map<String, dynamic> filter = {
"type": "boolean",
"display_name": label,
"label": label,
@ -190,6 +186,16 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
"value": v,
"tristate": (opts["tristate"] ?? true) as bool,
};
if (choices.isNotEmpty) {
// Configure as a choice input
filter["type"] = "choice";
filter["choices"] = choices;
filter.remove("tristate");
}
fields[key] = filter;
}
// Launch an interactive form for the user to select options
@ -211,16 +217,7 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
// Save boolean fields
for (String key in filterOptions.keys) {
bool? v;
dynamic value = data[key];
if (value is bool) {
v = value;
}
await setBooleanFilterValue(key, v);
await setFilterValue(key, data[key]);
}
// Refresh data from the server
@ -293,7 +290,7 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
params["ordering"] = o;
}
Map<String, String> f = await constructBooleanFilters();
Map<String, String> f = await constructFilters();
if (f.isNotEmpty) {
params.addAll(f);
@ -348,6 +345,10 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
void updateSearchTerm() {
searchTerm = searchController.text;
_pagingController.refresh();
if (mounted) {
setState(() {});
}
}
// Function to construct a single paginated item
@ -409,19 +410,19 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
*/
Widget buildSearchInput(BuildContext context) {
return ListTile(
trailing: orderingOptions.isEmpty ? null : GestureDetector(
child: FaIcon(FontAwesomeIcons.sort, color: COLOR_ACTION),
leading: orderingOptions.isEmpty ? null : GestureDetector(
child: Icon(Icons.filter_list, color: COLOR_ACTION, size: 32),
onTap: () async {
_saveOrderingOptions(context);
},
),
leading: GestureDetector(
trailing: GestureDetector(
child: FaIcon(
searchController.text.isEmpty ? FontAwesomeIcons.magnifyingGlass : FontAwesomeIcons.deleteLeft,
color: searchController.text.isNotEmpty ? COLOR_DANGER : null,
color: searchController.text.isNotEmpty ? COLOR_DANGER : COLOR_ACTION,
),
onTap: () {
if (searchController.text.isEmpty) {
if (searchController.text.isNotEmpty) {
searchController.clear();
}
updateSearchTerm();