2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 13:36:50 +00:00

Stock test actions (#345)

* Use FAB for stock item test result

* Change long press to tap

* Add setting to control display of stock tests results

* Add question mark if no result recorded
This commit is contained in:
Oliver 2023-04-28 23:27:59 +10:00 committed by GitHub
parent 49226a5fce
commit 383571707e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 80 additions and 34 deletions

View File

@ -4,6 +4,7 @@
- Add support for Project Codes - Add support for Project Codes
- Improve purchase order support - Improve purchase order support
- Fix action button colors - Fix action button colors
- Improvements for stock item test result display
- Added Norwegian translations - Added Norwegian translations
- Fix serial number field when creating stock item - Fix serial number field when creating stock item

View File

@ -11,6 +11,9 @@ import "package:inventree/inventree/model.dart";
/*
* Class representing a test result for a single stock item
*/
class InvenTreeStockItemTestResult extends InvenTreeModel { class InvenTreeStockItemTestResult extends InvenTreeModel {
InvenTreeStockItemTestResult() : super(); InvenTreeStockItemTestResult() : super();

View File

@ -1208,6 +1208,9 @@
"description": "" "description": ""
}, },
"testResultsDetail": "Display stock item test results",
"@testResultsDetail": {},
"testResultAdd": "Add Test Result", "testResultAdd": "Add Test Result",
"@testResultAdd": {}, "@testResultAdd": {},

View File

@ -24,6 +24,7 @@ const String INV_PART_SHOW_BOM = "partShowBom";
// Stock settings // Stock settings
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory"; const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
const String INV_STOCK_SHOW_TESTS = "stockShowTests";
const String INV_REPORT_ERRORS = "reportErrors"; const String INV_REPORT_ERRORS = "reportErrors";
const String INV_STRICT_HTTPS = "strictHttps"; const String INV_STRICT_HTTPS = "strictHttps";

View File

@ -18,6 +18,7 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
bool partShowParameters = true; bool partShowParameters = true;
bool partShowBom = true; bool partShowBom = true;
bool stockShowHistory = false; bool stockShowHistory = false;
bool stockShowTests = false;
@override @override
void initState() { void initState() {
@ -30,6 +31,7 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
partShowParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool; partShowParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
partShowBom = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_BOM, true) as bool; partShowBom = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_BOM, true) as bool;
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool; stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
stockShowTests = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_TESTS, true) as bool;
if (mounted) { if (mounted) {
setState(() { setState(() {
@ -86,6 +88,20 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
}, },
), ),
), ),
ListTile(
title: Text(L10().testResults),
subtitle: Text(L10().testResultsDetail),
leading: FaIcon(FontAwesomeIcons.vial),
trailing: Switch(
value: stockShowTests,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_STOCK_SHOW_TESTS, value);
setState(() {
stockShowTests = value;
});
},
),
)
] ]
) )
) )

View File

@ -47,6 +47,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
String getAppBarTitle() => L10().stockItem; String getAppBarTitle() => L10().stockItem;
bool stockShowHistory = false; bool stockShowHistory = false;
bool stockShowTests = true;
@override @override
List<Widget> appBarActions(BuildContext context) { List<Widget> appBarActions(BuildContext context) {
@ -214,6 +215,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
await api.StockStatus.load(); await api.StockStatus.load();
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool; stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
stockShowTests = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_TESTS, true) as bool;
final bool result = widget.item.pk > 0 && await widget.item.reload(); final bool result = widget.item.pk > 0 && await widget.item.reload();
@ -226,15 +228,19 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
// Request part information // Request part information
part = await InvenTreePart().get(widget.item.partId) as InvenTreePart?; part = await InvenTreePart().get(widget.item.partId) as InvenTreePart?;
// Request test results (async) stockShowTests &= part?.isTrackable ?? false;
widget.item.getTestResults().then((value) {
if (mounted) { // Request test results (async)
setState(() { if (stockShowTests) {
// Update widget.item.getTestResults().then((value) {
});
} if (mounted) {
}); setState(() {
// Update
});
}
});
}
// Request the number of attachments // Request the number of attachments
InvenTreeStockItemAttachment().count( InvenTreeStockItemAttachment().count(
@ -753,7 +759,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
); );
} }
if ((widget.item.testResultCount > 0) || (part?.isTrackable ?? false)) { if (stockShowTests || (widget.item.testResultCount > 0)) {
tiles.add( tiles.add(
ListTile( ListTile(
title: Text(L10().testResults), title: Text(L10().testResults),

View File

@ -1,15 +1,17 @@
import "package:flutter/material.dart";
import "package:flutter_speed_dial/flutter_speed_dial.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:inventree/api.dart";
import "package:inventree/app_colors.dart"; import "package:inventree/app_colors.dart";
import "package:inventree/l10.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 "package:inventree/inventree/model.dart"; import "package:inventree/inventree/model.dart";
import "package:inventree/api.dart";
import "package:inventree/widget/progress.dart"; import "package:inventree/widget/progress.dart";
import "package:inventree/l10.dart";
import "package:flutter/material.dart";
import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/refreshable_state.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
class StockItemTestResultsWidget extends StatefulWidget { class StockItemTestResultsWidget extends StatefulWidget {
@ -31,15 +33,25 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
String getAppBarTitle() => L10().testResults; String getAppBarTitle() => L10().testResults;
@override @override
List<Widget> appBarActions(BuildContext context) { List<Widget> appBarActions(BuildContext context) => [];
return [
IconButton( @override
icon: FaIcon(FontAwesomeIcons.circlePlus), List<SpeedDialChild> actionButtons(BuildContext context) {
onPressed: () { List<SpeedDialChild> actions = [];
addTestResult(context);
if (InvenTreeStockItemTestResult().canCreate) {
actions.add(
SpeedDialChild(
child: FaIcon(FontAwesomeIcons.circlePlus),
label: L10().testResultAdd,
onTap: () {
addTestResult(context);
} }
), )
]; );
}
return actions;
} }
@override @override
@ -153,6 +165,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
for (var item in results) { for (var item in results) {
bool _hasResult = false;
bool _required = false; bool _required = false;
String _test = ""; String _test = "";
bool _result = false; bool _result = false;
@ -167,34 +180,37 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
_result = item.passFailStatus(); _result = item.passFailStatus();
_test = item.testName; _test = item.testName;
_required = item.required; _required = item.required;
_value = item.latestResult()?.value ?? ""; _value = item.latestResult()?.value ?? L10().noResults;
_valueRequired = item.requiresValue; _valueRequired = item.requiresValue;
_attachmentRequired = item.requiresAttachment; _attachmentRequired = item.requiresAttachment;
_notes = item.latestResult()?.notes ?? ""; _notes = item.latestResult()?.notes ?? item.description;
_hasResult = item.latestResult() != null;
} else if (item is InvenTreeStockItemTestResult) { } else if (item is InvenTreeStockItemTestResult) {
_result = item.result; _result = item.result;
_test = item.testName; _test = item.testName;
_required = false; _required = false;
_value = item.value; _value = item.value;
_notes = item.notes; _notes = item.notes;
_hasResult = true;
} }
if (_result == true) { if (!_hasResult) {
_icon = FaIcon(FontAwesomeIcons.circleCheck, _icon = FaIcon(FontAwesomeIcons.circleQuestion, color: Colors.blue);
color: COLOR_SUCCESS, } else if (_result == true) {
); _icon = FaIcon(FontAwesomeIcons.circleCheck, color: COLOR_SUCCESS);
} else if (_result == false) { } else if (_result == false) {
_icon = FaIcon(FontAwesomeIcons.circleXmark, _icon = FaIcon(FontAwesomeIcons.circleXmark, color: COLOR_DANGER);
color: COLOR_DANGER,
);
} }
tiles.add(ListTile( tiles.add(ListTile(
title: Text(_test, style: TextStyle(fontWeight: _required ? FontWeight.bold : FontWeight.normal)), title: Text(_test, style: TextStyle(
fontWeight: _required ? FontWeight.bold : FontWeight.normal,
fontStyle: _hasResult ? FontStyle.normal : FontStyle.italic
)),
subtitle: Text(_notes), subtitle: Text(_notes),
trailing: Text(_value), trailing: Text(_value),
leading: _icon, leading: _icon,
onLongPress: () { onTap: () {
addTestResult( addTestResult(
context, context,
name: _test, name: _test,