mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 21:35:42 +00:00 
			
		
		
		
	More linting work
This commit is contained in:
		
							
								
								
									
										147
									
								
								lib/api.dart
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								lib/api.dart
									
									
									
									
									
								
							| @@ -1,25 +1,25 @@ | ||||
| import 'dart:async'; | ||||
| import 'dart:convert'; | ||||
| import 'dart:io'; | ||||
| import "dart:async"; | ||||
| import "dart:convert"; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:http/http.dart' as http; | ||||
| import 'package:intl/intl.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:http/http.dart" as http; | ||||
| import "package:intl/intl.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
|  | ||||
| import 'package:open_file/open_file.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:cached_network_image/cached_network_image.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:flutter_cache_manager/flutter_cache_manager.dart'; | ||||
| import "package:open_file/open_file.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:cached_network_image/cached_network_image.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:flutter_cache_manager/flutter_cache_manager.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/user_profile.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:path_provider/path_provider.dart'; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:path_provider/path_provider.dart"; | ||||
|  | ||||
|  | ||||
| /* | ||||
| @@ -158,11 +158,12 @@ class InvenTreeAPI { | ||||
|   String _makeUrl(String url) { | ||||
|  | ||||
|     // Strip leading slash | ||||
|     if (url.startsWith('/')) { | ||||
|     if (url.startsWith("/")) { | ||||
|       url = url.substring(1, url.length); | ||||
|     } | ||||
|  | ||||
|     url = url.replaceAll('//', '/'); | ||||
|     // Prevent double-slash | ||||
|     url = url.replaceAll("//", "/"); | ||||
|  | ||||
|     return baseUrl + url; | ||||
|   } | ||||
| @@ -175,7 +176,7 @@ class InvenTreeAPI { | ||||
|     if (endpoint.startsWith("/api/") || endpoint.startsWith("api/")) { | ||||
|       return _makeUrl(endpoint); | ||||
|     } else { | ||||
|       return _makeUrl("/api/" + endpoint); | ||||
|       return _makeUrl("/api/${endpoint}"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -210,10 +211,10 @@ class InvenTreeAPI { | ||||
|   } | ||||
|  | ||||
|   // Server instance information | ||||
|   String instance = ''; | ||||
|   String instance = ""; | ||||
|  | ||||
|   // Server version information | ||||
|   String _version = ''; | ||||
|   String _version = ""; | ||||
|  | ||||
|   // API version of the connected server | ||||
|   int _apiVersion = 1; | ||||
| @@ -272,8 +273,8 @@ class InvenTreeAPI { | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     if (!address.endsWith('/')) { | ||||
|       address = address + '/'; | ||||
|     if (!address.endsWith("/")) { | ||||
|       address = address + "/"; | ||||
|     } | ||||
|     /* TODO: Better URL validation | ||||
|      * - If not a valid URL, return error | ||||
| @@ -307,11 +308,11 @@ class InvenTreeAPI { | ||||
|     } | ||||
|  | ||||
|     // Record server information | ||||
|     _version = (data["version"] ?? '') as String; | ||||
|     instance = (data['instance'] ?? '') as String; | ||||
|     _version = (data["version"] ?? "") as String; | ||||
|     instance = (data["instance"] ?? "") as String; | ||||
|  | ||||
|     // Default API version is 1 if not provided | ||||
|     _apiVersion = (data['apiVersion'] ?? 1) as int; | ||||
|     _apiVersion = (data["apiVersion"] ?? 1) as int; | ||||
|  | ||||
|     if (_apiVersion < _minApiVersion) { | ||||
|  | ||||
| @@ -388,7 +389,7 @@ class InvenTreeAPI { | ||||
|  | ||||
|     _connected = false; | ||||
|     _connecting = false; | ||||
|     _token = ''; | ||||
|     _token = ""; | ||||
|     profile = null; | ||||
|   } | ||||
|  | ||||
| @@ -435,7 +436,7 @@ class InvenTreeAPI { | ||||
|  | ||||
|     // Next we request the permissions assigned to the current user | ||||
|     // Note: 2021-02-27 this "roles" feature for the API was just introduced. | ||||
|     // Any 'older' version of the server allows any API method for any logged in user! | ||||
|     // Any "older" version of the server allows any API method for any logged in user! | ||||
|     // We will return immediately, but request the user roles in the background | ||||
|  | ||||
|     var response = await get(_URL_GET_ROLES, expectedStatusCode: 200); | ||||
| @@ -446,9 +447,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|     var data = response.asMap(); | ||||
|  | ||||
|     if (data.containsKey('roles')) { | ||||
|     if (data.containsKey("roles")) { | ||||
|       // Save a local copy of the user roles | ||||
|       roles = response.data['roles'] as Map<String, dynamic>; | ||||
|       roles = response.data["roles"] as Map<String, dynamic>; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -456,7 +457,7 @@ class InvenTreeAPI { | ||||
|     /* | ||||
|      * Check if the user has the given role.permission assigned | ||||
|      *e | ||||
|      * e.g. 'part', 'change' | ||||
|      * e.g. "part", "change" | ||||
|      */ | ||||
|  | ||||
|     // If we do not have enough information, assume permission is allowed | ||||
| @@ -489,9 +490,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|     if (request == null) { | ||||
|       // Return an "invalid" APIResponse | ||||
|       return new APIResponse( | ||||
|       return APIResponse( | ||||
|         url: url, | ||||
|         method: 'PATCH', | ||||
|         method: "PATCH", | ||||
|         error: "HttpClientRequest is null" | ||||
|       ); | ||||
|     } | ||||
| @@ -535,7 +536,7 @@ class InvenTreeAPI { | ||||
|  | ||||
|     HttpClientRequest? _request; | ||||
|  | ||||
|     var client = createClient(true); | ||||
|     var client = createClient(allowBadCert: true); | ||||
|  | ||||
|     // Attempt to open a connection to the server | ||||
|     try { | ||||
| @@ -543,8 +544,8 @@ class InvenTreeAPI { | ||||
|  | ||||
|       // Set headers | ||||
|       _request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader()); | ||||
|       _request.headers.set(HttpHeaders.acceptHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.contentTypeHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.acceptHeader, "application/json"); | ||||
|       _request.headers.set(HttpHeaders.contentTypeHeader, "application/json"); | ||||
|       _request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale()); | ||||
|  | ||||
|     } on SocketException catch (error) { | ||||
| @@ -684,9 +685,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|     if (request == null) { | ||||
|       // Return an "invalid" APIResponse | ||||
|       return new APIResponse( | ||||
|       return APIResponse( | ||||
|         url: url, | ||||
|         method: 'OPTIONS' | ||||
|         method: "OPTIONS" | ||||
|       ); | ||||
|     } | ||||
|  | ||||
| @@ -703,9 +704,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|     if (request == null) { | ||||
|       // Return an "invalid" APIResponse | ||||
|       return new APIResponse( | ||||
|       return APIResponse( | ||||
|         url: url, | ||||
|         method: 'POST' | ||||
|         method: "POST" | ||||
|       ); | ||||
|     } | ||||
|  | ||||
| @@ -716,15 +717,13 @@ class InvenTreeAPI { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   HttpClient createClient(bool allowBadCert) { | ||||
|   HttpClient createClient({bool allowBadCert = true}) { | ||||
|  | ||||
|     var client = new HttpClient(); | ||||
|     var client = HttpClient(); | ||||
|  | ||||
|     client.badCertificateCallback = ((X509Certificate cert, String host, int port) { | ||||
|     client.badCertificateCallback = (X509Certificate cert, String host, int port) { | ||||
|       // TODO - Introspection of actual certificate? | ||||
|  | ||||
|       allowBadCert = true; | ||||
|  | ||||
|       if (allowBadCert) { | ||||
|         return true; | ||||
|       } else { | ||||
| @@ -734,7 +733,7 @@ class InvenTreeAPI { | ||||
|         ); | ||||
|         return false; | ||||
|       } | ||||
|     }); | ||||
|     }; | ||||
|  | ||||
|     // Set the connection timeout | ||||
|     client.connectionTimeout = Duration(seconds: 30); | ||||
| @@ -746,7 +745,7 @@ class InvenTreeAPI { | ||||
|    * Initiate a HTTP request to the server | ||||
|    * | ||||
|    * @param url is the API endpoint | ||||
|    * @param method is the HTTP method e.g. 'POST' / 'PATCH' / 'GET' etc; | ||||
|    * @param method is the HTTP method e.g. "POST" / "PATCH" / "GET" etc; | ||||
|    * @param params is the request parameters | ||||
|    */ | ||||
|   Future<HttpClientRequest?> apiRequest(String url, String method, {Map<String, String> urlParams = const {}}) async { | ||||
| @@ -763,7 +762,7 @@ class InvenTreeAPI { | ||||
|     } | ||||
|  | ||||
|     // Remove extraneous character if present | ||||
|     if (_url.endsWith('&')) { | ||||
|     if (_url.endsWith("&")) { | ||||
|       _url = _url.substring(0, _url.length - 1); | ||||
|     } | ||||
|  | ||||
| @@ -781,7 +780,7 @@ class InvenTreeAPI { | ||||
|  | ||||
|     HttpClientRequest? _request; | ||||
|  | ||||
|     var client = createClient(true); | ||||
|     var client = createClient(allowBadCert: true); | ||||
|  | ||||
|     // Attempt to open a connection to the server | ||||
|     try { | ||||
| @@ -789,8 +788,8 @@ class InvenTreeAPI { | ||||
|  | ||||
|       // Set headers | ||||
|       _request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader()); | ||||
|       _request.headers.set(HttpHeaders.acceptHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.contentTypeHeader, 'application/json'); | ||||
|       _request.headers.set(HttpHeaders.acceptHeader, "application/json"); | ||||
|       _request.headers.set(HttpHeaders.contentTypeHeader, "application/json"); | ||||
|       _request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale()); | ||||
|  | ||||
|       return _request; | ||||
| @@ -824,7 +823,7 @@ class InvenTreeAPI { | ||||
|       request.add(encoded_data); | ||||
|     } | ||||
|  | ||||
|     APIResponse response = new APIResponse( | ||||
|     APIResponse response = APIResponse( | ||||
|       method: request.method, | ||||
|       url: request.uri.toString() | ||||
|     ); | ||||
| @@ -837,6 +836,19 @@ class InvenTreeAPI { | ||||
|       // If the server returns a server error code, alert the user | ||||
|       if (_response.statusCode >= 500) { | ||||
|         showStatusCodeError(_response.statusCode); | ||||
|  | ||||
|         sentryReportMessage( | ||||
|             "Server error", | ||||
|             context: { | ||||
|               "url": request.uri.toString(), | ||||
|               "method": request.method, | ||||
|               "statusCode": _response.statusCode.toString(), | ||||
|               "requestHeaders": request.headers.toString(), | ||||
|               "responseHeaders": _response.headers.toString(), | ||||
|               "responseData": response.data.toString(), | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|       } else { | ||||
|         response.data = await responseToJson(_response) ?? {}; | ||||
|  | ||||
| @@ -846,21 +858,6 @@ class InvenTreeAPI { | ||||
|           if (statusCode != _response.statusCode) { | ||||
|             showStatusCodeError(_response.statusCode); | ||||
|           } | ||||
|  | ||||
|           // Report any server errors | ||||
|           if (_response.statusCode >= 500) { | ||||
|             sentryReportMessage( | ||||
|                 "Server error", | ||||
|                 context: { | ||||
|                   "url": request.uri.toString(), | ||||
|                   "method": request.method, | ||||
|                   "statusCode": _response.statusCode.toString(), | ||||
|                   "requestHeaders": request.headers.toString(), | ||||
|                   "responseHeaders": _response.headers.toString(), | ||||
|                   "responseData": response.data.toString(), | ||||
|                 } | ||||
|             ); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
| @@ -930,9 +927,9 @@ class InvenTreeAPI { | ||||
|  | ||||
|     if (request == null) { | ||||
|       // Return an "invalid" APIResponse | ||||
|       return new APIResponse( | ||||
|       return APIResponse( | ||||
|         url: url, | ||||
|         method: 'GET', | ||||
|         method: "GET", | ||||
|         error: "HttpClientRequest is null", | ||||
|       ); | ||||
|     } | ||||
| @@ -945,8 +942,8 @@ class InvenTreeAPI { | ||||
|     var headers = Map<String, String>(); | ||||
|  | ||||
|     headers[HttpHeaders.authorizationHeader] = _authorizationHeader(); | ||||
|     headers[HttpHeaders.acceptHeader] = 'application/json'; | ||||
|     headers[HttpHeaders.contentTypeHeader] = 'application/json'; | ||||
|     headers[HttpHeaders.acceptHeader] = "application/json"; | ||||
|     headers[HttpHeaders.contentTypeHeader] = "application/json"; | ||||
|     headers[HttpHeaders.acceptLanguageHeader] = Intl.getCurrentLocale(); | ||||
|  | ||||
|     return headers; | ||||
| @@ -956,7 +953,7 @@ class InvenTreeAPI { | ||||
|     if (_token.isNotEmpty) { | ||||
|       return "Token $_token"; | ||||
|     } else if (profile != null) { | ||||
|       return "Basic " + base64Encode(utf8.encode('${profile?.username}:${profile?.password}')); | ||||
|       return "Basic " + base64Encode(utf8.encode("${profile?.username}:${profile?.password}")); | ||||
|     } else { | ||||
|       return ""; | ||||
|     } | ||||
|   | ||||
| @@ -1,22 +1,22 @@ | ||||
| import 'dart:ui'; | ||||
| import 'dart:io'; | ||||
| import "dart:ui"; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:dropdown_search/dropdown_search.dart'; | ||||
| import 'package:date_field/date_field.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:dropdown_search/dropdown_search.dart"; | ||||
| import "package:date_field/date_field.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:inventree/widget/fields.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -41,24 +41,24 @@ class APIFormField { | ||||
|   dynamic initial_data; | ||||
|  | ||||
|   // Get the "api_url" associated with a related field | ||||
|   String get api_url => (data["api_url"] ?? '') as String; | ||||
|   String get api_url => (data["api_url"] ?? "") as String; | ||||
|  | ||||
|   // Get the "model" associated with a related field | ||||
|   String get model => (data["model"] ?? '') as String; | ||||
|   String get model => (data["model"] ?? "") as String; | ||||
|  | ||||
|   // Is this field hidden? | ||||
|   bool get hidden => (data['hidden'] ?? false) as bool; | ||||
|   bool get hidden => (data["hidden"] ?? false) as bool; | ||||
|  | ||||
|   // Is this field read only? | ||||
|   bool get readOnly => (data['read_only'] ?? false) as bool; | ||||
|   bool get readOnly => (data["read_only"] ?? false) as bool; | ||||
|  | ||||
|   bool get multiline => (data['multiline'] ?? false) as bool; | ||||
|   bool get multiline => (data["multiline"] ?? false) as bool; | ||||
|  | ||||
|   // Get the "value" as a string (look for "default" if not available) | ||||
|   dynamic get value => (data['value'] ?? data['default']); | ||||
|   dynamic get value => (data["value"] ?? data["default"]); | ||||
|  | ||||
|   // Get the "default" as a string | ||||
|   dynamic get defaultValue => data['default']; | ||||
|   dynamic get defaultValue => data["default"]; | ||||
|  | ||||
|   Map<String, String> get filters { | ||||
|  | ||||
| @@ -96,7 +96,7 @@ class APIFormField { | ||||
|  | ||||
|   // Return the error message associated with this field | ||||
|   List<String> errorMessages() { | ||||
|     List<dynamic> errors = (data['errors'] ?? []) as List<dynamic>; | ||||
|     List<dynamic> errors = (data["errors"] ?? []) as List<dynamic>; | ||||
|  | ||||
|     List<String> messages = []; | ||||
|  | ||||
| @@ -108,15 +108,15 @@ class APIFormField { | ||||
|   } | ||||
|  | ||||
|   // Is this field required? | ||||
|   bool get required => (data['required'] ?? false) as bool; | ||||
|   bool get required => (data["required"] ?? false) as bool; | ||||
|  | ||||
|   String get type => (data['type'] ?? '').toString(); | ||||
|   String get type => (data["type"] ?? "").toString(); | ||||
|  | ||||
|   String get label => (data['label'] ?? '').toString(); | ||||
|   String get label => (data["label"] ?? "").toString(); | ||||
|  | ||||
|   String get helpText => (data['help_text'] ?? '').toString(); | ||||
|   String get helpText => (data["help_text"] ?? "").toString(); | ||||
|  | ||||
|   String get placeholderText => (data['placeholder'] ?? '').toString(); | ||||
|   String get placeholderText => (data["placeholder"] ?? "").toString(); | ||||
|  | ||||
|   List<dynamic> get choices => (data["choices"] ?? []) as List<dynamic>; | ||||
|  | ||||
| @@ -193,13 +193,13 @@ class APIFormField { | ||||
|         labelText: label, | ||||
|         labelStyle: _labelStyle(), | ||||
|       ), | ||||
|       initialValue: DateTime.tryParse((value ?? '') as String), | ||||
|       initialValue: DateTime.tryParse((value ?? "") as String), | ||||
|       autovalidateMode: AutovalidateMode.always, | ||||
|       validator: (e) { | ||||
|         // TODO | ||||
|       }, | ||||
|       onDateSelected: (DateTime dt) { | ||||
|         data['value'] = dt.toString().split(" ").first; | ||||
|         data["value"] = dt.toString().split(" ").first; | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
| @@ -250,7 +250,7 @@ class APIFormField { | ||||
|  | ||||
|     // Check if the current value is within the allowed values | ||||
|     for (var opt in choices) { | ||||
|       if (opt['value'] == value) { | ||||
|       if (opt["value"] == value) { | ||||
|         _initial = opt; | ||||
|         break; | ||||
|       } | ||||
| @@ -267,13 +267,13 @@ class APIFormField { | ||||
|       autoFocusSearchBox: true, | ||||
|       showClearButton: !required, | ||||
|       itemAsString: (dynamic item) { | ||||
|         return (item['display_name'] ?? '') as String; | ||||
|         return (item["display_name"] ?? "") as String; | ||||
|       }, | ||||
|       onSaved: (item) { | ||||
|         if (item == null) { | ||||
|           data['value'] = null; | ||||
|           data["value"] = null; | ||||
|         } else { | ||||
|           data['value'] = item['value']; | ||||
|           data["value"] = item["value"]; | ||||
|         } | ||||
|       } | ||||
|     ); | ||||
| @@ -294,7 +294,7 @@ class APIFormField { | ||||
|       keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true), | ||||
|       validator: (value) { | ||||
|  | ||||
|         double? quantity = double.tryParse(value.toString()) ?? null; | ||||
|         double? quantity = double.tryParse(value.toString()); | ||||
|  | ||||
|         if (quantity == null) { | ||||
|           return L10().numberInvalid; | ||||
| @@ -335,7 +335,7 @@ class APIFormField { | ||||
|  | ||||
|           List<dynamic> results = []; | ||||
|  | ||||
|           for (var result in response.data['results'] ?? []) { | ||||
|           for (var result in response.data["results"] ?? []) { | ||||
|             results.add(result); | ||||
|           } | ||||
|  | ||||
| @@ -371,9 +371,9 @@ class APIFormField { | ||||
|       }, | ||||
|       onSaved: (item) { | ||||
|         if (item != null) { | ||||
|           data['value'] = item['pk'] ?? null; | ||||
|           data["value"] = item["pk"]; | ||||
|         } else { | ||||
|           data['value'] = null; | ||||
|           data["value"] = null; | ||||
|         } | ||||
|       }, | ||||
|       isFilteredOnline: true, | ||||
| @@ -386,7 +386,7 @@ class APIFormField { | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
|         return item['pk'] == selectedItem['pk']; | ||||
|         return item["pk"] == selectedItem["pk"]; | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| @@ -443,7 +443,7 @@ class APIFormField { | ||||
|           ) : null, | ||||
|         ); | ||||
|       case "owner": | ||||
|         String name = (item["name"] ?? '') as String; | ||||
|         String name = (item["name"] ?? "") as String; | ||||
|         bool isGroup = (item["label"] ?? "") == "group"; | ||||
|         return ListTile( | ||||
|           title: Text(name), | ||||
| @@ -478,7 +478,7 @@ class APIFormField { | ||||
|       readOnly: readOnly, | ||||
|       maxLines: multiline ? null : 1, | ||||
|       expands: false, | ||||
|       initialValue: (value ?? '') as String, | ||||
|       initialValue: (value ?? "") as String, | ||||
|       onSaved: (val) { | ||||
|         data["value"] = val; | ||||
|       }, | ||||
| @@ -500,7 +500,7 @@ class APIFormField { | ||||
|       helperStyle: _helperStyle(), | ||||
|       initial: value as bool, | ||||
|       onSaved: (val) { | ||||
|         data['value'] = val; | ||||
|         data["value"] = val; | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| @@ -631,7 +631,7 @@ Future<void> launchApiForm(BuildContext context, String title, String url, Map<S | ||||
|       dynamic value = modelData[key]; | ||||
|  | ||||
|       if (availableFields.containsKey(key)) { | ||||
|         availableFields[key]['value'] = value; | ||||
|         availableFields[key]["value"] = value; | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @@ -874,7 +874,7 @@ class _APIFormWidgetState extends State<APIFormWidget> { | ||||
|  | ||||
|         // Update field errors | ||||
|         for (var field in fields) { | ||||
|           field.data['errors'] = response.data[field.name]; | ||||
|           field.data["errors"] = response.data[field.name]; | ||||
|         } | ||||
|         break; | ||||
|       // TODO: Other status codes? | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
|  | ||||
|  | ||||
| import 'dart:ui'; | ||||
| import "dart:ui"; | ||||
|  | ||||
| const Color COLOR_GRAY = Color.fromRGBO(50, 50, 50, 1); | ||||
| const Color COLOR_GRAY_LIGHT = Color.fromRGBO(150, 150, 150, 1); | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
|  * Class for managing app-level configuration options | ||||
|  */ | ||||
|  | ||||
| import 'package:sembast/sembast.dart'; | ||||
| import 'package:inventree/preferences.dart'; | ||||
| import "package:sembast/sembast.dart"; | ||||
| import "package:inventree/preferences.dart"; | ||||
|  | ||||
| class InvenTreeSettingsManager { | ||||
|  | ||||
|   | ||||
| @@ -1,26 +1,26 @@ | ||||
| import 'package:inventree/app_settings.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:audioplayers/audioplayers.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:qr_code_scanner/qr_code_scanner.dart'; | ||||
| import "package:inventree/app_settings.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:audioplayers/audioplayers.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:one_context/one_context.dart"; | ||||
|  | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:qr_code_scanner/qr_code_scanner.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/location_display.dart'; | ||||
| import 'package:inventree/widget/part_detail.dart'; | ||||
| import 'package:inventree/widget/stock_detail.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| import 'dart:io'; | ||||
| import "package:inventree/widget/location_display.dart"; | ||||
| import "package:inventree/widget/part_detail.dart"; | ||||
| import "package:inventree/widget/stock_detail.dart"; | ||||
|  | ||||
|  | ||||
| class BarcodeHandler { | ||||
| @@ -38,7 +38,7 @@ class BarcodeHandler { | ||||
|  | ||||
|     QRViewController? _controller; | ||||
|  | ||||
|     void successTone() async { | ||||
|     Future<void> successTone() async { | ||||
|  | ||||
|       final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; | ||||
|  | ||||
| @@ -48,7 +48,7 @@ class BarcodeHandler { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     void failureTone() async { | ||||
|     Future <void> failureTone() async { | ||||
|  | ||||
|       final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; | ||||
|  | ||||
| @@ -120,9 +120,9 @@ class BarcodeHandler { | ||||
|               "errorDetail": response.errorDetail, | ||||
|             } | ||||
|         ); | ||||
|       } else if (data.containsKey('error')) { | ||||
|       } else if (data.containsKey("error")) { | ||||
|         onBarcodeUnknown(context, data); | ||||
|       } else if (data.containsKey('success')) { | ||||
|       } else if (data.containsKey("success")) { | ||||
|         onBarcodeMatched(context, data); | ||||
|       } else { | ||||
|         onBarcodeUnhandled(context, data); | ||||
| @@ -158,9 +158,9 @@ class BarcodeScanHandler extends BarcodeHandler { | ||||
|     int pk = -1; | ||||
|  | ||||
|     // A stocklocation has been passed? | ||||
|     if (data.containsKey('stocklocation')) { | ||||
|     if (data.containsKey("stocklocation")) { | ||||
|  | ||||
|       pk = (data['stocklocation']?['pk'] ?? -1) as int; | ||||
|       pk = (data["stocklocation"]?["pk"] ?? -1) as int; | ||||
|  | ||||
|       if (pk > 0) { | ||||
|  | ||||
| @@ -182,9 +182,9 @@ class BarcodeScanHandler extends BarcodeHandler { | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|     } else if (data.containsKey('stockitem')) { | ||||
|     } else if (data.containsKey("stockitem")) { | ||||
|  | ||||
|       pk = (data['stockitem']?['pk'] ?? -1) as int; | ||||
|       pk = (data["stockitem"]?["pk"] ?? -1) as int; | ||||
|  | ||||
|       if (pk > 0) { | ||||
|  | ||||
| @@ -208,9 +208,9 @@ class BarcodeScanHandler extends BarcodeHandler { | ||||
|             success: false | ||||
|         ); | ||||
|       } | ||||
|     } else if (data.containsKey('part')) { | ||||
|     } else if (data.containsKey("part")) { | ||||
|  | ||||
|       pk = (data['part']?['pk'] ?? -1) as int; | ||||
|       pk = (data["part"]?["pk"] ?? -1) as int; | ||||
|  | ||||
|       if (pk > 0) { | ||||
|  | ||||
| @@ -278,7 +278,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | ||||
|  | ||||
|     failureTone(); | ||||
|  | ||||
|     // If the barcode is known, we can't assign it to the stock item! | ||||
|     // If the barcode is known, we can"t assign it to the stock item! | ||||
|     showSnackIcon( | ||||
|       L10().barcodeInUse, | ||||
|       icon: FontAwesomeIcons.qrcode, | ||||
| @@ -296,7 +296,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { | ||||
|           L10().barcodeMissingHash, | ||||
|       ); | ||||
|     } else { | ||||
|       String hash = (data['hash'] ?? '') as String; | ||||
|       String hash = (data["hash"] ?? "") as String; | ||||
|  | ||||
|       if (hash.isNotEmpty) { | ||||
|         item.update( | ||||
| @@ -343,10 +343,10 @@ class StockItemScanIntoLocationHandler extends BarcodeHandler { | ||||
|  | ||||
|   @override | ||||
|   Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async { | ||||
|     // If the barcode points to a 'stocklocation', great! | ||||
|     if (data.containsKey('stocklocation')) { | ||||
|     // If the barcode points to a "stocklocation", great! | ||||
|     if (data.containsKey("stocklocation")) { | ||||
|       // Extract location information | ||||
|       int location = (data['stocklocation']['pk'] ?? -1) as int; | ||||
|       int location = (data["stocklocation"]["pk"] ?? -1) as int; | ||||
|  | ||||
|       if (location == -1) { | ||||
|         showSnackIcon( | ||||
| @@ -408,11 +408,11 @@ class StockLocationScanInItemsHandler extends BarcodeHandler { | ||||
|   Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async { | ||||
|  | ||||
|     // Returned barcode must match a stock item | ||||
|     if (data.containsKey('stockitem')) { | ||||
|     if (data.containsKey("stockitem")) { | ||||
|  | ||||
|       int item_id = data['stockitem']['pk'] as int; | ||||
|       int item_id = data["stockitem"]["pk"] as int; | ||||
|  | ||||
|       final InvenTreeStockItem? item = await InvenTreeStockItem().get(item_id) as InvenTreeStockItem; | ||||
|       final InvenTreeStockItem? item = await InvenTreeStockItem().get(item_id) as InvenTreeStockItem?; | ||||
|  | ||||
|       if (item == null) { | ||||
|  | ||||
| @@ -468,7 +468,7 @@ class InvenTreeQRView extends StatefulWidget { | ||||
|  | ||||
|   final BarcodeHandler _handler; | ||||
|  | ||||
|   InvenTreeQRView(this._handler, {Key? key}) : super(key: key); | ||||
|   const InvenTreeQRView(this._handler, {Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   State<StatefulWidget> createState() => _QRViewState(_handler); | ||||
| @@ -477,7 +477,7 @@ class InvenTreeQRView extends StatefulWidget { | ||||
|  | ||||
| class _QRViewState extends State<InvenTreeQRView> { | ||||
|  | ||||
|   final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); | ||||
|   final GlobalKey qrKey = GlobalKey(debugLabel: "QR"); | ||||
|  | ||||
|   QRViewController? _controller; | ||||
|  | ||||
|   | ||||
| @@ -12,11 +12,9 @@ import 'package:flutter/material.dart'; | ||||
| class S implements WidgetsLocalizations { | ||||
|   const S(); | ||||
|  | ||||
|   static const GeneratedLocalizationsDelegate delegate = | ||||
|       const GeneratedLocalizationsDelegate(); | ||||
|   static const GeneratedLocalizationsDelegate delegate = GeneratedLocalizationsDelegate(); | ||||
|  | ||||
|   static S of(BuildContext context) => | ||||
|       Localizations.of<S>(context, WidgetsLocalizations); | ||||
|   static S of(BuildContext context) => Localizations.of<S>(context, WidgetsLocalizations); | ||||
|  | ||||
|   @override | ||||
|   TextDirection get textDirection => TextDirection.ltr; | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import 'package:inventree/api.dart'; | ||||
|  | ||||
| import 'model.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
|  | ||||
|  | ||||
| /* | ||||
| @@ -9,6 +8,8 @@ import 'model.dart'; | ||||
|  | ||||
| class InvenTreeCompany extends InvenTreeModel { | ||||
|  | ||||
|   InvenTreeCompany() : super(); | ||||
|  | ||||
|   @override | ||||
|   String get URL => "company/"; | ||||
|  | ||||
| @@ -25,23 +26,21 @@ class InvenTreeCompany extends InvenTreeModel { | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   InvenTreeCompany() : super(); | ||||
|   String get image => (jsondata["image"] ?? jsondata["thumbnail"] ?? InvenTreeAPI.staticImage) as String; | ||||
|  | ||||
|   String get image => (jsondata['image'] ?? jsondata['thumbnail'] ?? InvenTreeAPI.staticImage) as String; | ||||
|   String get thumbnail => (jsondata["thumbnail"] ?? jsondata["image"] ?? InvenTreeAPI.staticThumb) as String; | ||||
|  | ||||
|   String get thumbnail => (jsondata['thumbnail'] ?? jsondata['image'] ?? InvenTreeAPI.staticThumb) as String; | ||||
|   String get website => (jsondata["website"] ?? "") as String; | ||||
|  | ||||
|   String get website => (jsondata['website'] ?? '') as String; | ||||
|   String get phone => (jsondata["phone"] ?? "") as String; | ||||
|  | ||||
|   String get phone => (jsondata['phone'] ?? '') as String; | ||||
|   String get email => (jsondata["email"] ?? "") as String; | ||||
|  | ||||
|   String get email => (jsondata['email'] ?? '') as String; | ||||
|   bool get isSupplier => (jsondata["is_supplier"] ?? false) as bool; | ||||
|  | ||||
|   bool get isSupplier => (jsondata['is_supplier'] ?? false) as bool; | ||||
|   bool get isManufacturer => (jsondata["is_manufacturer"] ?? false)  as bool; | ||||
|  | ||||
|   bool get isManufacturer => (jsondata['is_manufacturer'] ?? false)  as bool; | ||||
|  | ||||
|   bool get isCustomer => (jsondata['is_customer'] ?? false) as bool; | ||||
|   bool get isCustomer => (jsondata["is_customer"] ?? false) as bool; | ||||
|  | ||||
|   InvenTreeCompany.fromJson(Map<String, dynamic> json) : super.fromJson(json); | ||||
|  | ||||
| @@ -83,29 +82,29 @@ class InvenTreeSupplierPart extends InvenTreeModel { | ||||
|  | ||||
|   InvenTreeSupplierPart.fromJson(Map<String, dynamic> json) : super.fromJson(json); | ||||
|  | ||||
|   int get manufacturerId => (jsondata['manufacturer'] ?? -1) as int; | ||||
|   int get manufacturerId => (jsondata["manufacturer"] ?? -1) as int; | ||||
|  | ||||
|   String get manufacturerName => (jsondata['manufacturer_detail']['name'] ?? '') as String; | ||||
|   String get manufacturerName => (jsondata["manufacturer_detail"]["name"] ?? "") as String; | ||||
|  | ||||
|   String get manufacturerImage => (jsondata['manufacturer_detail']['image'] ?? jsondata['manufacturer_detail']['thumbnail'] ?? InvenTreeAPI.staticThumb) as String; | ||||
|   String get manufacturerImage => (jsondata["manufacturer_detail"]["image"] ?? jsondata["manufacturer_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String; | ||||
|  | ||||
|   int get manufacturerPartId => (jsondata['manufacturer_part'] ?? -1) as int; | ||||
|   int get manufacturerPartId => (jsondata["manufacturer_part"] ?? -1) as int; | ||||
|  | ||||
|   int get supplierId => (jsondata['supplier'] ?? -1) as int; | ||||
|   int get supplierId => (jsondata["supplier"] ?? -1) as int; | ||||
|  | ||||
|   String get supplierName => (jsondata['supplier_detail']['name'] ?? '') as String; | ||||
|   String get supplierName => (jsondata["supplier_detail"]["name"] ?? "") as String; | ||||
|  | ||||
|   String get supplierImage => (jsondata['supplier_detail']['image'] ?? jsondata['supplier_detail']['thumbnail'] ?? InvenTreeAPI.staticThumb) as String; | ||||
|   String get supplierImage => (jsondata["supplier_detail"]["image"] ?? jsondata["supplier_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String; | ||||
|  | ||||
|   String get SKU => (jsondata['SKU'] ?? '') as String; | ||||
|   String get SKU => (jsondata["SKU"] ?? "") as String; | ||||
|  | ||||
|   String get MPN => (jsondata['MPN'] ?? '') as String; | ||||
|   String get MPN => (jsondata["MPN"] ?? "") as String; | ||||
|  | ||||
|   int get partId => (jsondata['part'] ?? -1) as int; | ||||
|   int get partId => (jsondata["part"] ?? -1) as int; | ||||
|  | ||||
|   String get partImage => (jsondata["part_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String; | ||||
|  | ||||
|   String get partName => (jsondata["part_detail"]["full_name"] ?? '') as String; | ||||
|   String get partName => (jsondata["part_detail"]["full_name"] ?? "") as String; | ||||
|  | ||||
|   @override | ||||
|   InvenTreeModel createFromJson(Map<String, dynamic> json) { | ||||
| @@ -132,11 +131,11 @@ class InvenTreeManufacturerPart extends InvenTreeModel { | ||||
|  | ||||
|   InvenTreeManufacturerPart.fromJson(Map<String, dynamic> json) : super.fromJson(json); | ||||
|  | ||||
|   int get partId => (jsondata['part'] ?? -1) as int; | ||||
|   int get partId => (jsondata["part"] ?? -1) as int; | ||||
|  | ||||
|   int get manufacturerId => (jsondata['manufacturer'] ?? -1) as int; | ||||
|   int get manufacturerId => (jsondata["manufacturer"] ?? -1) as int; | ||||
|  | ||||
|   String get MPN => (jsondata['MPN'] ?? '') as String; | ||||
|   String get MPN => (jsondata["MPN"] ?? "") as String; | ||||
|  | ||||
|   @override | ||||
|   InvenTreeModel createFromJson(Map<String, dynamic> json) { | ||||
|   | ||||
| @@ -1,18 +1,17 @@ | ||||
| import 'dart:async'; | ||||
| import 'dart:io'; | ||||
| import "dart:async"; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:url_launcher/url_launcher.dart"; | ||||
|  | ||||
| import 'package:path/path.dart' as path; | ||||
| import 'package:http/http.dart' as http; | ||||
| import "package:path/path.dart" as path; | ||||
|  | ||||
| import '../l10.dart'; | ||||
| import '../api_form.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/api_form.dart"; | ||||
|  | ||||
|  | ||||
| // Paginated response object | ||||
| @@ -129,21 +128,21 @@ class InvenTreeModel { | ||||
|  | ||||
|   } | ||||
|  | ||||
|   int get pk => (jsondata['pk'] ?? -1) as int; | ||||
|   int get pk => (jsondata["pk"] ?? -1) as int; | ||||
|  | ||||
|   // Some common accessors | ||||
|   String get name => (jsondata['name'] ?? '') as String; | ||||
|   String get name => (jsondata["name"] ?? "") as String; | ||||
|  | ||||
|   String get description => (jsondata['description'] ?? '') as String; | ||||
|   String get description => (jsondata["description"] ?? "") as String; | ||||
|  | ||||
|   String get notes => (jsondata['notes'] ?? '') as String; | ||||
|   String get notes => (jsondata["notes"] ?? "") as String; | ||||
|  | ||||
|   int get parentId => (jsondata['parent'] ?? -1) as int; | ||||
|   int get parentId => (jsondata["parent"] ?? -1) as int; | ||||
|  | ||||
|   // Legacy API provided external link as "URL", while newer API uses "link" | ||||
|   String get link => (jsondata['link'] ?? jsondata['URL'] ?? '') as String; | ||||
|   String get link => (jsondata["link"] ?? jsondata["URL"] ?? "") as String; | ||||
|  | ||||
|   void goToInvenTreePage() async { | ||||
|   Future <void> goToInvenTreePage() async { | ||||
|  | ||||
|     if (await canLaunch(webUrl)) { | ||||
|       await launch(webUrl); | ||||
| @@ -152,7 +151,7 @@ class InvenTreeModel { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void openLink() async { | ||||
|   Future <void> openLink() async { | ||||
|  | ||||
|     if (link.isNotEmpty) { | ||||
|  | ||||
| @@ -162,7 +161,7 @@ class InvenTreeModel { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String get keywords => (jsondata['keywords'] ?? '') as String; | ||||
|   String get keywords => (jsondata["keywords"] ?? "") as String; | ||||
|  | ||||
|   // Create a new object from JSON data (not a constructor!) | ||||
|   InvenTreeModel createFromJson(Map<String, dynamic> json) { | ||||
| @@ -198,7 +197,7 @@ class InvenTreeModel { | ||||
|  | ||||
|     var response = await api.get(url, params: defaultGetFilters(), expectedStatusCode: 200); | ||||
|  | ||||
|     if (!response.isValid() || response.data == null || !(response.data is Map)) { | ||||
|     if (!response.isValid() || response.data == null || (response.data is! Map)) { | ||||
|  | ||||
|       // Report error | ||||
|       if (response.statusCode > 0) { | ||||
| @@ -267,12 +266,12 @@ class InvenTreeModel { | ||||
|  | ||||
|     // Override any default values | ||||
|     for (String key in filters.keys) { | ||||
|       params[key] = filters[key] ?? ''; | ||||
|       params[key] = filters[key] ?? ""; | ||||
|     } | ||||
|  | ||||
|     var response = await api.get(url, params: params); | ||||
|  | ||||
|     if (!response.isValid() || response.data == null || !(response.data is Map)) { | ||||
|     if (!response.isValid() || response.data == null || response.data is! Map) { | ||||
|  | ||||
|       if (response.statusCode > 0) { | ||||
|         await sentryReportMessage( | ||||
| @@ -302,18 +301,18 @@ class InvenTreeModel { | ||||
|  | ||||
|   Future<InvenTreeModel?> create(Map<String, dynamic> data) async { | ||||
|  | ||||
|     if (data.containsKey('pk')) { | ||||
|       data.remove('pk'); | ||||
|     if (data.containsKey("pk")) { | ||||
|       data.remove("pk"); | ||||
|     } | ||||
|  | ||||
|     if (data.containsKey('id')) { | ||||
|       data.remove('id'); | ||||
|     if (data.containsKey("id")) { | ||||
|       data.remove("id"); | ||||
|     } | ||||
|  | ||||
|     var response = await api.post(URL, body: data); | ||||
|  | ||||
|     // Invalid response returned from server | ||||
|     if (!response.isValid() || response.data == null || !(response.data is Map)) { | ||||
|     if (!response.isValid() || response.data == null || response.data is! Map) { | ||||
|  | ||||
|       if (response.statusCode > 0) { | ||||
|         await sentryReportMessage( | ||||
| @@ -345,7 +344,7 @@ class InvenTreeModel { | ||||
|     var params = defaultListFilters(); | ||||
|  | ||||
|     for (String key in filters.keys) { | ||||
|       params[key] = filters[key] ?? ''; | ||||
|       params[key] = filters[key] ?? ""; | ||||
|     } | ||||
|  | ||||
|     params["limit"] = "${limit}"; | ||||
| @@ -384,7 +383,7 @@ class InvenTreeModel { | ||||
|     var params = defaultListFilters(); | ||||
|  | ||||
|     for (String key in filters.keys) { | ||||
|       params[key] = filters[key] ?? ''; | ||||
|       params[key] = filters[key] ?? ""; | ||||
|     } | ||||
|  | ||||
|     var response = await api.get(URL, params: params); | ||||
| @@ -403,8 +402,8 @@ class InvenTreeModel { | ||||
|     } else if (response.isMap()) { | ||||
|       var mData = response.asMap(); | ||||
|  | ||||
|       if (mData.containsKey('results')) { | ||||
|         data = (response.data['results'] ?? []) as List<dynamic>; | ||||
|       if (mData.containsKey("results")) { | ||||
|         data = (response.data["results"] ?? []) as List<dynamic>; | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @@ -423,9 +422,9 @@ class InvenTreeModel { | ||||
|   // Provide a listing of objects at the endpoint | ||||
|   // TODO - Static function which returns a list of objects (of this class) | ||||
|  | ||||
|   // TODO - Define a 'delete' function | ||||
|   // TODO - Define a "delete" function | ||||
|  | ||||
|   // TODO - Define a 'save' / 'update' function | ||||
|   // TODO - Define a "save" / "update" function | ||||
|  | ||||
|   // Override this function for each sub-class | ||||
|   bool matchAgainstString(String filter) { | ||||
| @@ -462,7 +461,7 @@ class InvenTreeAttachment extends InvenTreeModel { | ||||
|  | ||||
|   InvenTreeAttachment() : super(); | ||||
|  | ||||
|   String get attachment => (jsondata["attachment"] ?? '') as String; | ||||
|   String get attachment => (jsondata["attachment"] ?? "") as String; | ||||
|  | ||||
|   // Return the filename of the attachment | ||||
|   String get filename { | ||||
| @@ -500,11 +499,11 @@ class InvenTreeAttachment extends InvenTreeModel { | ||||
|     return FontAwesomeIcons.fileAlt; | ||||
|   } | ||||
|  | ||||
|   String get comment => (jsondata["comment"] ?? '') as String; | ||||
|   String get comment => (jsondata["comment"] ?? "") as String; | ||||
|  | ||||
|   DateTime? get uploadDate { | ||||
|     if (jsondata.containsKey("upload_date")) { | ||||
|       return DateTime.tryParse((jsondata["upload_date"] ?? '') as String); | ||||
|       return DateTime.tryParse((jsondata["upload_date"] ?? "") as String); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
| @@ -517,8 +516,8 @@ class InvenTreeAttachment extends InvenTreeModel { | ||||
|     final APIResponse response = await InvenTreeAPI().uploadFile( | ||||
|         URL, | ||||
|         attachment, | ||||
|         method: 'POST', | ||||
|         name: 'attachment', | ||||
|         method: "POST", | ||||
|         name: "attachment", | ||||
|         fields: fields | ||||
|     ); | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'model.dart'; | ||||
| import 'dart:io'; | ||||
| import 'package:http/http.dart' as http; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import "model.dart"; | ||||
|  | ||||
| class InvenTreePartCategory extends InvenTreeModel { | ||||
|  | ||||
| @@ -33,7 +33,7 @@ class InvenTreePartCategory extends InvenTreeModel { | ||||
|     return filters; | ||||
|   } | ||||
|  | ||||
|   String get pathstring => (jsondata['pathstring'] ?? '') as String; | ||||
|   String get pathstring => (jsondata["pathstring"] ?? "") as String; | ||||
|  | ||||
|   String get parentpathstring { | ||||
|     // TODO - Drive the refactor tractor through this | ||||
| @@ -52,7 +52,7 @@ class InvenTreePartCategory extends InvenTreeModel { | ||||
|     return p; | ||||
|   } | ||||
|  | ||||
|   int get partcount => (jsondata['parts'] ?? 0) as int; | ||||
|   int get partcount => (jsondata["parts"] ?? 0) as int; | ||||
|  | ||||
|   InvenTreePartCategory() : super(); | ||||
|  | ||||
| @@ -74,17 +74,15 @@ class InvenTreePartTestTemplate extends InvenTreeModel { | ||||
|   @override | ||||
|   String get URL => "part/test-template/"; | ||||
|  | ||||
|   String get key => (jsondata['key'] ?? '') as String; | ||||
|   String get key => (jsondata["key"] ?? "") as String; | ||||
|  | ||||
|   String get testName => (jsondata['test_name'] ?? '') as String; | ||||
|   String get testName => (jsondata["test_name"] ?? "") as String; | ||||
|  | ||||
|   String get description => (jsondata['description'] ?? '') as String; | ||||
|   bool get required => (jsondata["required"] ?? false) as bool; | ||||
|  | ||||
|   bool get required => (jsondata['required'] ?? false) as bool; | ||||
|   bool get requiresValue => (jsondata["requires_value"] ?? false) as bool; | ||||
|  | ||||
|   bool get requiresValue => (jsondata['requires_value'] ?? false) as bool; | ||||
|  | ||||
|   bool get requiresAttachment => (jsondata['requires_attachment'] ?? false) as bool; | ||||
|   bool get requiresAttachment => (jsondata["requires_attachment"] ?? false) as bool; | ||||
|  | ||||
|   InvenTreePartTestTemplate() : super(); | ||||
|  | ||||
| @@ -195,7 +193,7 @@ class InvenTreePart extends InvenTreeModel { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   int get supplierCount => (jsondata['suppliers'] ?? 0) as int; | ||||
|   int get supplierCount => (jsondata["suppliers"] ?? 0) as int; | ||||
|  | ||||
|   // Request supplier parts for this part | ||||
|   Future<List<InvenTreeSupplierPart>> getSupplierParts() async { | ||||
| @@ -242,7 +240,7 @@ class InvenTreePart extends InvenTreeModel { | ||||
|   } | ||||
|  | ||||
|     // Get the number of stock on order for this Part | ||||
|     double get onOrder => double.tryParse(jsondata['ordering'].toString()) ?? 0; | ||||
|     double get onOrder => double.tryParse(jsondata["ordering"].toString()) ?? 0; | ||||
|  | ||||
|     String get onOrderString { | ||||
|  | ||||
| @@ -254,7 +252,7 @@ class InvenTreePart extends InvenTreeModel { | ||||
|     } | ||||
|  | ||||
|     // Get the stock count for this Part | ||||
|     double get inStock => double.tryParse(jsondata['in_stock'].toString()) ?? 0; | ||||
|     double get inStock => double.tryParse(jsondata["in_stock"].toString()) ?? 0; | ||||
|  | ||||
|     String get inStockString { | ||||
|  | ||||
| @@ -271,69 +269,69 @@ class InvenTreePart extends InvenTreeModel { | ||||
|       return q; | ||||
|     } | ||||
|  | ||||
|     String get units => (jsondata["units"] as String) ?? ""; | ||||
|     String get units => (jsondata["units"] ?? "") as String; | ||||
|  | ||||
|     // Get the number of units being build for this Part | ||||
|     double get building => double.tryParse(jsondata['building'].toString()) ?? 0; | ||||
|     double get building => double.tryParse(jsondata["building"].toString()) ?? 0; | ||||
|  | ||||
|     // Get the number of BOM items in this Part (if it is an assembly) | ||||
|     int get bomItemCount => (jsondata['bom_items'] ?? 0) as int; | ||||
|     int get bomItemCount => (jsondata["bom_items"] ?? 0) as int; | ||||
|  | ||||
|     // Get the number of BOMs this Part is used in (if it is a component) | ||||
|     int get usedInCount => (jsondata['used_in'] ?? 0) as int; | ||||
|     int get usedInCount => (jsondata["used_in"] ?? 0) as int; | ||||
|  | ||||
|     bool get isAssembly => (jsondata['assembly'] ?? false) as bool; | ||||
|     bool get isAssembly => (jsondata["assembly"] ?? false) as bool; | ||||
|  | ||||
|     bool get isComponent => (jsondata['component'] ?? false) as bool; | ||||
|     bool get isComponent => (jsondata["component"] ?? false) as bool; | ||||
|  | ||||
|     bool get isPurchaseable => (jsondata['purchaseable'] ?? false) as bool; | ||||
|     bool get isPurchaseable => (jsondata["purchaseable"] ?? false) as bool; | ||||
|  | ||||
|     bool get isSalable => (jsondata['salable'] ?? false) as bool; | ||||
|     bool get isSalable => (jsondata["salable"] ?? false) as bool; | ||||
|  | ||||
|     bool get isActive => (jsondata['active'] ?? false) as bool; | ||||
|     bool get isActive => (jsondata["active"] ?? false) as bool; | ||||
|  | ||||
|     bool get isVirtual => (jsondata['virtual'] ?? false) as bool; | ||||
|     bool get isVirtual => (jsondata["virtual"] ?? false) as bool; | ||||
|  | ||||
|     bool get isTrackable => (jsondata['trackable'] ?? false) as bool; | ||||
|     bool get isTrackable => (jsondata["trackable"] ?? false) as bool; | ||||
|  | ||||
|     // Get the IPN (internal part number) for the Part instance | ||||
|     String get IPN => (jsondata['IPN'] ?? '') as String; | ||||
|     String get IPN => (jsondata["IPN"] ?? "") as String; | ||||
|  | ||||
|     // Get the revision string for the Part instance | ||||
|     String get revision => (jsondata['revision'] ?? '') as String; | ||||
|     String get revision => (jsondata["revision"] ?? "") as String; | ||||
|  | ||||
|     // Get the category ID for the Part instance (or 'null' if does not exist) | ||||
|     int get categoryId => (jsondata['category'] ?? -1) as int; | ||||
|     // Get the category ID for the Part instance (or "null" if does not exist) | ||||
|     int get categoryId => (jsondata["category"] ?? -1) as int; | ||||
|  | ||||
|     // Get the category name for the Part instance | ||||
|     String get categoryName { | ||||
|       // Inavlid category ID | ||||
|       if (categoryId <= 0) return ''; | ||||
|       if (categoryId <= 0) return ""; | ||||
|  | ||||
|       if (!jsondata.containsKey('category_detail')) return ''; | ||||
|       if (!jsondata.containsKey("category_detail")) return ""; | ||||
|  | ||||
|       return (jsondata['category_detail']?['name'] ?? '') as String; | ||||
|       return (jsondata["category_detail"]?["name"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     // Get the category description for the Part instance | ||||
|     String get categoryDescription { | ||||
|       // Invalid category ID | ||||
|       if (categoryId <= 0) return ''; | ||||
|       if (categoryId <= 0) return ""; | ||||
|  | ||||
|       if (!jsondata.containsKey('category_detail')) return ''; | ||||
|       if (!jsondata.containsKey("category_detail")) return ""; | ||||
|  | ||||
|       return (jsondata['category_detail']?['description'] ?? '') as String; | ||||
|       return (jsondata["category_detail"]?["description"] ?? "") as String; | ||||
|     } | ||||
|     // Get the image URL for the Part instance | ||||
|     String get _image  => (jsondata['image'] ?? '') as String; | ||||
|     String get _image  => (jsondata["image"] ?? "") as String; | ||||
|  | ||||
|     // Get the thumbnail URL for the Part instance | ||||
|     String get _thumbnail => (jsondata['thumbnail'] ?? '') as String; | ||||
|     String get _thumbnail => (jsondata["thumbnail"] ?? "") as String; | ||||
|  | ||||
|     // Return the fully-qualified name for the Part instance | ||||
|     String get fullname { | ||||
|  | ||||
|       String fn = (jsondata['full_name'] ?? '') as String; | ||||
|       String fn = (jsondata["full_name"] ?? "") as String; | ||||
|  | ||||
|       if (fn.isNotEmpty) return fn; | ||||
|  | ||||
| @@ -369,15 +367,15 @@ class InvenTreePart extends InvenTreeModel { | ||||
|       final APIResponse response = await InvenTreeAPI().uploadFile( | ||||
|         url, | ||||
|         image, | ||||
|         method: 'PATCH', | ||||
|         name: 'image', | ||||
|         method: "PATCH", | ||||
|         name: "image", | ||||
|       ); | ||||
|  | ||||
|       return response.successful(); | ||||
|     } | ||||
|  | ||||
|     // Return the "starred" status of this part | ||||
|     bool get starred => (jsondata['starred'] ?? false) as bool; | ||||
|     bool get starred => (jsondata["starred"] ?? false) as bool; | ||||
|  | ||||
|     InvenTreePart() : super(); | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
|  | ||||
| import 'model.dart'; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
|  | ||||
| // TODO: In the future, status codes should be retrieved from the server | ||||
| const int PO_STATUS_PENDING = 10; | ||||
| @@ -44,27 +44,27 @@ class InvenTreePurchaseOrder extends InvenTreeModel { | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   String get issueDate => (jsondata['issue_date'] ?? '') as String; | ||||
|   String get issueDate => (jsondata["issue_date"] ?? "") as String; | ||||
|  | ||||
|   String get completeDate => (jsondata['complete_date'] ?? '') as String; | ||||
|   String get completeDate => (jsondata["complete_date"] ?? "") as String; | ||||
|  | ||||
|   String get creationDate => (jsondata['creation_date'] ?? '') as String; | ||||
|   String get creationDate => (jsondata["creation_date"] ?? "") as String; | ||||
|  | ||||
|   String get targetDate => (jsondata['target_date'] ?? '') as String; | ||||
|   String get targetDate => (jsondata["target_date"] ?? "") as String; | ||||
|  | ||||
|   int get lineItemCount => (jsondata['line_items'] ?? 0) as int; | ||||
|   int get lineItemCount => (jsondata["line_items"] ?? 0) as int; | ||||
|  | ||||
|   bool get overdue => (jsondata['overdue'] ?? false) as bool; | ||||
|   bool get overdue => (jsondata["overdue"] ?? false) as bool; | ||||
|  | ||||
|   String get reference => (jsondata['reference'] ?? '') as String; | ||||
|   String get reference => (jsondata["reference"] ?? "") as String; | ||||
|  | ||||
|   int get responsibleId => (jsondata['responsible'] ?? -1) as int; | ||||
|   int get responsibleId => (jsondata["responsible"] ?? -1) as int; | ||||
|  | ||||
|   int get supplierId => (jsondata['supplier'] ?? -1) as int; | ||||
|   int get supplierId => (jsondata["supplier"] ?? -1) as int; | ||||
|  | ||||
|   InvenTreeCompany? get supplier { | ||||
|  | ||||
|     dynamic supplier_detail = jsondata["supplier_detail"] ?? null; | ||||
|     dynamic supplier_detail = jsondata["supplier_detail"]; | ||||
|  | ||||
|     if (supplier_detail == null) { | ||||
|       return null; | ||||
| @@ -73,15 +73,15 @@ class InvenTreePurchaseOrder extends InvenTreeModel { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   String get supplierReference => (jsondata['supplier_reference'] ?? '') as String; | ||||
|   String get supplierReference => (jsondata["supplier_reference"] ?? "") as String; | ||||
|  | ||||
|   int get status => (jsondata['status'] ?? -1) as int; | ||||
|   int get status => (jsondata["status"] ?? -1) as int; | ||||
|  | ||||
|   String get statusText => (jsondata['status_text'] ?? '') as String; | ||||
|   String get statusText => (jsondata["status_text"] ?? "") as String; | ||||
|  | ||||
|   bool get isOpen => this.status == PO_STATUS_PENDING || this.status == PO_STATUS_PLACED; | ||||
|   bool get isOpen => status == PO_STATUS_PENDING || status == PO_STATUS_PLACED; | ||||
|  | ||||
|   bool get isFailed => this.status == PO_STATUS_CANCELLED || this.status == PO_STATUS_LOST || this.status == PO_STATUS_RETURNED; | ||||
|   bool get isFailed => status == PO_STATUS_CANCELLED || status == PO_STATUS_LOST || status == PO_STATUS_RETURNED; | ||||
|  | ||||
|   Future<List<InvenTreePOLineItem>> getLineItems() async { | ||||
|  | ||||
| @@ -146,17 +146,17 @@ class InvenTreePOLineItem extends InvenTreeModel { | ||||
|  | ||||
|   bool get isComplete => received >= quantity; | ||||
|  | ||||
|   double get quantity => (jsondata['quantity'] ?? 0) as double; | ||||
|   double get quantity => (jsondata["quantity"] ?? 0) as double; | ||||
|  | ||||
|   double get received => (jsondata['received'] ?? 0) as double; | ||||
|   double get received => (jsondata["received"] ?? 0) as double; | ||||
|  | ||||
|   double get outstanding => quantity - received; | ||||
|  | ||||
|   String get reference => (jsondata['reference'] ?? '') as String; | ||||
|   String get reference => (jsondata["reference"] ?? "") as String; | ||||
|  | ||||
|   int get orderId => (jsondata['order'] ?? -1) as int; | ||||
|   int get orderId => (jsondata["order"] ?? -1) as int; | ||||
|  | ||||
|   int get supplierPartId => (jsondata['part'] ?? -1) as int; | ||||
|   int get supplierPartId => (jsondata["part"] ?? -1) as int; | ||||
|  | ||||
|   InvenTreePart? get part { | ||||
|     dynamic part_detail = jsondata["part_detail"]; | ||||
| @@ -170,7 +170,7 @@ class InvenTreePOLineItem extends InvenTreeModel { | ||||
|  | ||||
|   InvenTreeSupplierPart? get supplierPart { | ||||
|  | ||||
|     dynamic detail = jsondata["supplier_part_detail"] ?? null; | ||||
|     dynamic detail = jsondata["supplier_part_detail"]; | ||||
|  | ||||
|     if (detail == null) { | ||||
|       return null; | ||||
| @@ -179,15 +179,15 @@ class InvenTreePOLineItem extends InvenTreeModel { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   double get purchasePrice => double.parse((jsondata['purchase_price'] ?? '') as String); | ||||
|   double get purchasePrice => double.parse((jsondata["purchase_price"] ?? "") as String); | ||||
|  | ||||
|   String get purchasePriceCurrency => (jsondata['purchase_price_currency'] ?? '') as String; | ||||
|   String get purchasePriceCurrency => (jsondata["purchase_price_currency"] ?? "") as String; | ||||
|  | ||||
|   String get purchasePriceString => (jsondata['purchase_price_string'] ?? '') as String; | ||||
|   String get purchasePriceString => (jsondata["purchase_price_string"] ?? "") as String; | ||||
|  | ||||
|   int get destination => (jsondata['destination'] ?? -1) as int; | ||||
|   int get destination => (jsondata["destination"] ?? -1) as int; | ||||
|  | ||||
|   Map<String, dynamic> get destinationDetail => (jsondata['destination_detail'] ?? {}) as Map<String, dynamic>; | ||||
|   Map<String, dynamic> get destinationDetail => (jsondata["destination_detail"] ?? {}) as Map<String, dynamic>; | ||||
|  | ||||
|   InvenTreePOLineItem() : super(); | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import 'dart:io'; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:device_info_plus/device_info_plus.dart'; | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import 'package:sentry_flutter/sentry_flutter.dart'; | ||||
| import "package:device_info_plus/device_info_plus.dart"; | ||||
| import "package:package_info_plus/package_info_plus.dart"; | ||||
| import "package:sentry_flutter/sentry_flutter.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| Future<Map<String, dynamic>> getDeviceInfo() async { | ||||
|  | ||||
| @@ -18,35 +18,35 @@ Future<Map<String, dynamic>> getDeviceInfo() async { | ||||
|     final iosDeviceInfo = await deviceInfo.iosInfo; | ||||
|  | ||||
|     device_info = { | ||||
|       'name': iosDeviceInfo.name, | ||||
|       'model': iosDeviceInfo.model, | ||||
|       'systemName': iosDeviceInfo.systemName, | ||||
|       'systemVersion': iosDeviceInfo.systemVersion, | ||||
|       'localizedModel': iosDeviceInfo.localizedModel, | ||||
|       'utsname': iosDeviceInfo.utsname.sysname, | ||||
|       'identifierForVendor': iosDeviceInfo.identifierForVendor, | ||||
|       'isPhysicalDevice': iosDeviceInfo.isPhysicalDevice, | ||||
|       "name": iosDeviceInfo.name, | ||||
|       "model": iosDeviceInfo.model, | ||||
|       "systemName": iosDeviceInfo.systemName, | ||||
|       "systemVersion": iosDeviceInfo.systemVersion, | ||||
|       "localizedModel": iosDeviceInfo.localizedModel, | ||||
|       "utsname": iosDeviceInfo.utsname.sysname, | ||||
|       "identifierForVendor": iosDeviceInfo.identifierForVendor, | ||||
|       "isPhysicalDevice": iosDeviceInfo.isPhysicalDevice, | ||||
|     }; | ||||
|  | ||||
|   } else if (Platform.isAndroid) { | ||||
|     final androidDeviceInfo = await deviceInfo.androidInfo; | ||||
|  | ||||
|     device_info = { | ||||
|       'type': androidDeviceInfo.type, | ||||
|       'model': androidDeviceInfo.model, | ||||
|       'device': androidDeviceInfo.device, | ||||
|       'id': androidDeviceInfo.id, | ||||
|       'androidId': androidDeviceInfo.androidId, | ||||
|       'brand': androidDeviceInfo.brand, | ||||
|       'display': androidDeviceInfo.display, | ||||
|       'hardware': androidDeviceInfo.hardware, | ||||
|       'manufacturer': androidDeviceInfo.manufacturer, | ||||
|       'product': androidDeviceInfo.product, | ||||
|       'version': androidDeviceInfo.version.release, | ||||
|       'supported32BitAbis': androidDeviceInfo.supported32BitAbis, | ||||
|       'supported64BitAbis': androidDeviceInfo.supported64BitAbis, | ||||
|       'supportedAbis': androidDeviceInfo.supportedAbis, | ||||
|       'isPhysicalDevice': androidDeviceInfo.isPhysicalDevice, | ||||
|       "type": androidDeviceInfo.type, | ||||
|       "model": androidDeviceInfo.model, | ||||
|       "device": androidDeviceInfo.device, | ||||
|       "id": androidDeviceInfo.id, | ||||
|       "androidId": androidDeviceInfo.androidId, | ||||
|       "brand": androidDeviceInfo.brand, | ||||
|       "display": androidDeviceInfo.display, | ||||
|       "hardware": androidDeviceInfo.hardware, | ||||
|       "manufacturer": androidDeviceInfo.manufacturer, | ||||
|       "product": androidDeviceInfo.product, | ||||
|       "version": androidDeviceInfo.version.release, | ||||
|       "supported32BitAbis": androidDeviceInfo.supported32BitAbis, | ||||
|       "supported64BitAbis": androidDeviceInfo.supported64BitAbis, | ||||
|       "supportedAbis": androidDeviceInfo.supportedAbis, | ||||
|       "isPhysicalDevice": androidDeviceInfo.isPhysicalDevice, | ||||
|     }; | ||||
|   } | ||||
|  | ||||
| @@ -90,7 +90,7 @@ Future<bool> sentryReportMessage(String message, {Map<String, String>? context}) | ||||
|  | ||||
|   if (isInDebugMode()) { | ||||
|  | ||||
|     print('----- In dev mode. Not sending message to Sentry.io -----'); | ||||
|     print("----- In dev mode. Not sending message to Sentry.io -----"); | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
| @@ -117,7 +117,7 @@ Future<bool> sentryReportMessage(String message, {Map<String, String>? context}) | ||||
|  | ||||
| Future<void> sentryReportError(dynamic error, dynamic stackTrace) async { | ||||
|  | ||||
|   print('----- Sentry Intercepted error: $error -----'); | ||||
|   print("----- Sentry Intercepted error: $error -----"); | ||||
|   print(stackTrace); | ||||
|  | ||||
|   // Errors thrown in development mode are unlikely to be interesting. You can | ||||
| @@ -125,7 +125,7 @@ Future<void> sentryReportError(dynamic error, dynamic stackTrace) async { | ||||
|   // the report. | ||||
|   if (isInDebugMode()) { | ||||
|  | ||||
|     print('----- In dev mode. Not sending report to Sentry.io -----'); | ||||
|     print("----- In dev mode. Not sending report to Sentry.io -----"); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,13 @@ | ||||
| import 'package:intl/intl.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:http/http.dart' as http; | ||||
| import 'model.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "dart:async"; | ||||
|  | ||||
| import "package:intl/intl.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
|  | ||||
| import 'dart:async'; | ||||
| import 'dart:io'; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
|  | ||||
| class InvenTreeStockItemTestResult extends InvenTreeModel { | ||||
| @@ -31,19 +29,17 @@ class InvenTreeStockItemTestResult extends InvenTreeModel { | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   String get key => (jsondata['key'] ?? '') as String; | ||||
|   String get key => (jsondata["key"] ?? "") as String; | ||||
|  | ||||
|   String get testName => (jsondata['test'] ?? '') as String; | ||||
|   String get testName => (jsondata["test"] ?? "") as String; | ||||
|  | ||||
|   bool get result => (jsondata['result'] ?? false) as bool; | ||||
|   bool get result => (jsondata["result"] ?? false) as bool; | ||||
|  | ||||
|   String get value => (jsondata['value'] ?? '') as String; | ||||
|   String get value => (jsondata["value"] ?? "") as String; | ||||
|  | ||||
|   String get notes => (jsondata['notes'] ?? '') as String; | ||||
|   String get attachment => (jsondata["attachment"] ?? "") as String; | ||||
|  | ||||
|   String get attachment => (jsondata['attachment'] ?? '') as String; | ||||
|  | ||||
|   String get date => (jsondata['date'] ?? '') as String; | ||||
|   String get date => (jsondata["date"] ?? "") as String; | ||||
|  | ||||
|   InvenTreeStockItemTestResult() : super(); | ||||
|  | ||||
| @@ -204,17 +200,17 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   String get uid => (jsondata['uid'] ?? '') as String; | ||||
|   String get uid => (jsondata["uid"] ?? "") as String; | ||||
|  | ||||
|   int get status => (jsondata['status'] ?? -1) as int; | ||||
|   int get status => (jsondata["status"] ?? -1) as int; | ||||
|  | ||||
|   String get packaging => (jsondata["packaging"] ?? '') as String; | ||||
|   String get packaging => (jsondata["packaging"] ?? "") as String; | ||||
|  | ||||
|   String get batch => (jsondata["batch"] ?? '') as String; | ||||
|   String get batch => (jsondata["batch"] ?? "") as String; | ||||
|  | ||||
|   int get partId => (jsondata['part'] ?? -1) as int; | ||||
|   int get partId => (jsondata["part"] ?? -1) as int; | ||||
|    | ||||
|   String get purchasePrice => (jsondata['purchase_price'] ?? '') as String; | ||||
|   String get purchasePrice => (jsondata["purchase_price"] ?? "") as String; | ||||
|  | ||||
|   bool get hasPurchasePrice { | ||||
|  | ||||
| @@ -223,14 +219,14 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|     return pp.isNotEmpty && pp.trim() != "-"; | ||||
|   } | ||||
|  | ||||
|   int get purchaseOrderId => (jsondata['purchase_order'] ?? -1) as int; | ||||
|   int get purchaseOrderId => (jsondata["purchase_order"] ?? -1) as int; | ||||
|  | ||||
|   int get trackingItemCount => (jsondata['tracking_items'] ?? 0) as int; | ||||
|   int get trackingItemCount => (jsondata["tracking_items"] ?? 0) as int; | ||||
|  | ||||
|   // Date of last update | ||||
|   DateTime? get updatedDate { | ||||
|     if (jsondata.containsKey("updated")) { | ||||
|       return DateTime.tryParse((jsondata["updated"] ?? '') as String); | ||||
|       return DateTime.tryParse((jsondata["updated"] ?? "") as String); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
| @@ -250,7 +246,7 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|  | ||||
|   DateTime? get stocktakeDate { | ||||
|     if (jsondata.containsKey("stocktake_date")) { | ||||
|       return DateTime.tryParse((jsondata["stocktake_date"] ?? '') as String); | ||||
|       return DateTime.tryParse((jsondata["stocktake_date"] ?? "") as String); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
| @@ -270,45 +266,45 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|  | ||||
|   String get partName { | ||||
|  | ||||
|     String nm = ''; | ||||
|     String nm = ""; | ||||
|  | ||||
|     // Use the detailed part information as priority | ||||
|     if (jsondata.containsKey('part_detail')) { | ||||
|       nm = (jsondata['part_detail']['full_name'] ?? '') as String; | ||||
|     if (jsondata.containsKey("part_detail")) { | ||||
|       nm = (jsondata["part_detail"]["full_name"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     // Backup if first value fails | ||||
|     if (nm.isEmpty) { | ||||
|       nm = (jsondata['part__name'] ?? '') as String; | ||||
|       nm = (jsondata["part__name"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return nm; | ||||
|   } | ||||
|  | ||||
|   String get partDescription { | ||||
|     String desc = ''; | ||||
|     String desc = ""; | ||||
|  | ||||
|     // Use the detailed part description as priority | ||||
|     if (jsondata.containsKey('part_detail')) { | ||||
|       desc = (jsondata['part_detail']['description'] ?? '') as String; | ||||
|     if (jsondata.containsKey("part_detail")) { | ||||
|       desc = (jsondata["part_detail"]["description"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     if (desc.isEmpty) { | ||||
|       desc = (jsondata['part__description'] ?? '') as String; | ||||
|       desc = (jsondata["part__description"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return desc; | ||||
|   } | ||||
|  | ||||
|   String get partImage { | ||||
|     String img = ''; | ||||
|     String img = ""; | ||||
|  | ||||
|     if (jsondata.containsKey('part_detail')) { | ||||
|       img = (jsondata['part_detail']['thumbnail'] ?? '') as String; | ||||
|     if (jsondata.containsKey("part_detail")) { | ||||
|       img = (jsondata["part_detail"]["thumbnail"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     if (img.isEmpty) { | ||||
|       img = (jsondata['part__thumbnail'] ?? '') as String; | ||||
|       img = (jsondata["part__thumbnail"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return img; | ||||
| @@ -321,63 +317,63 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|  | ||||
|     String thumb = ""; | ||||
|  | ||||
|     thumb = (jsondata['part_detail']?['thumbnail'] ?? '') as String; | ||||
|     thumb = (jsondata["part_detail"]?["thumbnail"] ?? "") as String; | ||||
|  | ||||
|     // Use 'image' as a backup | ||||
|     // Use "image" as a backup | ||||
|     if (thumb.isEmpty) { | ||||
|       thumb = (jsondata['part_detail']?['image'] ?? '') as String; | ||||
|       thumb = (jsondata["part_detail"]?["image"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     // Try a different approach | ||||
|     if (thumb.isEmpty) { | ||||
|       thumb = (jsondata['part__thumbnail'] ?? '') as String; | ||||
|       thumb = (jsondata["part__thumbnail"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     // Still no thumbnail? Use the 'no image' image | ||||
|     // Still no thumbnail? Use the "no image" image | ||||
|     if (thumb.isEmpty) thumb = InvenTreeAPI.staticThumb; | ||||
|  | ||||
|     return thumb; | ||||
|   } | ||||
|  | ||||
|   int get supplierPartId => (jsondata['supplier_part'] ?? -1) as int; | ||||
|   int get supplierPartId => (jsondata["supplier_part"] ?? -1) as int; | ||||
|  | ||||
|   String get supplierImage { | ||||
|     String thumb = ''; | ||||
|     String thumb = ""; | ||||
|  | ||||
|     if (jsondata.containsKey("supplier_detail")) { | ||||
|       thumb = (jsondata['supplier_detail']['supplier_logo'] ?? '') as String; | ||||
|       thumb = (jsondata["supplier_detail"]["supplier_logo"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return thumb; | ||||
|   } | ||||
|  | ||||
|   String get supplierName { | ||||
|     String sname = ''; | ||||
|     String sname = ""; | ||||
|  | ||||
|     if (jsondata.containsKey("supplier_detail")) { | ||||
|       sname = (jsondata["supplier_detail"]["supplier_name"] ?? '') as String; | ||||
|       sname = (jsondata["supplier_detail"]["supplier_name"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return sname; | ||||
|   } | ||||
|  | ||||
|   String get units { | ||||
|     return (jsondata['part_detail']?['units'] ?? '') as String; | ||||
|     return (jsondata["part_detail"]?["units"] ?? "") as String; | ||||
|   } | ||||
|  | ||||
|   String get supplierSKU { | ||||
|     String sku = ''; | ||||
|     String sku = ""; | ||||
|  | ||||
|     if (jsondata.containsKey("supplier_detail")) { | ||||
|       sku = (jsondata["supplier_detail"]["SKU"] ?? '') as String; | ||||
|       sku = (jsondata["supplier_detail"]["SKU"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return sku; | ||||
|   } | ||||
|  | ||||
|   String get serialNumber => (jsondata['serial'] ?? '') as String; | ||||
|   String get serialNumber => (jsondata["serial"] ?? "") as String; | ||||
|  | ||||
|   double get quantity => double.tryParse(jsondata['quantity'].toString()) ?? 0; | ||||
|   double get quantity => double.tryParse(jsondata["quantity"].toString()) ?? 0; | ||||
|  | ||||
|   String get quantityString { | ||||
|  | ||||
| @@ -395,33 +391,33 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|     return q; | ||||
|   } | ||||
|  | ||||
|   int get locationId => (jsondata['location'] ?? -1) as int; | ||||
|   int get locationId => (jsondata["location"] ?? -1) as int; | ||||
|  | ||||
|   bool isSerialized() => serialNumber.isNotEmpty && quantity.toInt() == 1; | ||||
|  | ||||
|   String serialOrQuantityDisplay() { | ||||
|     if (isSerialized()) { | ||||
|       return 'SN ${serialNumber}'; | ||||
|       return "SN ${serialNumber}"; | ||||
|     } | ||||
|  | ||||
|     // Is an integer? | ||||
|     if (quantity.toInt() == quantity) { | ||||
|       return '${quantity.toInt()}'; | ||||
|       return "${quantity.toInt()}"; | ||||
|     } | ||||
|  | ||||
|     return '${quantity}'; | ||||
|     return "${quantity}"; | ||||
|   } | ||||
|  | ||||
|   String get locationName { | ||||
|     String loc = ''; | ||||
|     String loc = ""; | ||||
|  | ||||
|     if (locationId == -1 || !jsondata.containsKey('location_detail')) return 'Unknown Location'; | ||||
|     if (locationId == -1 || !jsondata.containsKey("location_detail")) return "Unknown Location"; | ||||
|  | ||||
|     loc = (jsondata['location_detail']['name'] ?? '') as String; | ||||
|     loc = (jsondata["location_detail"]["name"] ?? "") as String; | ||||
|  | ||||
|     // Old-style name | ||||
|     if (loc.isEmpty) { | ||||
|       loc = (jsondata['location__name'] ?? '') as String; | ||||
|       loc = (jsondata["location__name"] ?? "") as String; | ||||
|     } | ||||
|  | ||||
|     return loc; | ||||
| @@ -429,9 +425,9 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|  | ||||
|   String get locationPathString { | ||||
|  | ||||
|     if (locationId == -1 || !jsondata.containsKey('location_detail')) return L10().locationNotSet; | ||||
|     if (locationId == -1 || !jsondata.containsKey("location_detail")) return L10().locationNotSet; | ||||
|  | ||||
|     String _loc = (jsondata['location_detail']['pathstring'] ?? '') as String; | ||||
|     String _loc = (jsondata["location_detail"]["pathstring"] ?? "") as String; | ||||
|  | ||||
|     if (_loc.isNotEmpty) { | ||||
|       return _loc; | ||||
| @@ -483,7 +479,7 @@ class InvenTreeStockItem extends InvenTreeModel { | ||||
|         "pk": "${pk}", | ||||
|         "quantity": "${q}", | ||||
|         }, | ||||
|         "notes": notes ?? '', | ||||
|         "notes": notes ?? "", | ||||
|       }, | ||||
|       expectedStatusCode: 200 | ||||
|     ); | ||||
| @@ -540,7 +536,7 @@ class InvenTreeStockLocation extends InvenTreeModel { | ||||
|   @override | ||||
|   String get URL => "stock/location/"; | ||||
|  | ||||
|   String get pathstring => (jsondata['pathstring'] ?? '') as String; | ||||
|   String get pathstring => (jsondata["pathstring"] ?? "") as String; | ||||
|  | ||||
|   @override | ||||
|   Map<String, dynamic> formFields() { | ||||
| @@ -553,13 +549,13 @@ class InvenTreeStockLocation extends InvenTreeModel { | ||||
|  | ||||
|   String get parentpathstring { | ||||
|     // TODO - Drive the refactor tractor through this | ||||
|     List<String> psplit = pathstring.split('/'); | ||||
|     List<String> psplit = pathstring.split("/"); | ||||
|  | ||||
|     if (psplit.length > 0) { | ||||
|       psplit.removeLast(); | ||||
|     } | ||||
|  | ||||
|     String p = psplit.join('/'); | ||||
|     String p = psplit.join("/"); | ||||
|  | ||||
|     if (p.isEmpty) { | ||||
|       p = "Top level stock location"; | ||||
| @@ -568,7 +564,7 @@ class InvenTreeStockLocation extends InvenTreeModel { | ||||
|     return p; | ||||
|   } | ||||
|  | ||||
|   int get itemcount => (jsondata['items'] ?? 0) as int; | ||||
|   int get itemcount => (jsondata["items"] ?? 0) as int; | ||||
|  | ||||
|   InvenTreeStockLocation() : super(); | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations_en.dart'; | ||||
| import "package:flutter_gen/gen_l10n/app_localizations.dart"; | ||||
| import "package:flutter_gen/gen_l10n/app_localizations_en.dart"; | ||||
|  | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import "package:one_context/one_context.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| // Shortcut function to reduce boilerplate! | ||||
| I18N L10() | ||||
|   | ||||
| @@ -1,19 +1,18 @@ | ||||
| import 'dart:async'; | ||||
| import "dart:async"; | ||||
|  | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:flutter_localizations/flutter_localizations.dart'; | ||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||
| import "package:flutter_localizations/flutter_localizations.dart"; | ||||
| import "package:flutter_gen/gen_l10n/app_localizations.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/home.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:one_context/one_context.dart"; | ||||
| import "package:package_info_plus/package_info_plus.dart"; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:sentry_flutter/sentry_flutter.dart"; | ||||
|  | ||||
| import 'dsn.dart'; | ||||
|  | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:sentry_flutter/sentry_flutter.dart'; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/dsn.dart"; | ||||
| import "package:inventree/widget/home.dart"; | ||||
|  | ||||
|  | ||||
| Future<void> main() async { | ||||
| @@ -75,24 +74,24 @@ class InvenTreeApp extends StatelessWidget { | ||||
|         GlobalCupertinoLocalizations.delegate, | ||||
|       ], | ||||
|       supportedLocales: [ | ||||
|         const Locale('de', ''),   // German | ||||
|         const Locale('el', ''),   // Greek | ||||
|         const Locale('en', ''),   // English | ||||
|         const Locale('es', ''),   // Spanish | ||||
|         const Locale('fr', ''),   // French | ||||
|         const Locale('he', ''),   // Hebrew | ||||
|         const Locale('it', ''),   // Italian | ||||
|         const Locale('ja', ''),   // Japanese | ||||
|         const Locale('ko', ''),   // Korean | ||||
|         const Locale('nl', ''),   // Dutch | ||||
|         const Locale('no', ''),   // Norwegian | ||||
|         const Locale('pl', ''),   // Polish | ||||
|         const Locale('ru', ''),   // Russian | ||||
|         const Locale('sv', ''),   // Swedish | ||||
|         const Locale('th', ''),   // Thai | ||||
|         const Locale('tr', ''),   // Turkish | ||||
|         const Locale('vi', ''),   // Vietnamese | ||||
|         const Locale('zh-CN', ''),   // Chinese | ||||
|         const Locale("de", ""),   // German | ||||
|         const Locale("el", ""),   // Greek | ||||
|         const Locale("en", ""),   // English | ||||
|         const Locale("es", ""),   // Spanish | ||||
|         const Locale("fr", ""),   // French | ||||
|         const Locale("he", ""),   // Hebrew | ||||
|         const Locale("it", ""),   // Italian | ||||
|         const Locale("ja", ""),   // Japanese | ||||
|         const Locale("ko", ""),   // Korean | ||||
|         const Locale("nl", ""),   // Dutch | ||||
|         const Locale("no", ""),   // Norwegian | ||||
|         const Locale("pl", ""),   // Polish | ||||
|         const Locale("ru", ""),   // Russian | ||||
|         const Locale("sv", ""),   // Swedish | ||||
|         const Locale("th", ""),   // Thai | ||||
|         const Locale("tr", ""),   // Turkish | ||||
|         const Locale("vi", ""),   // Vietnamese | ||||
|         const Locale("zh-CN", ""),   // Chinese | ||||
|       ], | ||||
|  | ||||
|     ); | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| import 'package:path_provider/path_provider.dart'; | ||||
| import 'package:sembast/sembast.dart'; | ||||
| import 'package:sembast/sembast_io.dart'; | ||||
| import 'package:path/path.dart'; | ||||
| import 'dart:async'; | ||||
| import "dart:async"; | ||||
|  | ||||
| import "package:path_provider/path_provider.dart"; | ||||
| import "package:sembast/sembast.dart"; | ||||
| import "package:sembast/sembast_io.dart"; | ||||
| import "package:path/path.dart"; | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Class for storing InvenTree preferences in a NoSql DB | ||||
| @@ -43,7 +45,7 @@ class InvenTreePreferencesDB { | ||||
|     print("Path: ${appDocumentDir.path}"); | ||||
|  | ||||
|     // Path with the form: /platform-specific-directory/demo.db | ||||
|     final dbPath = join(appDocumentDir.path, 'InvenTreeSettings.db'); | ||||
|     final dbPath = join(appDocumentDir.path, "InvenTreeSettings.db"); | ||||
|  | ||||
|     final database = await databaseFactoryIo.openDatabase(dbPath); | ||||
|  | ||||
| @@ -55,7 +57,7 @@ class InvenTreePreferencesDB { | ||||
| class InvenTreePreferences { | ||||
|  | ||||
|   /* The following settings are not stored to persistent storage, | ||||
|    * instead they are only used as 'session preferences'. | ||||
|    * instead they are only used as "session preferences". | ||||
|    * They are kept here as a convenience only. | ||||
|    */ | ||||
|  | ||||
|   | ||||
| @@ -1,22 +1,22 @@ | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/settings/release.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/settings/release.dart"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter/services.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:package_info_plus/package_info_plus.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| class InvenTreeAboutWidget extends StatelessWidget { | ||||
|  | ||||
|   final PackageInfo info; | ||||
|  | ||||
|   InvenTreeAboutWidget(this.info) : super(); | ||||
|   const InvenTreeAboutWidget(this.info) : super(); | ||||
|  | ||||
|   void _releaseNotes(BuildContext context) async { | ||||
|   Future <void> _releaseNotes(BuildContext context) async { | ||||
|  | ||||
|     // Load release notes from external file | ||||
|     String notes = await rootBundle.loadString("assets/release_notes.md"); | ||||
| @@ -27,7 +27,7 @@ class InvenTreeAboutWidget extends StatelessWidget { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _credits(BuildContext context) async { | ||||
|   Future <void> _credits(BuildContext context) async { | ||||
|  | ||||
|     String notes = await rootBundle.loadString("assets/credits.md"); | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| import 'package:inventree/app_settings.dart'; | ||||
| import "package:inventree/app_settings.dart"; | ||||
|  | ||||
| class InvenTreeAppSettingsWidget extends StatefulWidget { | ||||
|   @override | ||||
| @@ -31,7 +31,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> { | ||||
|     loadSettings(); | ||||
|   } | ||||
|  | ||||
|   void loadSettings() async { | ||||
|   Future <void> loadSettings() async { | ||||
|     barcodeSounds = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; | ||||
|     serverSounds = await InvenTreeSettingsManager().getValue("serverSounds", true) as bool; | ||||
|  | ||||
| @@ -42,7 +42,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void setBarcodeSounds(bool en) async { | ||||
|   Future <void> setBarcodeSounds(bool en) async { | ||||
|  | ||||
|     await InvenTreeSettingsManager().setValue("barcodeSounds", en); | ||||
|     barcodeSounds = await InvenTreeSettingsManager().getBool("barcodeSounds", true); | ||||
| @@ -51,7 +51,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void setServerSounds(bool en) async { | ||||
|   Future <void> setServerSounds(bool en) async { | ||||
|  | ||||
|     await InvenTreeSettingsManager().setValue("serverSounds", en); | ||||
|     serverSounds = await InvenTreeSettingsManager().getBool("serverSounds", true); | ||||
| @@ -60,7 +60,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void setPartSubcategory(bool en) async { | ||||
|   Future <void> setPartSubcategory(bool en) async { | ||||
|     await InvenTreeSettingsManager().setValue("partSubcategory", en); | ||||
|     partSubcategory = await InvenTreeSettingsManager().getBool("partSubcategory", true); | ||||
|  | ||||
| @@ -68,7 +68,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void setStockSublocation(bool en) async { | ||||
|   Future <void> setStockSublocation(bool en) async { | ||||
|     await InvenTreeSettingsManager().setValue("stockSublocation", en); | ||||
|     stockSublocation = await InvenTreeSettingsManager().getBool("stockSublocation", true); | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,12 @@ | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/widget/spinner.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
|  | ||||
| import '../api.dart'; | ||||
| import '../user_profile.dart'; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:inventree/widget/spinner.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
|  | ||||
| class InvenTreeLoginSettingsWidget extends StatefulWidget { | ||||
|  | ||||
| @@ -22,15 +19,13 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | ||||
|  | ||||
|   final GlobalKey<_InvenTreeLoginSettingsState> _loginKey = GlobalKey<_InvenTreeLoginSettingsState>(); | ||||
|  | ||||
|   final GlobalKey<FormState> _addProfileKey = new GlobalKey<FormState>(); | ||||
|  | ||||
|   List<UserProfile> profiles = []; | ||||
|  | ||||
|   _InvenTreeLoginSettingsState() { | ||||
|     _reload(); | ||||
|   } | ||||
|  | ||||
|   void _reload() async { | ||||
|   Future <void> _reload() async { | ||||
|  | ||||
|     profiles = await UserProfileDBManager().getAllProfiles(); | ||||
|  | ||||
| @@ -50,7 +45,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void _selectProfile(BuildContext context, UserProfile profile) async { | ||||
|   Future <void> _selectProfile(BuildContext context, UserProfile profile) async { | ||||
|  | ||||
|     // Disconnect InvenTree | ||||
|     InvenTreeAPI().disconnectFromServer(); | ||||
| @@ -73,18 +68,18 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | ||||
|     _reload(); | ||||
|   } | ||||
|  | ||||
|   void _deleteProfile(UserProfile profile) async { | ||||
|   Future <void> _deleteProfile(UserProfile profile) async { | ||||
|  | ||||
|     await UserProfileDBManager().deleteProfile(profile); | ||||
|  | ||||
|     _reload(); | ||||
|  | ||||
|     if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? '')) { | ||||
|     if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? "")) { | ||||
|       InvenTreeAPI().disconnectFromServer(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _updateProfile(UserProfile? profile) async { | ||||
|   Future <void> _updateProfile(UserProfile? profile) async { | ||||
|  | ||||
|     if (profile == null) { | ||||
|       return; | ||||
| @@ -92,7 +87,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | ||||
|  | ||||
|     _reload(); | ||||
|  | ||||
|     if (InvenTreeAPI().isConnected() && InvenTreeAPI().profile != null && profile.key == (InvenTreeAPI().profile?.key ?? '')) { | ||||
|     if (InvenTreeAPI().isConnected() && InvenTreeAPI().profile != null && profile.key == (InvenTreeAPI().profile?.key ?? "")) { | ||||
|       // Attempt server login (this will load the newly selected profile | ||||
|  | ||||
|       InvenTreeAPI().connectToServer().then((result) { | ||||
| @@ -108,7 +103,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> { | ||||
|     if (!profile.selected) return null; | ||||
|  | ||||
|     // Selected, but (for some reason) not the same as the API... | ||||
|     if ((InvenTreeAPI().profile?.key ?? '') != profile.key) { | ||||
|     if ((InvenTreeAPI().profile?.key ?? "") != profile.key) { | ||||
|       return FaIcon( | ||||
|         FontAwesomeIcons.questionCircle, | ||||
|         color: COLOR_WARNING | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_markdown/flutter_markdown.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter_markdown/flutter_markdown.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| class ReleaseNotesWidget extends StatelessWidget { | ||||
|  | ||||
|   final String releaseNotes; | ||||
|  | ||||
|   ReleaseNotesWidget(this.releaseNotes); | ||||
|   const ReleaseNotesWidget(this.releaseNotes); | ||||
|  | ||||
|   @override | ||||
|   Widget build (BuildContext context) { | ||||
| @@ -29,7 +29,7 @@ class CreditsWidget extends StatelessWidget { | ||||
|  | ||||
|   final String credits; | ||||
|  | ||||
|   CreditsWidget(this.credits); | ||||
|   const CreditsWidget(this.credits); | ||||
|  | ||||
|   @override | ||||
|   Widget build (BuildContext context) { | ||||
|   | ||||
| @@ -1,18 +1,16 @@ | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/settings/about.dart'; | ||||
| import 'package:inventree/settings/app_settings.dart'; | ||||
| import 'package:inventree/settings/login.dart'; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/settings/about.dart"; | ||||
| import "package:inventree/settings/app_settings.dart"; | ||||
| import "package:inventree/settings/login.dart"; | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import 'package:inventree/widget/submit_feedback.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/widget/submit_feedback.dart"; | ||||
|  | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
| import "package:url_launcher/url_launcher.dart"; | ||||
|  | ||||
| import 'login.dart'; | ||||
|  | ||||
| import 'package:package_info_plus/package_info_plus.dart'; | ||||
| import "package:package_info_plus/package_info_plus.dart"; | ||||
|  | ||||
| class InvenTreeSettingsWidget extends StatefulWidget { | ||||
|   // InvenTree settings view | ||||
| @@ -95,30 +93,30 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> { | ||||
|   } | ||||
|  | ||||
|  | ||||
|   void _openDocs() async { | ||||
|   Future <void> _openDocs() async { | ||||
|     if (await canLaunch(docsUrl)) { | ||||
|       await launch(docsUrl); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _translate() async { | ||||
|     final String url = "https://crowdin.com/project/inventree"; | ||||
|   Future <void> _translate() async { | ||||
|     const String url = "https://crowdin.com/project/inventree"; | ||||
|  | ||||
|     if (await canLaunch(url)) { | ||||
|       await launch(url); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _editServerSettings() async { | ||||
|   Future <void> _editServerSettings() async { | ||||
|  | ||||
|     Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget())); | ||||
|   } | ||||
|  | ||||
|   void _editAppSettings() async { | ||||
|   Future <void> _editAppSettings() async { | ||||
|     Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget())); | ||||
|   } | ||||
|  | ||||
|   void _about() async { | ||||
|   Future <void> _about() async { | ||||
|  | ||||
|     PackageInfo.fromPlatform().then((PackageInfo info) { | ||||
|       Navigator.push(context, | ||||
| @@ -126,7 +124,7 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void _submitFeedback(BuildContext context) async { | ||||
|   Future <void> _submitFeedback(BuildContext context) async { | ||||
|  | ||||
|     Navigator.push( | ||||
|       context, | ||||
|   | ||||
| @@ -2,8 +2,8 @@ | ||||
| /* | ||||
|  * Class for InvenTree user / login details | ||||
|  */ | ||||
| import 'package:sembast/sembast.dart'; | ||||
| import 'preferences.dart'; | ||||
| import "package:sembast/sembast.dart"; | ||||
| import "preferences.dart"; | ||||
|  | ||||
| class UserProfile { | ||||
|  | ||||
| @@ -38,10 +38,10 @@ class UserProfile { | ||||
|  | ||||
|   factory UserProfile.fromJson(int key, Map<String, dynamic> json, bool isSelected) => UserProfile( | ||||
|     key: key, | ||||
|     name: json['name'] as String, | ||||
|     server: json['server'] as String, | ||||
|     username: json['username'] as String, | ||||
|     password: json['password'] as String, | ||||
|     name: json["name"] as String, | ||||
|     server: json["server"] as String, | ||||
|     username: json["username"] as String, | ||||
|     password: json["password"] as String, | ||||
|     selected: isSelected, | ||||
|   ); | ||||
|  | ||||
| @@ -70,7 +70,7 @@ class UserProfileDBManager { | ||||
|  | ||||
|     final profiles = await store.find(await _db, finder: finder); | ||||
|  | ||||
|     return profiles.length > 0; | ||||
|     return profiles.isNotEmpty; | ||||
|   } | ||||
|  | ||||
|   Future<void> addProfile(UserProfile profile) async { | ||||
|   | ||||
| @@ -1,27 +1,27 @@ | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/app_settings.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/app_settings.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/part_detail.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/paginator.dart'; | ||||
| import "package:inventree/widget/part_detail.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/paginator.dart"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart"; | ||||
|  | ||||
| class CategoryDisplayWidget extends StatefulWidget { | ||||
|  | ||||
|   CategoryDisplayWidget(this.category, {Key? key}) : super(key: key); | ||||
|   const CategoryDisplayWidget(this.category, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreePartCategory? category; | ||||
|  | ||||
| @@ -41,7 +41,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if ((category != null) && InvenTreeAPI().checkPermission('part_category', 'change')) { | ||||
|     if ((category != null) && InvenTreeAPI().checkPermission("part_category", "change")) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.edit), | ||||
| @@ -278,7 +278,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
|       getCategoryDescriptionCard(extra: false), | ||||
|     ]; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'add')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "add")) { | ||||
|       tiles.add( | ||||
|           ListTile( | ||||
|             title: Text(L10().categoryCreate), | ||||
| @@ -331,7 +331,9 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
|         ); | ||||
|       case 1: | ||||
|         return PaginatedPartList( | ||||
|           {"category": "${category?.pk ?? null}"}, | ||||
|           { | ||||
|             "category": "${category?.pk ?? 'null'}" | ||||
|           }, | ||||
|         ); | ||||
|       case 2: | ||||
|         return ListView( | ||||
| @@ -350,7 +352,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> { | ||||
| class SubcategoryList extends StatelessWidget { | ||||
|   final List<InvenTreePartCategory> _categories; | ||||
|  | ||||
|   SubcategoryList(this._categories); | ||||
|   const SubcategoryList(this._categories); | ||||
|  | ||||
|   void _openCategory(BuildContext context, int pk) { | ||||
|  | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| class CompanyDetailWidget extends StatefulWidget { | ||||
|  | ||||
|   final InvenTreeCompany company; | ||||
|  | ||||
|   CompanyDetailWidget(this.company, {Key? key}) : super(key: key); | ||||
|   const CompanyDetailWidget(this.company, {Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _CompanyDetailState createState() => _CompanyDetailState(company); | ||||
| @@ -62,7 +62,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> { | ||||
|     await company.reload(); | ||||
|   } | ||||
|  | ||||
|   void editCompany(BuildContext context) async { | ||||
|   Future <void> editCompany(BuildContext context) async { | ||||
|  | ||||
|     company.editForm( | ||||
|       context, | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/paginator.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/company_detail.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/paginator.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/company_detail.dart"; | ||||
|  | ||||
| import '../l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| class CompanyListWidget extends StatefulWidget { | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
|  | ||||
| import 'package:inventree/app_settings.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:audioplayers/audioplayers.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import "package:inventree/app_settings.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:audioplayers/audioplayers.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:one_context/one_context.dart"; | ||||
|  | ||||
| Future<void> confirmationDialog(String title, String text, {String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async { | ||||
|  | ||||
|   | ||||
| @@ -1,21 +1,21 @@ | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/barcode.dart'; | ||||
| import 'package:inventree/widget/company_list.dart'; | ||||
| import 'package:inventree/widget/search.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/barcode.dart"; | ||||
| import "package:inventree/widget/company_list.dart"; | ||||
| import "package:inventree/widget/search.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/category_display.dart'; | ||||
| import 'package:inventree/widget/location_display.dart'; | ||||
| import "package:inventree/widget/category_display.dart"; | ||||
| import "package:inventree/widget/location_display.dart"; | ||||
|  | ||||
| import 'package:inventree/settings/settings.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import "package:inventree/settings/settings.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| class InvenTreeDrawer extends StatelessWidget { | ||||
|  | ||||
|   final BuildContext context; | ||||
|  | ||||
|   InvenTreeDrawer(this.context); | ||||
|   const InvenTreeDrawer(this.context); | ||||
|  | ||||
|   void _closeDrawer() { | ||||
|     // Close the drawer | ||||
| @@ -50,7 +50,7 @@ class InvenTreeDrawer extends StatelessWidget { | ||||
|    * Launch the camera to scan a QR code. | ||||
|    * Upon successful scan, data are passed off to be decoded. | ||||
|    */ | ||||
|   void _scan() async { | ||||
|   Future <void> _scan() async { | ||||
|     if (!InvenTreeAPI().checkConnection(context)) return; | ||||
|  | ||||
|     _closeDrawer(); | ||||
|   | ||||
| @@ -1,15 +1,13 @@ | ||||
| import "dart:async"; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:file_picker/file_picker.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:image_picker/image_picker.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
|  | ||||
| import 'dart:async'; | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import "package:file_picker/file_picker.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:image_picker/image_picker.dart"; | ||||
| import "package:one_context/one_context.dart"; | ||||
|  | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| class FilePickerDialog { | ||||
| @@ -167,7 +165,7 @@ class CheckBoxField extends FormField<bool> { | ||||
|  | ||||
| class StringField extends TextFormField { | ||||
|  | ||||
|   StringField({String label = "", String? hint, String? initial, Function(String?)? onSaved, Function? validator, bool allowEmpty = false, bool isEnabled = true}) : | ||||
|   StringField({String label = "", String? hint, String? initial, Function(String?)? onSaved, Function(String?)? validator, bool allowEmpty = false, bool isEnabled = true}) : | ||||
|       super( | ||||
|         decoration: InputDecoration( | ||||
|           labelText: allowEmpty ? label : label + "*", | ||||
| @@ -182,7 +180,7 @@ class StringField extends TextFormField { | ||||
|           } | ||||
|  | ||||
|           if (validator != null) { | ||||
|             return validator(value); | ||||
|             return validator(value) as String?; | ||||
|           } | ||||
|  | ||||
|           return null; | ||||
|   | ||||
| @@ -1,29 +1,29 @@ | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/user_profile.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| import 'package:inventree/barcode.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/barcode.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| import 'package:inventree/settings/login.dart'; | ||||
| import "package:inventree/settings/login.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/category_display.dart'; | ||||
| import 'package:inventree/widget/company_list.dart'; | ||||
| import 'package:inventree/widget/location_display.dart'; | ||||
| import 'package:inventree/widget/purchase_order_list.dart'; | ||||
| import 'package:inventree/widget/search.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:inventree/widget/spinner.dart'; | ||||
| import 'package:inventree/widget/drawer.dart'; | ||||
| import "package:inventree/widget/category_display.dart"; | ||||
| import "package:inventree/widget/company_list.dart"; | ||||
| import "package:inventree/widget/location_display.dart"; | ||||
| import "package:inventree/widget/purchase_order_list.dart"; | ||||
| import "package:inventree/widget/search.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:inventree/widget/spinner.dart"; | ||||
| import "package:inventree/widget/drawer.dart"; | ||||
|  | ||||
| class InvenTreeHomePage extends StatefulWidget { | ||||
|  | ||||
|   InvenTreeHomePage({Key? key}) : super(key: key); | ||||
|   const InvenTreeHomePage({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _InvenTreeHomePageState createState() => _InvenTreeHomePageState(); | ||||
| @@ -125,7 +125,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> { | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void _loadProfile() async { | ||||
|   Future <void> _loadProfile() async { | ||||
|  | ||||
|     _profile = await UserProfileDBManager().getSelectedProfile(); | ||||
|  | ||||
|   | ||||
| @@ -1,21 +1,21 @@ | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/app_settings.dart'; | ||||
| import 'package:inventree/barcode.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/app_settings.dart"; | ||||
| import "package:inventree/barcode.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
|  | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/stock_detail.dart'; | ||||
| import 'package:inventree/widget/paginator.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/stock_detail.dart"; | ||||
| import "package:inventree/widget/paginator.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart"; | ||||
|  | ||||
| class LocationDisplayWidget extends StatefulWidget { | ||||
|  | ||||
| @@ -62,7 +62,7 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> { | ||||
|     ); | ||||
|      */ | ||||
|  | ||||
|     if ((location != null) && (InvenTreeAPI().checkPermission('stock_location', 'change'))) { | ||||
|     if ((location != null) && (InvenTreeAPI().checkPermission("stock_location", "change"))) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.edit), | ||||
| @@ -96,7 +96,7 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> { | ||||
|  | ||||
|   List<InvenTreeStockLocation> _sublocations = []; | ||||
|  | ||||
|   String _locationFilter = ''; | ||||
|   String _locationFilter = ""; | ||||
|  | ||||
|   List<InvenTreeStockLocation> get sublocations { | ||||
|      | ||||
| @@ -340,7 +340,7 @@ List<Widget> detailTiles() { | ||||
|  | ||||
|     tiles.add(locationDescriptionCard(includeActions: false)); | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('stock', 'add')) { | ||||
|     if (InvenTreeAPI().checkPermission("stock", "add")) { | ||||
|  | ||||
|       tiles.add( | ||||
|         ListTile( | ||||
| @@ -368,7 +368,7 @@ List<Widget> detailTiles() { | ||||
|  | ||||
|     if (location != null) { | ||||
|       // Stock adjustment actions | ||||
|       if (InvenTreeAPI().checkPermission('stock', 'change')) { | ||||
|       if (InvenTreeAPI().checkPermission("stock", "change")) { | ||||
|         // Scan items into location | ||||
|         tiles.add( | ||||
|             ListTile( | ||||
| @@ -430,7 +430,7 @@ List<Widget> detailTiles() { | ||||
| class SublocationList extends StatelessWidget { | ||||
|   final List<InvenTreeStockLocation> _locations; | ||||
|  | ||||
|   SublocationList(this._locations); | ||||
|   const SublocationList(this._locations); | ||||
|  | ||||
|   void _openLocation(BuildContext context, int pk) { | ||||
|  | ||||
| @@ -446,7 +446,7 @@ class SublocationList extends StatelessWidget { | ||||
|     InvenTreeStockLocation loc = _locations[index]; | ||||
|  | ||||
|     return ListTile( | ||||
|       title: Text('${loc.name}'), | ||||
|       title: Text("${loc.name}"), | ||||
|       subtitle: Text("${loc.description}"), | ||||
|       trailing: Text("${loc.itemcount}"), | ||||
|       onTap: () { | ||||
| @@ -477,7 +477,7 @@ class PaginatedStockList extends StatefulWidget { | ||||
|  | ||||
|   final Map<String, String> filters; | ||||
|  | ||||
|   PaginatedStockList(this.filters); | ||||
|   const PaginatedStockList(this.filters); | ||||
|  | ||||
|   @override | ||||
|   _PaginatedStockListState createState() => _PaginatedStockListState(filters); | ||||
| @@ -516,7 +516,7 @@ class _PaginatedStockListState extends State<PaginatedStockList> { | ||||
|   Future<void> _fetchPage(int pageKey) async { | ||||
|     try { | ||||
|  | ||||
|       Map<String, String> params = this.filters; | ||||
|       Map<String, String> params = filters; | ||||
|  | ||||
|       params["search"] = "${_searchTerm}"; | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| // Pagination related widgets | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| class PaginatedSearchWidget extends StatelessWidget { | ||||
| @@ -44,9 +42,9 @@ class PaginatedSearchWidget extends StatelessWidget { | ||||
|  | ||||
| class NoResultsWidget extends StatelessWidget { | ||||
|  | ||||
|   final String description; | ||||
|   const NoResultsWidget(this.description); | ||||
|  | ||||
|   NoResultsWidget(this.description); | ||||
|   final String description; | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|   | ||||
| @@ -1,23 +1,19 @@ | ||||
| import "dart:io"; | ||||
|  | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/fields.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
|  | ||||
| import 'package:file_picker/file_picker.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:image_picker/image_picker.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
|  | ||||
| import 'dart:io'; | ||||
|  | ||||
| import '../api.dart'; | ||||
| import '../l10.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| class PartAttachmentsWidget extends StatefulWidget { | ||||
|  | ||||
|   PartAttachmentsWidget(this.part, {Key? key}) : super(key: key); | ||||
|   const PartAttachmentsWidget(this.part, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreePart part; | ||||
|  | ||||
| @@ -42,7 +38,7 @@ class _PartAttachmentDisplayState extends RefreshableState<PartAttachmentsWidget | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "change")) { | ||||
|  | ||||
|       // File upload | ||||
|       actions.add( | ||||
|   | ||||
| @@ -1,28 +1,28 @@ | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import 'package:inventree/widget/part_attachments_widget.dart'; | ||||
| import 'package:inventree/widget/part_notes.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/category_display.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/part_image_widget.dart'; | ||||
| import 'package:inventree/widget/stock_detail.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/widget/part_attachments_widget.dart"; | ||||
| import "package:inventree/widget/part_notes.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/category_display.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/part_image_widget.dart"; | ||||
| import "package:inventree/widget/stock_detail.dart"; | ||||
|  | ||||
| import 'location_display.dart'; | ||||
| import "pcakage:inventree/widget/location_display.dart"; | ||||
|  | ||||
|  | ||||
| class PartDetailWidget extends StatefulWidget { | ||||
|  | ||||
|   PartDetailWidget(this.part, {Key? key}) : super(key: key); | ||||
|   const PartDetailWidget(this.part, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreePart part; | ||||
|  | ||||
| @@ -46,7 +46,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'view')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "view")) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.globe), | ||||
| @@ -55,7 +55,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "change")) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.edit), | ||||
| @@ -89,9 +89,9 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|     await part.getTestTemplates(); | ||||
|   } | ||||
|  | ||||
|   void _toggleStar() async { | ||||
|   Future <void> _toggleStar() async { | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'view')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "view")) { | ||||
|       await part.update(values: {"starred": "${!part.starred}"}); | ||||
|       refresh(); | ||||
|     } | ||||
| @@ -327,7 +327,8 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|     } | ||||
|  | ||||
|     // TODO - Add request tests? | ||||
|     if (false && part.isTrackable) { | ||||
|     /* | ||||
|     if (part.isTrackable) { | ||||
|       tiles.add(ListTile( | ||||
|           title: Text(L10().testsRequired), | ||||
|           leading: FaIcon(FontAwesomeIcons.tasks), | ||||
| @@ -336,6 +337,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|         ) | ||||
|       ); | ||||
|     } | ||||
|      */ | ||||
|  | ||||
|     // Notes field | ||||
|     tiles.add( | ||||
| @@ -453,7 +455,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> { | ||||
|       ); | ||||
|     } | ||||
|      | ||||
|     if (false && !part.isActive && InvenTreeAPI().checkPermission('part', 'delete')) { | ||||
|     if (false && !part.isActive && InvenTreeAPI().checkPermission("part", "delete")) { | ||||
|       tiles.add( | ||||
|         ListTile( | ||||
|           title: Text(L10().deletePart), | ||||
|   | ||||
| @@ -1,23 +1,21 @@ | ||||
| import 'dart:io'; | ||||
| import "dart:io"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:image_picker/image_picker.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/foundation.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
|  | ||||
| import '../l10.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/fields.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| class PartImageWidget extends StatefulWidget { | ||||
|  | ||||
|   PartImageWidget(this.part, {Key? key}) : super(key: key); | ||||
|   const PartImageWidget(this.part, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreePart part; | ||||
|  | ||||
| @@ -46,7 +44,7 @@ class _PartImageState extends RefreshableState<PartImageWidget> { | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "change")) { | ||||
|  | ||||
|       // File upload | ||||
|       actions.add( | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter_markdown/flutter_markdown.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter_markdown/flutter_markdown.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| class PartNotesWidget extends StatefulWidget { | ||||
|  | ||||
|   final InvenTreePart part; | ||||
|  | ||||
|   PartNotesWidget(this.part, {Key? key}) : super(key: key); | ||||
|   const PartNotesWidget(this.part, {Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _PartNotesState createState() => _PartNotesState(part); | ||||
| @@ -38,7 +38,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> { | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('part', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("part", "change")) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.edit), | ||||
|   | ||||
| @@ -1,19 +1,19 @@ | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "dart:core"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'dart:core'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/widget/company_detail.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/widget/company_detail.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
|  | ||||
| class PartSupplierWidget extends StatefulWidget { | ||||
|  | ||||
|   PartSupplierWidget(this.part, {Key? key}) : super(key: key); | ||||
|   const PartSupplierWidget(this.part, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreePart part; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
|  | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| /* | ||||
|  * Construct a circular progress indicator | ||||
|   | ||||
| @@ -1,21 +1,20 @@ | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/purchase_order.dart'; | ||||
| import 'package:inventree/widget/company_detail.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| import '../l10.dart'; | ||||
| import 'location_display.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/inventree/purchase_order.dart"; | ||||
| import "package:inventree/widget/company_detail.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/widget/location_display.dart"; | ||||
|  | ||||
|  | ||||
| class PurchaseOrderDetailWidget extends StatefulWidget { | ||||
|  | ||||
|   PurchaseOrderDetailWidget(this.order, {Key? key}): super(key: key); | ||||
|   const PurchaseOrderDetailWidget(this.order, {Key? key}): super(key: key); | ||||
|  | ||||
|   final InvenTreePurchaseOrder order; | ||||
|  | ||||
| @@ -72,7 +71,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg | ||||
|  | ||||
|   } | ||||
|  | ||||
|   void editOrder(BuildContext context) async { | ||||
|   Future <void> editOrder(BuildContext context) async { | ||||
|  | ||||
|     order.editForm( | ||||
|       context, | ||||
|   | ||||
| @@ -1,23 +1,22 @@ | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; | ||||
| import 'package:inventree/inventree/company.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/paginator.dart'; | ||||
| import 'package:inventree/widget/purchase_order_detail.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart"; | ||||
|  | ||||
| import '../l10.dart'; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/inventree/purchase_order.dart'; | ||||
| import "package:inventree/inventree/company.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/paginator.dart"; | ||||
| import "package:inventree/widget/purchase_order_detail.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/inventree/purchase_order.dart"; | ||||
|  | ||||
| /* | ||||
|  * Widget class for displaying a list of Purchase Orders | ||||
|  */ | ||||
| class PurchaseOrderListWidget extends StatefulWidget { | ||||
|  | ||||
|   PurchaseOrderListWidget({this.filters = const {}, Key? key}) : super(key: key); | ||||
|   const PurchaseOrderListWidget({this.filters = const {}, Key? key}) : super(key: key); | ||||
|  | ||||
|   final Map<String, String> filters; | ||||
|  | ||||
| @@ -100,7 +99,7 @@ class _PaginatedPurchaseOrderListState extends State<_PaginatedPurchaseOrderList | ||||
|  | ||||
|       // Copy across provided filters | ||||
|       for (String key in filters.keys) { | ||||
|         params[key] = filters[key] ?? ''; | ||||
|         params[key] = filters[key] ?? ""; | ||||
|       } | ||||
|  | ||||
|       final page = await InvenTreePurchaseOrder().listPaginated( | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import 'package:inventree/widget/drawer.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/widgets.dart'; | ||||
| import "package:inventree/widget/drawer.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter/widgets.dart"; | ||||
|  | ||||
|  | ||||
| abstract class RefreshableState<T extends StatefulWidget> extends State<T> { | ||||
| @@ -32,6 +32,7 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> { | ||||
|  | ||||
|   String getAppBarTitle(BuildContext context) { return "App Bar Title"; } | ||||
|  | ||||
|   @override | ||||
|   void initState() { | ||||
|     super.initState(); | ||||
|     WidgetsBinding.instance?.addPostFrameCallback((_) => onBuild(_context!)); | ||||
|   | ||||
| @@ -1,17 +1,17 @@ | ||||
|  | ||||
| import 'package:inventree/widget/part_detail.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:inventree/widget/stock_detail.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/widget/part_detail.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:inventree/widget/stock_detail.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
|  | ||||
| import '../api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| // TODO - Refactor duplicate code in this file! | ||||
|  | ||||
| @@ -101,7 +101,7 @@ class PartSearchDelegate extends SearchDelegate<InvenTreePart?> { | ||||
|       IconButton( | ||||
|         icon: FaIcon(FontAwesomeIcons.backspace), | ||||
|         onPressed: () { | ||||
|           query = ''; | ||||
|           query = ""; | ||||
|           search(context); | ||||
|         }, | ||||
|       ), | ||||
| @@ -119,7 +119,7 @@ class PartSearchDelegate extends SearchDelegate<InvenTreePart?> { | ||||
|     return IconButton( | ||||
|       icon: Icon(Icons.arrow_back), | ||||
|       onPressed: () { | ||||
|         this.close(context, null); | ||||
|         close(context, null); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| @@ -289,7 +289,7 @@ class StockSearchDelegate extends SearchDelegate<InvenTreeStockItem?> { | ||||
|       IconButton( | ||||
|         icon: FaIcon(FontAwesomeIcons.backspace), | ||||
|         onPressed: () { | ||||
|           query = ''; | ||||
|           query = ""; | ||||
|           search(context); | ||||
|         }, | ||||
|       ), | ||||
| @@ -307,7 +307,7 @@ class StockSearchDelegate extends SearchDelegate<InvenTreeStockItem?> { | ||||
|     return IconButton( | ||||
|         icon: Icon(Icons.arrow_back), | ||||
|         onPressed: () { | ||||
|           this.close(context, null); | ||||
|           close(context, null); | ||||
|         } | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -8,11 +8,11 @@ | ||||
|  * | Text          <icon> | | ||||
|  */ | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:one_context/one_context.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:one_context/one_context.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
|  | ||||
| void showSnackIcon(String text, {IconData? icon, Function()? onAction, bool? success, String? actionText}) { | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
|  | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/app_colors.dart"; | ||||
|  | ||||
| class Spinner extends StatefulWidget { | ||||
|   final IconData? icon; | ||||
|   | ||||
| @@ -1,20 +1,18 @@ | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/part_detail.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/part_detail.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
|  | ||||
| import '../api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
|  | ||||
| class StarredPartWidget extends StatefulWidget { | ||||
|  | ||||
|   StarredPartWidget({Key? key}) : super(key: key); | ||||
|   const StarredPartWidget({Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _StarredPartState createState() => _StarredPartState(); | ||||
|   | ||||
| @@ -1,30 +1,30 @@ | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/barcode.dart'; | ||||
| import 'package:inventree/inventree/model.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/widget/location_display.dart'; | ||||
| import 'package:inventree/widget/part_detail.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import 'package:inventree/widget/stock_item_test_results.dart'; | ||||
| import 'package:inventree/widget/stock_notes.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/barcode.dart"; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/widget/dialogs.dart"; | ||||
| import "package:inventree/widget/fields.dart"; | ||||
| import "package:inventree/widget/location_display.dart"; | ||||
| import "package:inventree/widget/part_detail.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
| import "package:inventree/widget/stock_item_test_results.dart"; | ||||
| import "package:inventree/widget/stock_notes.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'package:inventree/api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
| import 'package:dropdown_search/dropdown_search.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import "package:dropdown_search/dropdown_search.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
| class StockDetailWidget extends StatefulWidget { | ||||
|  | ||||
|   StockDetailWidget(this.item, {Key? key}) : super(key: key); | ||||
|   const StockDetailWidget(this.item, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreeStockItem item; | ||||
|  | ||||
| @@ -53,7 +53,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|  | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('stock', 'view')) { | ||||
|     if (InvenTreeAPI().checkPermission("stock", "view")) { | ||||
|       actions.add( | ||||
|         IconButton( | ||||
|           icon: FaIcon(FontAwesomeIcons.globe), | ||||
| @@ -62,7 +62,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('stock', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("stock", "change")) { | ||||
|       actions.add( | ||||
|           IconButton( | ||||
|             icon: FaIcon(FontAwesomeIcons.edit), | ||||
| @@ -99,13 +99,13 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     await item.reload(); | ||||
|  | ||||
|     // Request part information | ||||
|     part = await InvenTreePart().get(item.partId) as InvenTreePart; | ||||
|     part = await InvenTreePart().get(item.partId) as InvenTreePart?; | ||||
|  | ||||
|     // Request test results... | ||||
|     await item.getTestResults(); | ||||
|   } | ||||
|  | ||||
|   void _editStockItem(BuildContext context) async { | ||||
|   Future <void> _editStockItem(BuildContext context) async { | ||||
|  | ||||
|     var fields = InvenTreeStockItem().formFields(); | ||||
|  | ||||
| @@ -125,7 +125,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|  | ||||
|   } | ||||
|  | ||||
|   void _addStock() async { | ||||
|   Future <void> _addStock() async { | ||||
|  | ||||
|     double quantity = double.parse(_quantityController.text); | ||||
|     _quantityController.clear(); | ||||
| @@ -138,7 +138,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     refresh(); | ||||
|   } | ||||
|  | ||||
|   void _addStockDialog() async { | ||||
|   Future <void> _addStockDialog() async { | ||||
|  | ||||
|     _quantityController.clear(); | ||||
|     _notesController.clear(); | ||||
| @@ -171,7 +171,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _removeStock() async { | ||||
|   Future <void> _removeStock() async { | ||||
|  | ||||
|     double quantity = double.parse(_quantityController.text); | ||||
|     _quantityController.clear(); | ||||
| @@ -211,7 +211,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _countStock() async { | ||||
|   Future <void> _countStock() async { | ||||
|  | ||||
|     double quantity = double.parse(_quantityController.text); | ||||
|     _quantityController.clear(); | ||||
| @@ -223,7 +223,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     refresh(); | ||||
|   } | ||||
|  | ||||
|   void _countStockDialog() async { | ||||
|   Future <void> _countStockDialog() async { | ||||
|  | ||||
|     _quantityController.text = item.quantity.toString(); | ||||
|     _notesController.clear(); | ||||
| @@ -251,9 +251,9 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|   } | ||||
|  | ||||
|  | ||||
|   void _unassignBarcode(BuildContext context) async { | ||||
|   Future<void> _unassignBarcode(BuildContext context) async { | ||||
|  | ||||
|     final bool result = await item.update(values: {'uid': ''}); | ||||
|     final bool result = await item.update(values: {"uid": ""}); | ||||
|  | ||||
|     if (result) { | ||||
|       showSnackIcon( | ||||
| @@ -271,7 +271,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|   } | ||||
|  | ||||
|  | ||||
|   void _transferStock(int locationId) async { | ||||
|   Future <void> _transferStock(int locationId) async { | ||||
|  | ||||
|     double quantity = double.tryParse(_quantityController.text) ?? item.quantity; | ||||
|     String notes = _notesController.text; | ||||
| @@ -288,7 +288,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void _transferStockDialog(BuildContext context) async { | ||||
|   Future <void> _transferStockDialog(BuildContext context) async { | ||||
|  | ||||
|     int? location_pk; | ||||
|  | ||||
| @@ -349,13 +349,13 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|             hint: L10().searchLocation, | ||||
|             onChanged: null, | ||||
|             itemAsString: (dynamic location) { | ||||
|               return (location['pathstring'] ?? '') as String; | ||||
|               return (location["pathstring"] ?? "") as String; | ||||
|             }, | ||||
|             onSaved: (dynamic location) { | ||||
|               if (location == null) { | ||||
|                 location_pk = null; | ||||
|               } else { | ||||
|                 location_pk = location['pk'] as int; | ||||
|                 location_pk = location["pk"] as int; | ||||
|               } | ||||
|             }, | ||||
|             isFilteredOnline: true, | ||||
| @@ -503,7 +503,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|  | ||||
|     // Supplier part? | ||||
|     // TODO: Display supplier part info page? | ||||
|     if (false && item.supplierPartId > 0) { | ||||
|     /* | ||||
|     if (item.supplierPartId > 0) { | ||||
|       tiles.add( | ||||
|         ListTile( | ||||
|           title: Text("${item.supplierName}"), | ||||
| @@ -514,6 +515,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|         ) | ||||
|       ); | ||||
|     } | ||||
|      */ | ||||
|  | ||||
|     if (item.link.isNotEmpty) { | ||||
|       tiles.add( | ||||
| @@ -559,7 +561,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     // TODO - Is this stock item linked to a PurchaseOrder? | ||||
|  | ||||
|     // TODO - Re-enable stock item history display | ||||
|     if (false && item.trackingItemCount > 0) { | ||||
|     /* | ||||
|     if (item.trackingItemCount > 0) { | ||||
|       tiles.add( | ||||
|         ListTile( | ||||
|           title: Text(L10().history), | ||||
| @@ -574,6 +577,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|         ) | ||||
|       ); | ||||
|     } | ||||
|      */ | ||||
|  | ||||
|     // Notes field | ||||
|     tiles.add( | ||||
| @@ -600,7 +604,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|     tiles.add(headerTile()); | ||||
|  | ||||
|     // First check that the user has the required permissions to adjust stock | ||||
|     if (!InvenTreeAPI().checkPermission('stock', 'change')) { | ||||
|     if (!InvenTreeAPI().checkPermission("stock", "change")) { | ||||
|       tiles.add( | ||||
|         ListTile( | ||||
|           title: Text(L10().permissionRequired), | ||||
| @@ -710,12 +714,11 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | ||||
|       items: <BottomNavigationBarItem> [ | ||||
|         BottomNavigationBarItem( | ||||
|           icon: FaIcon(FontAwesomeIcons.infoCircle), | ||||
|           title: Text(L10().details), | ||||
|           label: L10().details, | ||||
|         ), | ||||
|         BottomNavigationBarItem( | ||||
|           icon: FaIcon(FontAwesomeIcons.wrench), | ||||
|           title: Text(L10().actions), | ||||
|         ), | ||||
|           label: L10().actions,        ), | ||||
|       ] | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -1,27 +1,21 @@ | ||||
| import 'package:inventree/api_form.dart'; | ||||
| import 'package:inventree/app_colors.dart'; | ||||
| import 'package:inventree/inventree/part.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/inventree/model.dart'; | ||||
| import 'package:inventree/api.dart'; | ||||
| import 'package:inventree/widget/dialogs.dart'; | ||||
| import 'package:inventree/widget/fields.dart'; | ||||
| import 'package:inventree/widget/progress.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
| import "package:inventree/app_colors.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/widget/progress.dart"; | ||||
|  | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
|  | ||||
|  | ||||
| class StockItemTestResultsWidget extends StatefulWidget { | ||||
|  | ||||
|   StockItemTestResultsWidget(this.item, {Key? key}) : super(key: key); | ||||
|   const StockItemTestResultsWidget(this.item, {Key? key}) : super(key: key); | ||||
|  | ||||
|   final InvenTreeStockItem item; | ||||
|  | ||||
| @@ -32,8 +26,6 @@ class StockItemTestResultsWidget extends StatefulWidget { | ||||
|  | ||||
| class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestResultsWidget> { | ||||
|  | ||||
|   final _addResultKey = GlobalKey<FormState>(); | ||||
|  | ||||
|   @override | ||||
|   String getAppBarTitle(BuildContext context) => L10().testResults; | ||||
|  | ||||
| @@ -59,7 +51,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes | ||||
|  | ||||
|   _StockItemTestResultDisplayState(this.item); | ||||
|  | ||||
|   void addTestResult(BuildContext context, {String name = '', bool nameIsEditable = true, bool result = false, String value = '', bool valueRequired = false, bool attachmentRequired = false}) async  { | ||||
|   Future <void> addTestResult(BuildContext context, {String name = "", bool nameIsEditable = true, bool result = false, String value = "", bool valueRequired = false, bool attachmentRequired = false}) async  { | ||||
|  | ||||
|     InvenTreeStockItemTestResult().createForm( | ||||
|       context, | ||||
| @@ -165,7 +157,6 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes | ||||
|       String _test = ""; | ||||
|       bool _result = false; | ||||
|       String _value = ""; | ||||
|       String _notes = ""; | ||||
|  | ||||
|       FaIcon _icon = FaIcon(FontAwesomeIcons.questionCircle, color: COLOR_BLUE); | ||||
|       bool _valueRequired = false; | ||||
| @@ -175,8 +166,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes | ||||
|         _result = item.passFailStatus(); | ||||
|         _test = item.testName; | ||||
|         _required = item.required; | ||||
|         _value = item.latestResult()?.value ?? ''; | ||||
|         _notes = item.latestResult()?.notes ?? ''; | ||||
|         _value = item.latestResult()?.value ?? ""; | ||||
|         _valueRequired = item.requiresValue; | ||||
|         _attachmentRequired = item.requiresAttachment; | ||||
|       } else if (item is InvenTreeStockItemTestResult) { | ||||
| @@ -184,7 +174,6 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes | ||||
|         _test = item.testName; | ||||
|         _required = false; | ||||
|         _value = item.value; | ||||
|         _notes = item.notes; | ||||
|       } | ||||
|  | ||||
|       if (_result == true) { | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
|  | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/inventree/stock.dart'; | ||||
| import 'package:inventree/widget/refreshable_state.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter_markdown/flutter_markdown.dart'; | ||||
| import 'package:inventree/l10.dart'; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
| import "package:inventree/widget/refreshable_state.dart"; | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter_markdown/flutter_markdown.dart"; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| import '../api.dart'; | ||||
| import "package:inventree/api.dart"; | ||||
|  | ||||
|  | ||||
| class StockNotesWidget extends StatefulWidget { | ||||
|  | ||||
|   final InvenTreeStockItem item; | ||||
|  | ||||
|   StockNotesWidget(this.item, {Key? key}) : super(key: key); | ||||
|   const StockNotesWidget(this.item, {Key? key}) : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _StockNotesState createState() => _StockNotesState(item); | ||||
| @@ -39,7 +39,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> { | ||||
|   List<Widget> getAppBarActions(BuildContext context) { | ||||
|     List<Widget> actions = []; | ||||
|  | ||||
|     if (InvenTreeAPI().checkPermission('stock', 'change')) { | ||||
|     if (InvenTreeAPI().checkPermission("stock", "change")) { | ||||
|       actions.add( | ||||
|           IconButton( | ||||
|               icon: FaIcon(FontAwesomeIcons.edit), | ||||
|   | ||||
| @@ -1,12 +1,10 @@ | ||||
| import "package:flutter/cupertino.dart"; | ||||
| import "package:flutter/material.dart"; | ||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||
| import "package:inventree/inventree/sentry.dart"; | ||||
| import "package:inventree/widget/snacks.dart"; | ||||
|  | ||||
|  | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:font_awesome_flutter/font_awesome_flutter.dart'; | ||||
| import 'package:inventree/inventree/sentry.dart'; | ||||
| import 'package:inventree/widget/snacks.dart'; | ||||
|  | ||||
| import '../l10.dart'; | ||||
| import "package:inventree/l10.dart"; | ||||
|  | ||||
| class SubmitFeedbackWidget extends StatefulWidget { | ||||
|  | ||||
| @@ -18,7 +16,7 @@ class SubmitFeedbackWidget extends StatefulWidget { | ||||
|  | ||||
| class _SubmitFeedbackState extends State<SubmitFeedbackWidget> { | ||||
|  | ||||
|   final _formkey = new GlobalKey<FormState>(); | ||||
|   final _formkey = GlobalKey<FormState>(); | ||||
|  | ||||
|   String message = ""; | ||||
|  | ||||
| @@ -61,8 +59,6 @@ class _SubmitFeedbackState extends State<SubmitFeedbackWidget> { | ||||
|         key: _formkey, | ||||
|         child: SingleChildScrollView( | ||||
|           child: Column( | ||||
|             mainAxisAlignment: MainAxisAlignment.start, | ||||
|             mainAxisSize: MainAxisSize.max, | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
|             children: [ | ||||
|               TextFormField( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user