mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 05:15: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/app_colors.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/widget/dialogs.dart'; | ||||||
| import 'package:inventree/widget/fields.dart'; | import 'package:inventree/widget/fields.dart'; | ||||||
| import 'package:inventree/l10.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) |  * @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); |   var options = await InvenTreeAPI().options(url); | ||||||
|  |  | ||||||
| @@ -503,6 +504,7 @@ Future<void> launchApiForm(BuildContext context, String title, String url, Map<S | |||||||
|         title, |         title, | ||||||
|         url, |         url, | ||||||
|         formFields, |         formFields, | ||||||
|  |         method, | ||||||
|         onSuccess: onSuccess, |         onSuccess: onSuccess, | ||||||
|     )) |     )) | ||||||
|   ); |   ); | ||||||
| @@ -517,14 +519,18 @@ class APIFormWidget extends StatefulWidget { | |||||||
|   //! API URL |   //! API URL | ||||||
|   final String url; |   final String url; | ||||||
|  |  | ||||||
|  |   //! API method | ||||||
|  |   final String method; | ||||||
|  |  | ||||||
|   final List<APIFormField> fields; |   final List<APIFormField> fields; | ||||||
|  |  | ||||||
|   Function? onSuccess; |   Function(Map<String, dynamic>)? onSuccess; | ||||||
|  |  | ||||||
|   APIFormWidget( |   APIFormWidget( | ||||||
|       this.title, |       this.title, | ||||||
|       this.url, |       this.url, | ||||||
|       this.fields, |       this.fields, | ||||||
|  |       this.method, | ||||||
|       { |       { | ||||||
|         Key? key, |         Key? key, | ||||||
|         this.onSuccess, |         this.onSuccess, | ||||||
| @@ -532,7 +538,7 @@ class APIFormWidget extends StatefulWidget { | |||||||
|   ) : super(key: key); |   ) : super(key: key); | ||||||
|  |  | ||||||
|   @override |   @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 url; | ||||||
|  |  | ||||||
|  |   String method; | ||||||
|  |  | ||||||
|   List<APIFormField> fields; |   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() { |   List<Widget> _buildForm() { | ||||||
|  |  | ||||||
| @@ -584,30 +592,42 @@ class _APIFormWidgetState extends State<APIFormWidget> { | |||||||
|     return widgets; |     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 { |   Future<void> _save(BuildContext context) async { | ||||||
|  |  | ||||||
|     // Package up the form data |     // Package up the form data | ||||||
|     Map<String, String> _data = {}; |     Map<String, String> data = {}; | ||||||
|  |  | ||||||
|     for (var field in fields) { |     for (var field in fields) { | ||||||
|  |  | ||||||
|       dynamic value = field.value; |       dynamic value = field.value; | ||||||
|  |  | ||||||
|       if (value == null) { |       if (value == null) { | ||||||
|         _data[field.name] = ""; |         data[field.name] = ""; | ||||||
|       } else { |       } else { | ||||||
|         _data[field.name] = value.toString(); |         data[field.name] = value.toString(); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO: Handle "POST" forms too!! |     final response = await _submit(data); | ||||||
|     final response = await InvenTreeAPI().patch( |  | ||||||
|       url, |  | ||||||
|       body: _data, |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     if (!response.isValid()) { |     if (!response.isValid()) { | ||||||
|       // TODO: Display an error message! |       showServerError(L10().serverError, L10().responseInvalid); | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -625,7 +645,17 @@ class _APIFormWidgetState extends State<APIFormWidget> { | |||||||
|         var successFunc = onSuccess; |         var successFunc = onSuccess; | ||||||
|  |  | ||||||
|         if (successFunc != null) { |         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; |         return; | ||||||
|       case 400: |       case 400: | ||||||
|   | |||||||
| @@ -72,7 +72,25 @@ class InvenTreeModel { | |||||||
|     return {}; |     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) { |     if (fields.isEmpty) { | ||||||
|       fields = formFields(); |       fields = formFields(); | ||||||
| @@ -84,7 +102,8 @@ class InvenTreeModel { | |||||||
|       url, |       url, | ||||||
|       fields, |       fields, | ||||||
|       modelData: jsondata, |       modelData: jsondata, | ||||||
|       onSuccess: onSuccess |       onSuccess: onSuccess, | ||||||
|  |       method: "PATCH" | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -67,7 +67,13 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     _cat.editForm(context, L10().editCategory, onSuccess: refresh); |     _cat.editForm( | ||||||
|  |         context, | ||||||
|  |         L10().editCategory, | ||||||
|  |         onSuccess: (data) async { | ||||||
|  |           refresh(); | ||||||
|  |         } | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _CategoryDisplayState(this.category); |   _CategoryDisplayState(this.category); | ||||||
| @@ -211,13 +217,26 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | |||||||
|  |  | ||||||
|     int pk = category?.pk ?? -1; |     int pk = category?.pk ?? -1; | ||||||
|  |  | ||||||
|     launchApiForm( |     InvenTreePartCategory().createForm( | ||||||
|       context, |       context, | ||||||
|       L10().categoryCreate, |       L10().categoryCreate, | ||||||
|         InvenTreePartCategory().URL, |       data: { | ||||||
|         InvenTreePartCategory().formFields(), |  | ||||||
|         modelData: { |  | ||||||
|         "parent": (pk > 0) ? pk : null, |         "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": {}, |         "currency": {}, | ||||||
|       }, |       }, | ||||||
|       modelData: company.jsondata, |       modelData: company.jsondata, | ||||||
|       onSuccess: refresh |       onSuccess: (data) async { | ||||||
|  |         refresh(); | ||||||
|  |       } | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -94,7 +94,9 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> { | |||||||
|         "parent": {}, |         "parent": {}, | ||||||
|       }, |       }, | ||||||
|       modelData: _loc.jsondata, |       modelData: _loc.jsondata, | ||||||
|       onSuccess: refresh |       onSuccess: (data) async { | ||||||
|  |         refresh(); | ||||||
|  |       } | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -126,7 +126,9 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | |||||||
|           "virtual": {}, |           "virtual": {}, | ||||||
|         }, |         }, | ||||||
|         modelData: part.jsondata, |         modelData: part.jsondata, | ||||||
|         onSuccess: refresh, |         onSuccess: (data) async { | ||||||
|  |           refresh(); | ||||||
|  |         }, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> { | |||||||
|                 } |                 } | ||||||
|               }, |               }, | ||||||
|               modelData: part.jsondata, |               modelData: part.jsondata, | ||||||
|               onSuccess: () async { |               onSuccess: (data) async { | ||||||
|                 refresh(); |                 refresh(); | ||||||
|               } |               } | ||||||
|             ); |             ); | ||||||
|   | |||||||
| @@ -120,7 +120,9 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|         "link": {}, |         "link": {}, | ||||||
|       }, |       }, | ||||||
|       modelData: item.jsondata, |       modelData: item.jsondata, | ||||||
|       onSuccess: refresh |       onSuccess: (data) async { | ||||||
|  |         refresh(); | ||||||
|  |       } | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> { | |||||||
|                       } |                       } | ||||||
|                     }, |                     }, | ||||||
|                     modelData: item.jsondata, |                     modelData: item.jsondata, | ||||||
|                     onSuccess: () { |                     onSuccess: (data) async { | ||||||
|                       refresh(); |                       refresh(); | ||||||
|                     } |                     } | ||||||
|                 ); |                 ); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user