mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-30 21:05:42 +00:00 
			
		
		
		
	* Add action for scanning a stock location into another location * Adds barcode scan handler for new functionality * Handle scanning of stock location * Cleanup * Refactor existing barcode scanning functions - Will require extensive testing and validation * Add entry to release notes * Delete dead code * Improved ordering based on stock quantity * Bug fix for 'adjustStock' function * Improve error responses for barcode scanning * Improve error responses for barcode scanning * Remove old debug statements * Add some extra explanatory texts * Icon change * Fixes for unit tests * Adds extra functionality for user profile manager * Refactor barcode code - do not rely on BuildContext * Adds initial unit testing for barcode scanning - Work on mocking barcode data - Add hooks for testing snackBar and audio files * Linting fixes * More barcode unit tests * Cleanup unit tests for barcode * Remove unused import * Handle HTTPException in API * Improvements for API unit testing * Unit testing for scanning item into location * Add unit test for scanning in items from a location context * Unit test for scanning location into parent location * Improve feedback for barcode scanning events
		
			
				
	
	
		
			248 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import "package:flutter/material.dart";
 | |
| import "package:font_awesome_flutter/font_awesome_flutter.dart";
 | |
| import "package:inventree/helpers.dart";
 | |
| import "package:one_context/one_context.dart";
 | |
| 
 | |
| import "package:inventree/api.dart";
 | |
| import "package:inventree/l10.dart";
 | |
| import "package:inventree/preferences.dart";
 | |
| import "package:inventree/widget/snacks.dart";
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Display a "confirmation" dialog allowing the user to accept or reject an action
 | |
|  */
 | |
| Future<void> confirmationDialog(String title, String text, {IconData icon = FontAwesomeIcons.questionCircle, String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async {
 | |
| 
 | |
|   String _accept = acceptText ?? L10().ok;
 | |
|   String _reject = rejectText ?? L10().cancel;
 | |
| 
 | |
|   OneContext().showDialog(
 | |
|     builder: (BuildContext context) {
 | |
|       return AlertDialog(
 | |
|         title: ListTile(
 | |
|           title: Text(title),
 | |
|           leading: FaIcon(icon),
 | |
|         ),
 | |
|         content: Text(text),
 | |
|         actions: [
 | |
|           TextButton(
 | |
|             child: Text(_reject),
 | |
|             onPressed: () {
 | |
|               // Close this dialog
 | |
|               Navigator.pop(context);
 | |
| 
 | |
|               if (onReject != null) {
 | |
|                 onReject();
 | |
|               }
 | |
|             }
 | |
|           ),
 | |
|           TextButton(
 | |
|             child: Text(_accept),
 | |
|             onPressed: () {
 | |
|               // Close this dialog
 | |
|               Navigator.pop(context);
 | |
| 
 | |
|               if (onAccept != null) {
 | |
|                 onAccept();
 | |
|               }
 | |
|             },
 | |
|           )
 | |
|         ]
 | |
|       );
 | |
|     }
 | |
|   );
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Construct an error dialog showing information to the user
 | |
|  *
 | |
|  * @title = Title to be displayed at the top of the dialog
 | |
|  * @description = Simple string description of error
 | |
|  * @data = Error response (e.g from server)
 | |
|  */
 | |
| Future<void> showErrorDialog(String title, {String description = "", APIResponse? response, IconData icon = FontAwesomeIcons.exclamationCircle, Function? onDismissed}) async {
 | |
| 
 | |
|   List<Widget> children = [];
 | |
| 
 | |
|   if (description.isNotEmpty) {
 | |
|     children.add(
 | |
|       ListTile(
 | |
|         title: Text(description),
 | |
|       )
 | |
|     );
 | |
|   } else if (response != null) {
 | |
|     // Look for extra error information in the provided APIResponse object
 | |
|     switch (response.statusCode) {
 | |
|       case 400:  // Bad request (typically bad input)
 | |
|         if (response.data is Map<String, dynamic>) {
 | |
|           for (String field in response.data.keys) {
 | |
| 
 | |
|             dynamic error = response.data[field];
 | |
| 
 | |
|             if (error is List) {
 | |
|               for (int ii = 0; ii < error.length; ii++) {
 | |
|                 children.add(
 | |
|                   ListTile(
 | |
|                     title: Text(field),
 | |
|                     subtitle: Text(error[ii].toString()),
 | |
|                   )
 | |
|                 );
 | |
|               }
 | |
|             } else {
 | |
|               children.add(
 | |
|                   ListTile(
 | |
|                     title: Text(field),
 | |
|                     subtitle: Text(response.data[field].toString()),
 | |
|                   )
 | |
|               );
 | |
|             }
 | |
|           }
 | |
|         } else {
 | |
|           children.add(
 | |
|             ListTile(
 | |
|               title: Text(L10().responseInvalid),
 | |
|               subtitle: Text(response.data.toString())
 | |
|             )
 | |
|           );
 | |
|         }
 | |
|         break;
 | |
|       default:
 | |
|         // Unhandled server response
 | |
|         children.add(
 | |
|           ListTile(
 | |
|             title: Text(L10().statusCode),
 | |
|             subtitle: Text(response.statusCode.toString()),
 | |
|           )
 | |
|         );
 | |
| 
 | |
|         children.add(
 | |
|           ListTile(
 | |
|             title: Text(L10().responseData),
 | |
|             subtitle: Text(response.data.toString()),
 | |
|           )
 | |
|         );
 | |
| 
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   OneContext().showDialog(
 | |
|     builder: (context) => SimpleDialog(
 | |
|       title: ListTile(
 | |
|         title: Text(title),
 | |
|         leading: FaIcon(icon),
 | |
|       ),
 | |
|       children: children
 | |
|     )
 | |
|   ).then((value) {
 | |
|     if (onDismissed != null) {
 | |
|       onDismissed();
 | |
|     }
 | |
|   });
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Display a message indicating the nature of a server / API error
 | |
|  */
 | |
| Future<void> showServerError(String url, String title, String description) async {
 | |
| 
 | |
|   if (!OneContext.hasContext) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // We ignore error messages for certain URLs
 | |
|   if (url.contains("notifications")) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (title.isEmpty) {
 | |
|     title = L10().serverError;
 | |
|   }
 | |
| 
 | |
|   // Play a sound
 | |
|   final bool tones = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
 | |
| 
 | |
|   if (tones) {
 | |
|     playAudioFile("sounds/server_error.mp3");
 | |
|   }
 | |
| 
 | |
|   showSnackIcon(
 | |
|     title,
 | |
|     success: false,
 | |
|     actionText: L10().details,
 | |
|     onAction: () {
 | |
|       showErrorDialog(
 | |
|           L10().serverError,
 | |
|           description: description,
 | |
|           icon: FontAwesomeIcons.server
 | |
|       );
 | |
|     }
 | |
|   );
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Displays an error indicating that the server returned an unexpected status code
 | |
|  */
 | |
| Future<void> showStatusCodeError(String url, int status) async {
 | |
| 
 | |
|   String msg = L10().responseInvalid;
 | |
|   String extra = "${L10().statusCode}: ${status}";
 | |
| 
 | |
|   switch (status) {
 | |
|     case 400:
 | |
|       msg = L10().response400;
 | |
|       break;
 | |
|     case 401:
 | |
|       msg = L10().response401;
 | |
|       break;
 | |
|     case 403:
 | |
|       msg = L10().response403;
 | |
|       break;
 | |
|     case 404:
 | |
|       msg = L10().response404;
 | |
|       break;
 | |
|     case 405:
 | |
|       msg = L10().response405;
 | |
|       break;
 | |
|     case 429:
 | |
|       msg = L10().response429;
 | |
|       break;
 | |
|     case 500:
 | |
|       msg = L10().response500;
 | |
|       break;
 | |
|     case 501:
 | |
|       msg = L10().response501;
 | |
|       break;
 | |
|     case 502:
 | |
|       msg = L10().response502;
 | |
|       break;
 | |
|     case 503:
 | |
|       msg = L10().response503;
 | |
|       break;
 | |
|     case 504:
 | |
|       msg = L10().response504;
 | |
|       break;
 | |
|     case 505:
 | |
|       msg = L10().response505;
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   showServerError(
 | |
|     url,
 | |
|     msg,
 | |
|     extra,
 | |
|   );
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Displays a message indicating that the server timed out on a certain request
 | |
|  */
 | |
| Future<void> showTimeoutError(String url) async {
 | |
|   await showServerError(url, L10().timeout, L10().noResponse);
 | |
| }
 |