mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 05:15:42 +00:00 
			
		
		
		
	Snack bars for barcode actions
This commit is contained in:
		
							
								
								
									
										165
									
								
								lib/barcode.dart
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								lib/barcode.dart
									
									
									
									
									
								
							| @@ -45,27 +45,18 @@ class BarcodeHandler { | |||||||
|     Future<void> onBarcodeUnknown(Map<String, dynamic> data) { |     Future<void> onBarcodeUnknown(Map<String, dynamic> data) { | ||||||
|       // Called when the server does not know about a barcode |       // Called when the server does not know about a barcode | ||||||
|       // Override this function |       // Override this function | ||||||
|       showErrorDialog( |       showSnackIcon( | ||||||
|         "Invalid Barcode", |         I18N.of(OneContext().context).barcodeNoMatch, | ||||||
|         "Barcode does not match any known item", |         success: false, | ||||||
|         error: "Barcode Error", |         icon: FontAwesomeIcons.qrcode | ||||||
|         icon: FontAwesomeIcons.barcode, |  | ||||||
|         onDismissed: () { |  | ||||||
|           _controller.resumeCamera(); |  | ||||||
|         } |  | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Future<void> onBarcodeUnhandled(Map<String, dynamic> data) { |     Future<void> onBarcodeUnhandled(Map<String, dynamic> data) { | ||||||
|       // Called when the server returns an unhandled response |       // Called when the server returns an unhandled response | ||||||
|       showErrorDialog( |       showServerError(I18N.of(OneContext().context).responseUnknown, data.toString()); | ||||||
|           "Response Data", |  | ||||||
|           data.toString(), |       _controller.resumeCamera(); | ||||||
|           error: "Unknown Response", |  | ||||||
|           onDismissed: () { |  | ||||||
|             _controller.resumeCamera(); |  | ||||||
|           } |  | ||||||
|       ); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Future<void> processBarcode(BuildContext context, QRViewController _controller, String barcode, {String url = "barcode/"}) { |     Future<void> processBarcode(BuildContext context, QRViewController _controller, String barcode, {String url = "barcode/"}) { | ||||||
| @@ -93,23 +84,22 @@ class BarcodeHandler { | |||||||
|         final Map<String, dynamic> data = json.decode(response.body); |         final Map<String, dynamic> data = json.decode(response.body); | ||||||
|  |  | ||||||
|         if (data.containsKey('error')) { |         if (data.containsKey('error')) { | ||||||
|  |           _controller.resumeCamera(); | ||||||
|           onBarcodeUnknown(data); |           onBarcodeUnknown(data); | ||||||
|         } else if (data.containsKey('success')) { |         } else if (data.containsKey('success')) { | ||||||
|  |           _controller.resumeCamera(); | ||||||
|           onBarcodeMatched(data); |           onBarcodeMatched(data); | ||||||
|         } else { |         } else { | ||||||
|  |           _controller.resumeCamera(); | ||||||
|           onBarcodeUnhandled(data); |           onBarcodeUnhandled(data); | ||||||
|         } |         } | ||||||
|       }).timeout( |       }).timeout( | ||||||
|           Duration(seconds: 5) |           Duration(seconds: 5) | ||||||
|       ).catchError((error) { |       ).catchError((error) { | ||||||
|  |  | ||||||
|         showErrorDialog( |         showServerError(I18N.of(OneContext().context).error, error.toString()); | ||||||
|           I18N.of(OneContext().context).error, |         _controller.resumeCamera(); | ||||||
|             error.toString(), |  | ||||||
|             onDismissed: () { |  | ||||||
|               _controller.resumeCamera(); |  | ||||||
|             } |  | ||||||
|         ); |  | ||||||
|         return; |         return; | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| @@ -129,30 +119,10 @@ class BarcodeScanHandler extends BarcodeHandler { | |||||||
|   Future<void> onBarcodeUnknown(Map<String, dynamic> data) { |   Future<void> onBarcodeUnknown(Map<String, dynamic> data) { | ||||||
|  |  | ||||||
|     showSnackIcon( |     showSnackIcon( | ||||||
|         "No barcode", |         I18N.of(OneContext().context).barcodeNoMatch, | ||||||
|         icon: FontAwesomeIcons.exclamationCircle, |         icon: FontAwesomeIcons.exclamationCircle, | ||||||
|         actionText: "Details", |         success: false, | ||||||
|         onAction: () { |  | ||||||
|           print("Action!"); |  | ||||||
|         }, |  | ||||||
|         success: true, |  | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     _controller.resumeCamera(); |  | ||||||
|  |  | ||||||
|     /* |  | ||||||
|     showErrorDialog( |  | ||||||
|         _context, |  | ||||||
|         data['error'] ?? '', |  | ||||||
|         data['plugin'] ?? 'No barcode plugin information', |  | ||||||
|         error: "Barcode Error", |  | ||||||
|         icon: FontAwesomeIcons.barcode, |  | ||||||
|         onDismissed: () { |  | ||||||
|           _controller.resumeCamera(); |  | ||||||
|         } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|      */ |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -175,7 +145,10 @@ class BarcodeScanHandler extends BarcodeHandler { | |||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         // TODO - Show an error here! |         showSnackIcon( | ||||||
|  |           I18N.of(OneContext().context).invalidStockLocation, | ||||||
|  |           success: false | ||||||
|  |         ); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|     } else if (data.containsKey('stockitem')) { |     } else if (data.containsKey('stockitem')) { | ||||||
| @@ -188,7 +161,10 @@ class BarcodeScanHandler extends BarcodeHandler { | |||||||
|           Navigator.push(_context, MaterialPageRoute(builder: (context) => StockDetailWidget(item))); |           Navigator.push(_context, MaterialPageRoute(builder: (context) => StockDetailWidget(item))); | ||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         // TODO - Show an error here! |         showSnackIcon( | ||||||
|  |             I18N.of(OneContext().context).invalidStockItem, | ||||||
|  |             success: false | ||||||
|  |         ); | ||||||
|       } |       } | ||||||
|     } else if (data.containsKey('part')) { |     } else if (data.containsKey('part')) { | ||||||
|  |  | ||||||
| @@ -200,20 +176,29 @@ class BarcodeScanHandler extends BarcodeHandler { | |||||||
|           Navigator.push(_context, MaterialPageRoute(builder: (context) => PartDetailWidget(part))); |           Navigator.push(_context, MaterialPageRoute(builder: (context) => PartDetailWidget(part))); | ||||||
|         }); |         }); | ||||||
|       } else { |       } else { | ||||||
|         // TODO - Show an error here! |         showSnackIcon( | ||||||
|  |             I18N.of(OneContext().context).invalidPart, | ||||||
|  |             success: false | ||||||
|  |         ); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       showDialog( |       showSnackIcon( | ||||||
|           context: _context, |         I18N.of(OneContext().context).barcodeUnknown, | ||||||
|           child: SimpleDialog( |         success: false, | ||||||
|             title: Text(I18N.of(_context).unknownResponse), |         onAction: () { | ||||||
|             children: <Widget>[ |           showDialog( | ||||||
|               ListTile( |               context: _context, | ||||||
|                 title: Text("Response data"), |               child: SimpleDialog( | ||||||
|                 subtitle: Text(data.toString()), |                 title: Text(I18N.of(_context).unknownResponse), | ||||||
|  |                 children: <Widget>[ | ||||||
|  |                   ListTile( | ||||||
|  |                     title: Text("Response data"), | ||||||
|  |                     subtitle: Text(data.toString()), | ||||||
|  |                   ) | ||||||
|  |                 ], | ||||||
|               ) |               ) | ||||||
|             ], |           ); | ||||||
|           ) |         } | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -235,12 +220,10 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | |||||||
|   @override |   @override | ||||||
|   Future<void> onBarcodeMatched(Map<String, dynamic> data) { |   Future<void> onBarcodeMatched(Map<String, dynamic> data) { | ||||||
|     // If the barcode is known, we can't asisgn it to the stock item! |     // If the barcode is known, we can't asisgn it to the stock item! | ||||||
|     showErrorDialog( |     showSnackIcon( | ||||||
|       "Barcode in Use", |       I18N.of(OneContext().context).barcodeInUse, | ||||||
|       "Barcode is already known", |       icon: FontAwesomeIcons.qrcode, | ||||||
|       onDismissed: () { |       success: false | ||||||
|         _controller.resumeCamera(); |  | ||||||
|       } |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -249,14 +232,9 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | |||||||
|     // If the barcode is unknown, we *can* assign it to the stock item! |     // If the barcode is unknown, we *can* assign it to the stock item! | ||||||
|  |  | ||||||
|     if (!data.containsKey("hash")) { |     if (!data.containsKey("hash")) { | ||||||
|       showErrorDialog( |       showServerError("Missing data", "Barcode hash data missing from response"); | ||||||
|         "Missing Data", |  | ||||||
|         "Missing hash data from server", |  | ||||||
|         onDismissed: () { |  | ||||||
|           _controller.resumeCamera(); |  | ||||||
|         } |  | ||||||
|       ); |  | ||||||
|     } else { |     } else { | ||||||
|  |  | ||||||
|       // Send the 'hash' code as the UID for the stock item |       // Send the 'hash' code as the UID for the stock item | ||||||
|       item.update( |       item.update( | ||||||
|         _context, |         _context, | ||||||
| @@ -265,22 +243,22 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | |||||||
|         } |         } | ||||||
|       ).then((result) { |       ).then((result) { | ||||||
|         if (result) { |         if (result) { | ||||||
|           showInfoDialog( |  | ||||||
|               _context, |           // Close the barcode scanner | ||||||
|               "Barcode Set", |           _controller.dispose(); | ||||||
|               "Barcode assigned to stock item", |           Navigator.of(_context).pop(); | ||||||
|               onDismissed: () { |  | ||||||
|                 _controller.dispose(); |           showSnackIcon( | ||||||
|                 Navigator.of(_context).pop(); |             I18N.of(OneContext().context).barcodeAssigned, | ||||||
|               } |             success: true, | ||||||
|  |             icon: FontAwesomeIcons.qrcode | ||||||
|           ); |           ); | ||||||
|         } else { |         } else { | ||||||
|           showErrorDialog( |  | ||||||
|             "Server Error", |           showSnackIcon( | ||||||
|             "Could not assign barcode", |               I18N.of(OneContext().context).barcodeNotAssigned, | ||||||
|             onDismissed: () { |               success: false, | ||||||
|               _controller.resumeCamera(); |               icon: FontAwesomeIcons.qrcode | ||||||
|             } |  | ||||||
|           ); |           ); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
| @@ -393,14 +371,23 @@ class StockItemScanIntoLocationHandler extends BarcodeHandler { | |||||||
|       // Transfer stock to specified location |       // Transfer stock to specified location | ||||||
|       item.transferStock(location).then((response) { |       item.transferStock(location).then((response) { | ||||||
|         print("Response: ${response.statusCode}"); |         print("Response: ${response.statusCode}"); | ||||||
|  |  | ||||||
|  |         // Close the scanner | ||||||
|         _controller.dispose(); |         _controller.dispose(); | ||||||
|         Navigator.of(_context).pop(); |         Navigator.of(_context).pop(); | ||||||
|  |  | ||||||
|  |         showSnackIcon( | ||||||
|  |           I18N.of(OneContext().context).barcodeScanIntoLocationSuccess, | ||||||
|  |           success: true, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|       }); |       }); | ||||||
|     } else { |     } else { | ||||||
|       // Display a snack bar with the error |       showSnackIcon( | ||||||
|       OneContext().showSnackBar(builder: (context) => SnackBar( |         I18N.of(OneContext().context).invalidStockLocation, | ||||||
|         content: Text("This was not a stock item!") |         success: false, | ||||||
|       )); |       ); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							 Submodule lib/l10n updated: f1e991199f...0e41299506
									
								
							| @@ -24,8 +24,18 @@ void showSnackIcon(String text, {IconData icon, Function onAction, bool success, | |||||||
|   if (success == true) { |   if (success == true) { | ||||||
|     backgroundColor = Colors.lightGreen; |     backgroundColor = Colors.lightGreen; | ||||||
|  |  | ||||||
|  |     // Select an icon if we do not have an action | ||||||
|  |     if (icon == null && onAction == null) { | ||||||
|  |       icon = FontAwesomeIcons.checkCircle; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   } else if (success == false) { |   } else if (success == false) { | ||||||
|     backgroundColor = Colors.deepOrange; |     backgroundColor = Colors.deepOrange; | ||||||
|  |  | ||||||
|  |     if (icon == null && onAction == null) { | ||||||
|  |       icon = FontAwesomeIcons.exclamationCircle; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SnackBarAction action; |   SnackBarAction action; | ||||||
|   | |||||||
| @@ -245,6 +245,26 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   void _unassignBarcode(BuildContext context) async { | ||||||
|  |  | ||||||
|  |     final bool result = await item.update(context, values: {'uid': ''}); | ||||||
|  |  | ||||||
|  |     if (result) { | ||||||
|  |       showSnackIcon( | ||||||
|  |         I18N.of(context).stockItemUpdateSuccess, | ||||||
|  |         success: true | ||||||
|  |       ); | ||||||
|  |     } else { | ||||||
|  |       showSnackIcon( | ||||||
|  |         I18N.of(context).stockItemUpdateFailure, | ||||||
|  |         success: false, | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     refresh(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   void _transferStock(BuildContext context, InvenTreeStockLocation location) async { |   void _transferStock(BuildContext context, InvenTreeStockLocation location) async { | ||||||
|     Navigator.of(context).pop(); |     Navigator.of(context).pop(); | ||||||
|  |  | ||||||
| @@ -568,7 +588,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|     if (item.uid.isEmpty) { |     if (item.uid.isEmpty) { | ||||||
|       tiles.add( |       tiles.add( | ||||||
|         ListTile( |         ListTile( | ||||||
|           title: Text(I18N.of(context).assignBarcode), |           title: Text(I18N.of(context).barcodeAssign), | ||||||
|           leading: FaIcon(FontAwesomeIcons.barcode), |           leading: FaIcon(FontAwesomeIcons.barcode), | ||||||
|           trailing: FaIcon(FontAwesomeIcons.qrcode), |           trailing: FaIcon(FontAwesomeIcons.qrcode), | ||||||
|           onTap: () { |           onTap: () { | ||||||
| @@ -581,6 +601,16 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|           } |           } | ||||||
|         ) |         ) | ||||||
|       ); |       ); | ||||||
|  |     } else { | ||||||
|  |       tiles.add( | ||||||
|  |         ListTile( | ||||||
|  |           title: Text(I18N.of(context).barcodeUnassign), | ||||||
|  |           leading: FaIcon(FontAwesomeIcons.barcode), | ||||||
|  |           onTap: () { | ||||||
|  |             _unassignBarcode(context); | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return tiles; |     return tiles; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user