mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-30 21:05:42 +00:00 
			
		
		
		
	API forms return the JSON data to the onSuccess function
This commit is contained in:
		| @@ -7,6 +7,7 @@ import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
|  | ||||
| @@ -420,7 +421,7 @@ Map<String, dynamic> extractFields(APIResponse response) { | ||||
|  * @param method is the HTTP method to use to send the form data to the server (e.g. POST / PATCH) | ||||
|  */ | ||||
|  | ||||
| Future<void> launchApiForm(BuildContext context, String title, String url, Map<String, dynamic> fields, {Map<String, dynamic> modelData = const {}, String method = "PATCH", Function? onSuccess, Function? onCancel}) async { | ||||
| Future<void> launchApiForm(BuildContext context, String title, String url, Map<String, dynamic> fields, {Map<String, dynamic> modelData = const {}, String method = "PATCH", Function(Map<String, dynamic>)? onSuccess, Function? onCancel}) async { | ||||
|  | ||||
|   var options = await InvenTreeAPI().options(url); | ||||
|  | ||||
| @@ -503,6 +504,7 @@ Future<void> launchApiForm(BuildContext context, String title, String url, Map<S | ||||
|         title, | ||||
|         url, | ||||
|         formFields, | ||||
|         method, | ||||
|         onSuccess: onSuccess, | ||||
|     )) | ||||
|   ); | ||||
| @@ -517,14 +519,18 @@ class APIFormWidget extends StatefulWidget { | ||||
|   //! API URL | ||||
|   final String url; | ||||
|  | ||||
|   //! API method | ||||
|   final String method; | ||||
|  | ||||
|   final List<APIFormField> fields; | ||||
|  | ||||
|   Function? onSuccess; | ||||
|   Function(Map<String, dynamic>)? onSuccess; | ||||
|  | ||||
|   APIFormWidget( | ||||
|       this.title, | ||||
|       this.url, | ||||
|       this.fields, | ||||
|       this.method, | ||||
|       { | ||||
|         Key? key, | ||||
|         this.onSuccess, | ||||
| @@ -532,7 +538,7 @@ class APIFormWidget extends StatefulWidget { | ||||
|   ) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _APIFormWidgetState createState() => _APIFormWidgetState(title, url, fields, onSuccess); | ||||
|   _APIFormWidgetState createState() => _APIFormWidgetState(title, url, fields, method, onSuccess); | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -545,11 +551,13 @@ class _APIFormWidgetState extends State<APIFormWidget> { | ||||
|  | ||||
|   String url; | ||||
|  | ||||
|   String method; | ||||
|  | ||||
|   List<APIFormField> fields; | ||||
|  | ||||
|   Function? onSuccess; | ||||
|   Function(Map<String, dynamic>)? onSuccess; | ||||
|  | ||||
|   _APIFormWidgetState(this.title, this.url, this.fields, this.onSuccess) : super(); | ||||
|   _APIFormWidgetState(this.title, this.url, this.fields, this.method, this.onSuccess) : super(); | ||||
|  | ||||
|   List<Widget> _buildForm() { | ||||
|  | ||||
| @@ -584,30 +592,42 @@ class _APIFormWidgetState extends State<APIFormWidget> { | ||||
|     return widgets; | ||||
|   } | ||||
|  | ||||
|   Future<APIResponse> _submit(Map<String, String> data) async { | ||||
|  | ||||
|     if (method == "POST") { | ||||
|       return await InvenTreeAPI().post( | ||||
|         url, | ||||
|         body: data | ||||
|       ); | ||||
|     } else { | ||||
|       return await InvenTreeAPI().patch( | ||||
|         url, | ||||
|         body: data, | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   Future<void> _save(BuildContext context) async { | ||||
|  | ||||
|     // Package up the form data | ||||
|     Map<String, String> _data = {}; | ||||
|     Map<String, String> data = {}; | ||||
|  | ||||
|     for (var field in fields) { | ||||
|  | ||||
|       dynamic value = field.value; | ||||
|  | ||||
|       if (value == null) { | ||||
|         _data[field.name] = ""; | ||||
|         data[field.name] = ""; | ||||
|       } else { | ||||
|         _data[field.name] = value.toString(); | ||||
|         data[field.name] = value.toString(); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // TODO: Handle "POST" forms too!! | ||||
|     final response = await InvenTreeAPI().patch( | ||||
|       url, | ||||
|       body: _data, | ||||
|     ); | ||||
|     final response = await _submit(data); | ||||
|  | ||||
|     if (!response.isValid()) { | ||||
|       // TODO: Display an error message! | ||||
|       showServerError(L10().serverError, L10().responseInvalid); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
| @@ -625,7 +645,17 @@ class _APIFormWidgetState extends State<APIFormWidget> { | ||||
|         var successFunc = onSuccess; | ||||
|  | ||||
|         if (successFunc != null) { | ||||
|           successFunc(); | ||||
|  | ||||
|           // Ensure the response is a valid JSON structure | ||||
|           Map<String, dynamic> json = {}; | ||||
|  | ||||
|           if (response.data != null && response.data is Map) { | ||||
|             for (dynamic key in response.data.keys) { | ||||
|               json[key.toString()] = response.data[key]; | ||||
|             } | ||||
|           } | ||||
|  | ||||
|           successFunc(json); | ||||
|         } | ||||
|         return; | ||||
|       case 400: | ||||
|   | ||||
| @@ -72,7 +72,25 @@ class InvenTreeModel { | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   Future<void> editForm(BuildContext context, String title, {Map<String, dynamic> fields=const {}, Function? onSuccess}) async { | ||||
|   Future<void> createForm(BuildContext context, String title, {Map<String, dynamic> fields=const{}, Map<String, dynamic> data=const {}, Function(dynamic)? onSuccess}) async { | ||||
|  | ||||
|     if (fields.isEmpty) { | ||||
|       fields = formFields(); | ||||
|     } | ||||
|  | ||||
|     launchApiForm( | ||||
|       context, | ||||
|       title, | ||||
|       URL, | ||||
|       fields, | ||||
|       modelData: data, | ||||
|       onSuccess: onSuccess, | ||||
|       method: "POST", | ||||
|     ); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   Future<void> editForm(BuildContext context, String title, {Map<String, dynamic> fields=const {}, Function(dynamic)? onSuccess}) async { | ||||
|  | ||||
|     if (fields.isEmpty) { | ||||
|       fields = formFields(); | ||||
| @@ -84,7 +102,8 @@ class InvenTreeModel { | ||||
|       url, | ||||
|       fields, | ||||
|       modelData: jsondata, | ||||
|       onSuccess: onSuccess | ||||
|       onSuccess: onSuccess, | ||||
|       method: "PATCH" | ||||
|     ); | ||||
|  | ||||
|   } | ||||
|   | ||||
| @@ -67,7 +67,13 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     _cat.editForm(context, L10().editCategory, onSuccess: refresh); | ||||
|     _cat.editForm( | ||||
|         context, | ||||
|         L10().editCategory, | ||||
|         onSuccess: (data) async { | ||||
|           refresh(); | ||||
|         } | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   _CategoryDisplayState(this.category); | ||||
| @@ -211,13 +217,26 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
|  | ||||
|     int pk = category?.pk ?? -1; | ||||
|  | ||||
|     launchApiForm( | ||||
|     InvenTreePartCategory().createForm( | ||||
|       context, | ||||
|       L10().categoryCreate, | ||||
|         InvenTreePartCategory().URL, | ||||
|         InvenTreePartCategory().formFields(), | ||||
|         modelData: { | ||||
|       data: { | ||||
|         "parent": (pk > 0) ? pk : null, | ||||
|       }, | ||||
|       onSuccess: (data) async { | ||||
|          | ||||
|         if (data.containsKey("pk")) { | ||||
|           var new_cat = InvenTreePartCategory.fromJson(data); | ||||
|  | ||||
|           Navigator.push( | ||||
|             context, | ||||
|             MaterialPageRoute( | ||||
|               builder: (context) => CategoryDisplayWidget(new_cat) | ||||
|             ) | ||||
|           ); | ||||
|         } else { | ||||
|           refresh(); | ||||
|         } | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -79,7 +79,9 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> { | ||||
|         "currency": {}, | ||||
|       }, | ||||
|       modelData: company.jsondata, | ||||
|       onSuccess: refresh | ||||
|       onSuccess: (data) async { | ||||
|         refresh(); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -94,7 +94,9 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> { | ||||
|         "parent": {}, | ||||
|       }, | ||||
|       modelData: _loc.jsondata, | ||||
|       onSuccess: refresh | ||||
|       onSuccess: (data) async { | ||||
|         refresh(); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -126,7 +126,9 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|           "virtual": {}, | ||||
|         }, | ||||
|         modelData: part.jsondata, | ||||
|         onSuccess: refresh, | ||||
|         onSuccess: (data) async { | ||||
|           refresh(); | ||||
|         }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -56,7 +56,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> { | ||||
|                 } | ||||
|               }, | ||||
|               modelData: part.jsondata, | ||||
|               onSuccess: () async { | ||||
|               onSuccess: (data) async { | ||||
|                 refresh(); | ||||
|               } | ||||
|             ); | ||||
|   | ||||
| @@ -120,7 +120,9 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|         "link": {}, | ||||
|       }, | ||||
|       modelData: item.jsondata, | ||||
|       onSuccess: refresh | ||||
|       onSuccess: (data) async { | ||||
|         refresh(); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|   } | ||||
|   | ||||
| @@ -56,7 +56,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> { | ||||
|                       } | ||||
|                     }, | ||||
|                     modelData: item.jsondata, | ||||
|                     onSuccess: () { | ||||
|                     onSuccess: (data) async { | ||||
|                       refresh(); | ||||
|                     } | ||||
|                 ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user