2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

More linting work

This commit is contained in:
Oliver 2021-09-28 20:24:55 +10:00
parent c1152ee286
commit ad0cc36540
50 changed files with 904 additions and 907 deletions

View File

@ -1,7 +1,9 @@
include: package:lint/analysis_options.yaml include: package:lint/analysis_options.yaml
analyzer: analyzer:
exclude: [build/**] exclude:
- [build/**]
- lib/generated/**
language: language:
strict-raw-types: true strict-raw-types: true
strong-mode: strong-mode:
@ -17,7 +19,41 @@ linter:
# Make constructors the first thing in every class # Make constructors the first thing in every class
sort_constructors_first: true sort_constructors_first: true
prefer_single_quotes: true prefer_double_quotes: true
prefer_final_locals: false
prefer_const_constructors: false
prefer_final_in_for_each: false
use_build_context_synchronously: false
avoid_redundant_argument_values: false
unnecessary_brace_in_string_interps: false
unnecessary_string_interpolations: false
no_logic_in_create_state: false
parameter_assignments: false
non_constant_identifier_names: false
constant_identifier_names: false
package_prefixed_library_names: false
prefer_const_literals_to_create_immutables: false
avoid_print: false
avoid_positional_boolean_parameters: false
prefer_final_fields: false
sort_child_properties_last: false
# Blindly follow the Flutter code style, which prefers types everywhere # Blindly follow the Flutter code style, which prefers types everywhere
always_specify_types: true always_specify_types: false

View File

@ -1,25 +1,25 @@
import 'dart:async'; import "dart:async";
import 'dart:convert'; import "dart:convert";
import 'dart:io'; import "dart:io";
import 'package:flutter/foundation.dart'; import "package:flutter/foundation.dart";
import 'package:http/http.dart' as http; import "package:http/http.dart" as http;
import 'package:intl/intl.dart'; import "package:intl/intl.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:open_file/open_file.dart'; import "package:open_file/open_file.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:cached_network_image/cached_network_image.dart'; import "package:cached_network_image/cached_network_image.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import "package:flutter_cache_manager/flutter_cache_manager.dart";
import 'package:inventree/widget/dialogs.dart'; import "package:inventree/widget/dialogs.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/user_profile.dart'; import "package:inventree/user_profile.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import 'package:path_provider/path_provider.dart'; import "package:path_provider/path_provider.dart";
/* /*
@ -158,11 +158,12 @@ class InvenTreeAPI {
String _makeUrl(String url) { String _makeUrl(String url) {
// Strip leading slash // Strip leading slash
if (url.startsWith('/')) { if (url.startsWith("/")) {
url = url.substring(1, url.length); url = url.substring(1, url.length);
} }
url = url.replaceAll('//', '/'); // Prevent double-slash
url = url.replaceAll("//", "/");
return baseUrl + url; return baseUrl + url;
} }
@ -175,7 +176,7 @@ class InvenTreeAPI {
if (endpoint.startsWith("/api/") || endpoint.startsWith("api/")) { if (endpoint.startsWith("/api/") || endpoint.startsWith("api/")) {
return _makeUrl(endpoint); return _makeUrl(endpoint);
} else { } else {
return _makeUrl("/api/" + endpoint); return _makeUrl("/api/${endpoint}");
} }
} }
@ -210,10 +211,10 @@ class InvenTreeAPI {
} }
// Server instance information // Server instance information
String instance = ''; String instance = "";
// Server version information // Server version information
String _version = ''; String _version = "";
// API version of the connected server // API version of the connected server
int _apiVersion = 1; int _apiVersion = 1;
@ -272,8 +273,8 @@ class InvenTreeAPI {
return false; return false;
} }
if (!address.endsWith('/')) { if (!address.endsWith("/")) {
address = address + '/'; address = address + "/";
} }
/* TODO: Better URL validation /* TODO: Better URL validation
* - If not a valid URL, return error * - If not a valid URL, return error
@ -307,11 +308,11 @@ class InvenTreeAPI {
} }
// Record server information // Record server information
_version = (data["version"] ?? '') as String; _version = (data["version"] ?? "") as String;
instance = (data['instance'] ?? '') as String; instance = (data["instance"] ?? "") as String;
// Default API version is 1 if not provided // Default API version is 1 if not provided
_apiVersion = (data['apiVersion'] ?? 1) as int; _apiVersion = (data["apiVersion"] ?? 1) as int;
if (_apiVersion < _minApiVersion) { if (_apiVersion < _minApiVersion) {
@ -388,7 +389,7 @@ class InvenTreeAPI {
_connected = false; _connected = false;
_connecting = false; _connecting = false;
_token = ''; _token = "";
profile = null; profile = null;
} }
@ -435,7 +436,7 @@ class InvenTreeAPI {
// Next we request the permissions assigned to the current user // Next we request the permissions assigned to the current user
// Note: 2021-02-27 this "roles" feature for the API was just introduced. // 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 // We will return immediately, but request the user roles in the background
var response = await get(_URL_GET_ROLES, expectedStatusCode: 200); var response = await get(_URL_GET_ROLES, expectedStatusCode: 200);
@ -446,9 +447,9 @@ class InvenTreeAPI {
var data = response.asMap(); var data = response.asMap();
if (data.containsKey('roles')) { if (data.containsKey("roles")) {
// Save a local copy of the user 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 * Check if the user has the given role.permission assigned
*e *e
* e.g. 'part', 'change' * e.g. "part", "change"
*/ */
// If we do not have enough information, assume permission is allowed // If we do not have enough information, assume permission is allowed
@ -489,9 +490,9 @@ class InvenTreeAPI {
if (request == null) { if (request == null) {
// Return an "invalid" APIResponse // Return an "invalid" APIResponse
return new APIResponse( return APIResponse(
url: url, url: url,
method: 'PATCH', method: "PATCH",
error: "HttpClientRequest is null" error: "HttpClientRequest is null"
); );
} }
@ -535,7 +536,7 @@ class InvenTreeAPI {
HttpClientRequest? _request; HttpClientRequest? _request;
var client = createClient(true); var client = createClient(allowBadCert: true);
// Attempt to open a connection to the server // Attempt to open a connection to the server
try { try {
@ -543,8 +544,8 @@ class InvenTreeAPI {
// Set headers // Set headers
_request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader()); _request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader());
_request.headers.set(HttpHeaders.acceptHeader, 'application/json'); _request.headers.set(HttpHeaders.acceptHeader, "application/json");
_request.headers.set(HttpHeaders.contentTypeHeader, 'application/json'); _request.headers.set(HttpHeaders.contentTypeHeader, "application/json");
_request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale()); _request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale());
} on SocketException catch (error) { } on SocketException catch (error) {
@ -684,9 +685,9 @@ class InvenTreeAPI {
if (request == null) { if (request == null) {
// Return an "invalid" APIResponse // Return an "invalid" APIResponse
return new APIResponse( return APIResponse(
url: url, url: url,
method: 'OPTIONS' method: "OPTIONS"
); );
} }
@ -703,9 +704,9 @@ class InvenTreeAPI {
if (request == null) { if (request == null) {
// Return an "invalid" APIResponse // Return an "invalid" APIResponse
return new APIResponse( return APIResponse(
url: url, 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? // TODO - Introspection of actual certificate?
allowBadCert = true;
if (allowBadCert) { if (allowBadCert) {
return true; return true;
} else { } else {
@ -734,7 +733,7 @@ class InvenTreeAPI {
); );
return false; return false;
} }
}); };
// Set the connection timeout // Set the connection timeout
client.connectionTimeout = Duration(seconds: 30); client.connectionTimeout = Duration(seconds: 30);
@ -746,7 +745,7 @@ class InvenTreeAPI {
* Initiate a HTTP request to the server * Initiate a HTTP request to the server
* *
* @param url is the API endpoint * @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 * @param params is the request parameters
*/ */
Future<HttpClientRequest?> apiRequest(String url, String method, {Map<String, String> urlParams = const {}}) async { Future<HttpClientRequest?> apiRequest(String url, String method, {Map<String, String> urlParams = const {}}) async {
@ -763,7 +762,7 @@ class InvenTreeAPI {
} }
// Remove extraneous character if present // Remove extraneous character if present
if (_url.endsWith('&')) { if (_url.endsWith("&")) {
_url = _url.substring(0, _url.length - 1); _url = _url.substring(0, _url.length - 1);
} }
@ -781,7 +780,7 @@ class InvenTreeAPI {
HttpClientRequest? _request; HttpClientRequest? _request;
var client = createClient(true); var client = createClient(allowBadCert: true);
// Attempt to open a connection to the server // Attempt to open a connection to the server
try { try {
@ -789,8 +788,8 @@ class InvenTreeAPI {
// Set headers // Set headers
_request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader()); _request.headers.set(HttpHeaders.authorizationHeader, _authorizationHeader());
_request.headers.set(HttpHeaders.acceptHeader, 'application/json'); _request.headers.set(HttpHeaders.acceptHeader, "application/json");
_request.headers.set(HttpHeaders.contentTypeHeader, 'application/json'); _request.headers.set(HttpHeaders.contentTypeHeader, "application/json");
_request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale()); _request.headers.set(HttpHeaders.acceptLanguageHeader, Intl.getCurrentLocale());
return _request; return _request;
@ -824,7 +823,7 @@ class InvenTreeAPI {
request.add(encoded_data); request.add(encoded_data);
} }
APIResponse response = new APIResponse( APIResponse response = APIResponse(
method: request.method, method: request.method,
url: request.uri.toString() url: request.uri.toString()
); );
@ -837,18 +836,7 @@ class InvenTreeAPI {
// If the server returns a server error code, alert the user // If the server returns a server error code, alert the user
if (_response.statusCode >= 500) { if (_response.statusCode >= 500) {
showStatusCodeError(_response.statusCode); showStatusCodeError(_response.statusCode);
} else {
response.data = await responseToJson(_response) ?? {};
if (statusCode != null) {
// Expected status code not returned
if (statusCode != _response.statusCode) {
showStatusCodeError(_response.statusCode);
}
// Report any server errors
if (_response.statusCode >= 500) {
sentryReportMessage( sentryReportMessage(
"Server error", "Server error",
context: { context: {
@ -860,6 +848,15 @@ class InvenTreeAPI {
"responseData": response.data.toString(), "responseData": response.data.toString(),
} }
); );
} else {
response.data = await responseToJson(_response) ?? {};
if (statusCode != null) {
// Expected status code not returned
if (statusCode != _response.statusCode) {
showStatusCodeError(_response.statusCode);
} }
} }
} }
@ -930,9 +927,9 @@ class InvenTreeAPI {
if (request == null) { if (request == null) {
// Return an "invalid" APIResponse // Return an "invalid" APIResponse
return new APIResponse( return APIResponse(
url: url, url: url,
method: 'GET', method: "GET",
error: "HttpClientRequest is null", error: "HttpClientRequest is null",
); );
} }
@ -945,8 +942,8 @@ class InvenTreeAPI {
var headers = Map<String, String>(); var headers = Map<String, String>();
headers[HttpHeaders.authorizationHeader] = _authorizationHeader(); headers[HttpHeaders.authorizationHeader] = _authorizationHeader();
headers[HttpHeaders.acceptHeader] = 'application/json'; headers[HttpHeaders.acceptHeader] = "application/json";
headers[HttpHeaders.contentTypeHeader] = 'application/json'; headers[HttpHeaders.contentTypeHeader] = "application/json";
headers[HttpHeaders.acceptLanguageHeader] = Intl.getCurrentLocale(); headers[HttpHeaders.acceptLanguageHeader] = Intl.getCurrentLocale();
return headers; return headers;
@ -956,7 +953,7 @@ class InvenTreeAPI {
if (_token.isNotEmpty) { if (_token.isNotEmpty) {
return "Token $_token"; return "Token $_token";
} else if (profile != null) { } else if (profile != null) {
return "Basic " + base64Encode(utf8.encode('${profile?.username}:${profile?.password}')); return "Basic " + base64Encode(utf8.encode("${profile?.username}:${profile?.password}"));
} else { } else {
return ""; return "";
} }

View File

@ -1,22 +1,22 @@
import 'dart:ui'; import "dart:ui";
import 'dart:io'; import "dart:io";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:dropdown_search/dropdown_search.dart'; import "package:dropdown_search/dropdown_search.dart";
import 'package:date_field/date_field.dart'; import "package:date_field/date_field.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/widget/dialogs.dart'; import "package:inventree/widget/dialogs.dart";
import 'package:inventree/widget/fields.dart'; import "package:inventree/widget/fields.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
@ -41,24 +41,24 @@ class APIFormField {
dynamic initial_data; dynamic initial_data;
// Get the "api_url" associated with a related field // 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 // 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? // 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? // 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) // 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 // Get the "default" as a string
dynamic get defaultValue => data['default']; dynamic get defaultValue => data["default"];
Map<String, String> get filters { Map<String, String> get filters {
@ -96,7 +96,7 @@ class APIFormField {
// Return the error message associated with this field // Return the error message associated with this field
List<String> errorMessages() { List<String> errorMessages() {
List<dynamic> errors = (data['errors'] ?? []) as List<dynamic>; List<dynamic> errors = (data["errors"] ?? []) as List<dynamic>;
List<String> messages = []; List<String> messages = [];
@ -108,15 +108,15 @@ class APIFormField {
} }
// Is this field required? // 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>; List<dynamic> get choices => (data["choices"] ?? []) as List<dynamic>;
@ -193,13 +193,13 @@ class APIFormField {
labelText: label, labelText: label,
labelStyle: _labelStyle(), labelStyle: _labelStyle(),
), ),
initialValue: DateTime.tryParse((value ?? '') as String), initialValue: DateTime.tryParse((value ?? "") as String),
autovalidateMode: AutovalidateMode.always, autovalidateMode: AutovalidateMode.always,
validator: (e) { validator: (e) {
// TODO // TODO
}, },
onDateSelected: (DateTime dt) { 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 // Check if the current value is within the allowed values
for (var opt in choices) { for (var opt in choices) {
if (opt['value'] == value) { if (opt["value"] == value) {
_initial = opt; _initial = opt;
break; break;
} }
@ -267,13 +267,13 @@ class APIFormField {
autoFocusSearchBox: true, autoFocusSearchBox: true,
showClearButton: !required, showClearButton: !required,
itemAsString: (dynamic item) { itemAsString: (dynamic item) {
return (item['display_name'] ?? '') as String; return (item["display_name"] ?? "") as String;
}, },
onSaved: (item) { onSaved: (item) {
if (item == null) { if (item == null) {
data['value'] = null; data["value"] = null;
} else { } else {
data['value'] = item['value']; data["value"] = item["value"];
} }
} }
); );
@ -294,7 +294,7 @@ class APIFormField {
keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true), keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true),
validator: (value) { validator: (value) {
double? quantity = double.tryParse(value.toString()) ?? null; double? quantity = double.tryParse(value.toString());
if (quantity == null) { if (quantity == null) {
return L10().numberInvalid; return L10().numberInvalid;
@ -335,7 +335,7 @@ class APIFormField {
List<dynamic> results = []; List<dynamic> results = [];
for (var result in response.data['results'] ?? []) { for (var result in response.data["results"] ?? []) {
results.add(result); results.add(result);
} }
@ -371,9 +371,9 @@ class APIFormField {
}, },
onSaved: (item) { onSaved: (item) {
if (item != null) { if (item != null) {
data['value'] = item['pk'] ?? null; data["value"] = item["pk"];
} else { } else {
data['value'] = null; data["value"] = null;
} }
}, },
isFilteredOnline: true, isFilteredOnline: true,
@ -386,7 +386,7 @@ class APIFormField {
return false; return false;
} }
return item['pk'] == selectedItem['pk']; return item["pk"] == selectedItem["pk"];
} }
); );
} }
@ -443,7 +443,7 @@ class APIFormField {
) : null, ) : null,
); );
case "owner": case "owner":
String name = (item["name"] ?? '') as String; String name = (item["name"] ?? "") as String;
bool isGroup = (item["label"] ?? "") == "group"; bool isGroup = (item["label"] ?? "") == "group";
return ListTile( return ListTile(
title: Text(name), title: Text(name),
@ -478,7 +478,7 @@ class APIFormField {
readOnly: readOnly, readOnly: readOnly,
maxLines: multiline ? null : 1, maxLines: multiline ? null : 1,
expands: false, expands: false,
initialValue: (value ?? '') as String, initialValue: (value ?? "") as String,
onSaved: (val) { onSaved: (val) {
data["value"] = val; data["value"] = val;
}, },
@ -500,7 +500,7 @@ class APIFormField {
helperStyle: _helperStyle(), helperStyle: _helperStyle(),
initial: value as bool, initial: value as bool,
onSaved: (val) { 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]; dynamic value = modelData[key];
if (availableFields.containsKey(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 // Update field errors
for (var field in fields) { for (var field in fields) {
field.data['errors'] = response.data[field.name]; field.data["errors"] = response.data[field.name];
} }
break; break;
// TODO: Other status codes? // TODO: Other status codes?

View File

@ -1,6 +1,6 @@
import 'dart:ui'; import "dart:ui";
const Color COLOR_GRAY = Color.fromRGBO(50, 50, 50, 1); const Color COLOR_GRAY = Color.fromRGBO(50, 50, 50, 1);
const Color COLOR_GRAY_LIGHT = Color.fromRGBO(150, 150, 150, 1); const Color COLOR_GRAY_LIGHT = Color.fromRGBO(150, 150, 150, 1);

View File

@ -2,8 +2,8 @@
* Class for managing app-level configuration options * Class for managing app-level configuration options
*/ */
import 'package:sembast/sembast.dart'; import "package:sembast/sembast.dart";
import 'package:inventree/preferences.dart'; import "package:inventree/preferences.dart";
class InvenTreeSettingsManager { class InvenTreeSettingsManager {

View File

@ -1,26 +1,26 @@
import 'package:inventree/app_settings.dart'; import "dart:io";
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: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:qr_code_scanner/qr_code_scanner.dart";
import 'package:inventree/inventree/part.dart';
import 'package:inventree/l10.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/api.dart";
import 'package:inventree/widget/part_detail.dart';
import 'package:inventree/widget/stock_detail.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 { class BarcodeHandler {
@ -38,7 +38,7 @@ class BarcodeHandler {
QRViewController? _controller; QRViewController? _controller;
void successTone() async { Future<void> successTone() async {
final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; 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; final bool en = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool;
@ -120,9 +120,9 @@ class BarcodeHandler {
"errorDetail": response.errorDetail, "errorDetail": response.errorDetail,
} }
); );
} else if (data.containsKey('error')) { } else if (data.containsKey("error")) {
onBarcodeUnknown(context, data); onBarcodeUnknown(context, data);
} else if (data.containsKey('success')) { } else if (data.containsKey("success")) {
onBarcodeMatched(context, data); onBarcodeMatched(context, data);
} else { } else {
onBarcodeUnhandled(context, data); onBarcodeUnhandled(context, data);
@ -158,9 +158,9 @@ class BarcodeScanHandler extends BarcodeHandler {
int pk = -1; int pk = -1;
// A stocklocation has been passed? // 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) { 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) { if (pk > 0) {
@ -208,9 +208,9 @@ class BarcodeScanHandler extends BarcodeHandler {
success: false 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) { if (pk > 0) {
@ -278,7 +278,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
failureTone(); 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( showSnackIcon(
L10().barcodeInUse, L10().barcodeInUse,
icon: FontAwesomeIcons.qrcode, icon: FontAwesomeIcons.qrcode,
@ -296,7 +296,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
L10().barcodeMissingHash, L10().barcodeMissingHash,
); );
} else { } else {
String hash = (data['hash'] ?? '') as String; String hash = (data["hash"] ?? "") as String;
if (hash.isNotEmpty) { if (hash.isNotEmpty) {
item.update( item.update(
@ -343,10 +343,10 @@ class StockItemScanIntoLocationHandler extends BarcodeHandler {
@override @override
Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async { Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async {
// If the barcode points to a 'stocklocation', great! // If the barcode points to a "stocklocation", great!
if (data.containsKey('stocklocation')) { if (data.containsKey("stocklocation")) {
// Extract location information // Extract location information
int location = (data['stocklocation']['pk'] ?? -1) as int; int location = (data["stocklocation"]["pk"] ?? -1) as int;
if (location == -1) { if (location == -1) {
showSnackIcon( showSnackIcon(
@ -408,11 +408,11 @@ class StockLocationScanInItemsHandler extends BarcodeHandler {
Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async { Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async {
// Returned barcode must match a stock item // 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) { if (item == null) {
@ -468,7 +468,7 @@ class InvenTreeQRView extends StatefulWidget {
final BarcodeHandler _handler; final BarcodeHandler _handler;
InvenTreeQRView(this._handler, {Key? key}) : super(key: key); const InvenTreeQRView(this._handler, {Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() => _QRViewState(_handler); State<StatefulWidget> createState() => _QRViewState(_handler);
@ -477,7 +477,7 @@ class InvenTreeQRView extends StatefulWidget {
class _QRViewState extends State<InvenTreeQRView> { class _QRViewState extends State<InvenTreeQRView> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); final GlobalKey qrKey = GlobalKey(debugLabel: "QR");
QRViewController? _controller; QRViewController? _controller;

View File

@ -12,11 +12,9 @@ import 'package:flutter/material.dart';
class S implements WidgetsLocalizations { class S implements WidgetsLocalizations {
const S(); const S();
static const GeneratedLocalizationsDelegate delegate = static const GeneratedLocalizationsDelegate delegate = GeneratedLocalizationsDelegate();
const GeneratedLocalizationsDelegate();
static S of(BuildContext context) => static S of(BuildContext context) => Localizations.of<S>(context, WidgetsLocalizations);
Localizations.of<S>(context, WidgetsLocalizations);
@override @override
TextDirection get textDirection => TextDirection.ltr; TextDirection get textDirection => TextDirection.ltr;

View File

@ -1,6 +1,5 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import "package:inventree/inventree/model.dart";
import 'model.dart';
/* /*
@ -9,6 +8,8 @@ import 'model.dart';
class InvenTreeCompany extends InvenTreeModel { class InvenTreeCompany extends InvenTreeModel {
InvenTreeCompany() : super();
@override @override
String get URL => "company/"; 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); 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); 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 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 @override
InvenTreeModel createFromJson(Map<String, dynamic> json) { InvenTreeModel createFromJson(Map<String, dynamic> json) {
@ -132,11 +131,11 @@ class InvenTreeManufacturerPart extends InvenTreeModel {
InvenTreeManufacturerPart.fromJson(Map<String, dynamic> json) : super.fromJson(json); 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 @override
InvenTreeModel createFromJson(Map<String, dynamic> json) { InvenTreeModel createFromJson(Map<String, dynamic> json) {

View File

@ -1,18 +1,17 @@
import 'dart:async'; import "dart:async";
import 'dart:io'; import "dart:io";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/widget/dialogs.dart'; import "package:inventree/widget/dialogs.dart";
import 'package:url_launcher/url_launcher.dart'; import "package:url_launcher/url_launcher.dart";
import 'package:path/path.dart' as path; import "package:path/path.dart" as path;
import 'package:http/http.dart' as http;
import '../l10.dart'; import "package:inventree/l10.dart";
import '../api_form.dart'; import "package:inventree/api_form.dart";
// Paginated response object // 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 // 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" // 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)) { if (await canLaunch(webUrl)) {
await launch(webUrl); await launch(webUrl);
@ -152,7 +151,7 @@ class InvenTreeModel {
} }
} }
void openLink() async { Future <void> openLink() async {
if (link.isNotEmpty) { 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!) // Create a new object from JSON data (not a constructor!)
InvenTreeModel createFromJson(Map<String, dynamic> json) { InvenTreeModel createFromJson(Map<String, dynamic> json) {
@ -198,7 +197,7 @@ class InvenTreeModel {
var response = await api.get(url, params: defaultGetFilters(), expectedStatusCode: 200); 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 // Report error
if (response.statusCode > 0) { if (response.statusCode > 0) {
@ -267,12 +266,12 @@ class InvenTreeModel {
// Override any default values // Override any default values
for (String key in filters.keys) { for (String key in filters.keys) {
params[key] = filters[key] ?? ''; params[key] = filters[key] ?? "";
} }
var response = await api.get(url, params: params); 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) { if (response.statusCode > 0) {
await sentryReportMessage( await sentryReportMessage(
@ -302,18 +301,18 @@ class InvenTreeModel {
Future<InvenTreeModel?> create(Map<String, dynamic> data) async { Future<InvenTreeModel?> create(Map<String, dynamic> data) async {
if (data.containsKey('pk')) { if (data.containsKey("pk")) {
data.remove('pk'); data.remove("pk");
} }
if (data.containsKey('id')) { if (data.containsKey("id")) {
data.remove('id'); data.remove("id");
} }
var response = await api.post(URL, body: data); var response = await api.post(URL, body: data);
// Invalid response returned from server // 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) { if (response.statusCode > 0) {
await sentryReportMessage( await sentryReportMessage(
@ -345,7 +344,7 @@ class InvenTreeModel {
var params = defaultListFilters(); var params = defaultListFilters();
for (String key in filters.keys) { for (String key in filters.keys) {
params[key] = filters[key] ?? ''; params[key] = filters[key] ?? "";
} }
params["limit"] = "${limit}"; params["limit"] = "${limit}";
@ -384,7 +383,7 @@ class InvenTreeModel {
var params = defaultListFilters(); var params = defaultListFilters();
for (String key in filters.keys) { for (String key in filters.keys) {
params[key] = filters[key] ?? ''; params[key] = filters[key] ?? "";
} }
var response = await api.get(URL, params: params); var response = await api.get(URL, params: params);
@ -403,8 +402,8 @@ class InvenTreeModel {
} else if (response.isMap()) { } else if (response.isMap()) {
var mData = response.asMap(); var mData = response.asMap();
if (mData.containsKey('results')) { if (mData.containsKey("results")) {
data = (response.data['results'] ?? []) as List<dynamic>; data = (response.data["results"] ?? []) as List<dynamic>;
} }
} }
@ -423,9 +422,9 @@ class InvenTreeModel {
// Provide a listing of objects at the endpoint // Provide a listing of objects at the endpoint
// TODO - Static function which returns a list of objects (of this class) // 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 // Override this function for each sub-class
bool matchAgainstString(String filter) { bool matchAgainstString(String filter) {
@ -462,7 +461,7 @@ class InvenTreeAttachment extends InvenTreeModel {
InvenTreeAttachment() : super(); InvenTreeAttachment() : super();
String get attachment => (jsondata["attachment"] ?? '') as String; String get attachment => (jsondata["attachment"] ?? "") as String;
// Return the filename of the attachment // Return the filename of the attachment
String get filename { String get filename {
@ -500,11 +499,11 @@ class InvenTreeAttachment extends InvenTreeModel {
return FontAwesomeIcons.fileAlt; return FontAwesomeIcons.fileAlt;
} }
String get comment => (jsondata["comment"] ?? '') as String; String get comment => (jsondata["comment"] ?? "") as String;
DateTime? get uploadDate { DateTime? get uploadDate {
if (jsondata.containsKey("upload_date")) { if (jsondata.containsKey("upload_date")) {
return DateTime.tryParse((jsondata["upload_date"] ?? '') as String); return DateTime.tryParse((jsondata["upload_date"] ?? "") as String);
} else { } else {
return null; return null;
} }
@ -517,8 +516,8 @@ class InvenTreeAttachment extends InvenTreeModel {
final APIResponse response = await InvenTreeAPI().uploadFile( final APIResponse response = await InvenTreeAPI().uploadFile(
URL, URL,
attachment, attachment,
method: 'POST', method: "POST",
name: 'attachment', name: "attachment",
fields: fields fields: fields
); );

View File

@ -1,12 +1,12 @@
import 'package:inventree/api.dart'; import "dart:io";
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'; import "package:inventree/api.dart";
import 'dart:io'; import "package:inventree/inventree/stock.dart";
import 'package:http/http.dart' as http; import "package:inventree/inventree/company.dart";
import "package:flutter/cupertino.dart";
import "package:inventree/l10.dart";
import "model.dart";
class InvenTreePartCategory extends InvenTreeModel { class InvenTreePartCategory extends InvenTreeModel {
@ -33,7 +33,7 @@ class InvenTreePartCategory extends InvenTreeModel {
return filters; return filters;
} }
String get pathstring => (jsondata['pathstring'] ?? '') as String; String get pathstring => (jsondata["pathstring"] ?? "") as String;
String get parentpathstring { String get parentpathstring {
// TODO - Drive the refactor tractor through this // TODO - Drive the refactor tractor through this
@ -52,7 +52,7 @@ class InvenTreePartCategory extends InvenTreeModel {
return p; return p;
} }
int get partcount => (jsondata['parts'] ?? 0) as int; int get partcount => (jsondata["parts"] ?? 0) as int;
InvenTreePartCategory() : super(); InvenTreePartCategory() : super();
@ -74,17 +74,15 @@ class InvenTreePartTestTemplate extends InvenTreeModel {
@override @override
String get URL => "part/test-template/"; 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(); 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 // Request supplier parts for this part
Future<List<InvenTreeSupplierPart>> getSupplierParts() async { Future<List<InvenTreeSupplierPart>> getSupplierParts() async {
@ -242,7 +240,7 @@ class InvenTreePart extends InvenTreeModel {
} }
// Get the number of stock on order for this Part // 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 { String get onOrderString {
@ -254,7 +252,7 @@ class InvenTreePart extends InvenTreeModel {
} }
// Get the stock count for this Part // 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 { String get inStockString {
@ -271,69 +269,69 @@ class InvenTreePart extends InvenTreeModel {
return q; 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 // 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) // 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) // 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 // 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 // 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) // Get the category ID for the Part instance (or "null" if does not exist)
int get categoryId => (jsondata['category'] ?? -1) as int; int get categoryId => (jsondata["category"] ?? -1) as int;
// Get the category name for the Part instance // Get the category name for the Part instance
String get categoryName { String get categoryName {
// Inavlid category ID // 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 // Get the category description for the Part instance
String get categoryDescription { String get categoryDescription {
// Invalid category ID // 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 // 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 // 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 // Return the fully-qualified name for the Part instance
String get fullname { String get fullname {
String fn = (jsondata['full_name'] ?? '') as String; String fn = (jsondata["full_name"] ?? "") as String;
if (fn.isNotEmpty) return fn; if (fn.isNotEmpty) return fn;
@ -369,15 +367,15 @@ class InvenTreePart extends InvenTreeModel {
final APIResponse response = await InvenTreeAPI().uploadFile( final APIResponse response = await InvenTreeAPI().uploadFile(
url, url,
image, image,
method: 'PATCH', method: "PATCH",
name: 'image', name: "image",
); );
return response.successful(); return response.successful();
} }
// Return the "starred" status of this part // 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(); InvenTreePart() : super();

View File

@ -1,7 +1,7 @@
import 'package:inventree/inventree/company.dart'; import "package:inventree/inventree/company.dart";
import 'package:inventree/inventree/part.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 // TODO: In the future, status codes should be retrieved from the server
const int PO_STATUS_PENDING = 10; 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 { InvenTreeCompany? get supplier {
dynamic supplier_detail = jsondata["supplier_detail"] ?? null; dynamic supplier_detail = jsondata["supplier_detail"];
if (supplier_detail == null) { if (supplier_detail == null) {
return 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 { Future<List<InvenTreePOLineItem>> getLineItems() async {
@ -146,17 +146,17 @@ class InvenTreePOLineItem extends InvenTreeModel {
bool get isComplete => received >= quantity; 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; 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 { InvenTreePart? get part {
dynamic part_detail = jsondata["part_detail"]; dynamic part_detail = jsondata["part_detail"];
@ -170,7 +170,7 @@ class InvenTreePOLineItem extends InvenTreeModel {
InvenTreeSupplierPart? get supplierPart { InvenTreeSupplierPart? get supplierPart {
dynamic detail = jsondata["supplier_part_detail"] ?? null; dynamic detail = jsondata["supplier_part_detail"];
if (detail == null) { if (detail == null) {
return 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(); InvenTreePOLineItem() : super();

View File

@ -1,10 +1,10 @@
import 'dart:io'; import "dart:io";
import 'package:device_info_plus/device_info_plus.dart'; import "package:device_info_plus/device_info_plus.dart";
import 'package:package_info_plus/package_info_plus.dart'; import "package:package_info_plus/package_info_plus.dart";
import 'package:sentry_flutter/sentry_flutter.dart'; import "package:sentry_flutter/sentry_flutter.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
Future<Map<String, dynamic>> getDeviceInfo() async { Future<Map<String, dynamic>> getDeviceInfo() async {
@ -18,35 +18,35 @@ Future<Map<String, dynamic>> getDeviceInfo() async {
final iosDeviceInfo = await deviceInfo.iosInfo; final iosDeviceInfo = await deviceInfo.iosInfo;
device_info = { device_info = {
'name': iosDeviceInfo.name, "name": iosDeviceInfo.name,
'model': iosDeviceInfo.model, "model": iosDeviceInfo.model,
'systemName': iosDeviceInfo.systemName, "systemName": iosDeviceInfo.systemName,
'systemVersion': iosDeviceInfo.systemVersion, "systemVersion": iosDeviceInfo.systemVersion,
'localizedModel': iosDeviceInfo.localizedModel, "localizedModel": iosDeviceInfo.localizedModel,
'utsname': iosDeviceInfo.utsname.sysname, "utsname": iosDeviceInfo.utsname.sysname,
'identifierForVendor': iosDeviceInfo.identifierForVendor, "identifierForVendor": iosDeviceInfo.identifierForVendor,
'isPhysicalDevice': iosDeviceInfo.isPhysicalDevice, "isPhysicalDevice": iosDeviceInfo.isPhysicalDevice,
}; };
} else if (Platform.isAndroid) { } else if (Platform.isAndroid) {
final androidDeviceInfo = await deviceInfo.androidInfo; final androidDeviceInfo = await deviceInfo.androidInfo;
device_info = { device_info = {
'type': androidDeviceInfo.type, "type": androidDeviceInfo.type,
'model': androidDeviceInfo.model, "model": androidDeviceInfo.model,
'device': androidDeviceInfo.device, "device": androidDeviceInfo.device,
'id': androidDeviceInfo.id, "id": androidDeviceInfo.id,
'androidId': androidDeviceInfo.androidId, "androidId": androidDeviceInfo.androidId,
'brand': androidDeviceInfo.brand, "brand": androidDeviceInfo.brand,
'display': androidDeviceInfo.display, "display": androidDeviceInfo.display,
'hardware': androidDeviceInfo.hardware, "hardware": androidDeviceInfo.hardware,
'manufacturer': androidDeviceInfo.manufacturer, "manufacturer": androidDeviceInfo.manufacturer,
'product': androidDeviceInfo.product, "product": androidDeviceInfo.product,
'version': androidDeviceInfo.version.release, "version": androidDeviceInfo.version.release,
'supported32BitAbis': androidDeviceInfo.supported32BitAbis, "supported32BitAbis": androidDeviceInfo.supported32BitAbis,
'supported64BitAbis': androidDeviceInfo.supported64BitAbis, "supported64BitAbis": androidDeviceInfo.supported64BitAbis,
'supportedAbis': androidDeviceInfo.supportedAbis, "supportedAbis": androidDeviceInfo.supportedAbis,
'isPhysicalDevice': androidDeviceInfo.isPhysicalDevice, "isPhysicalDevice": androidDeviceInfo.isPhysicalDevice,
}; };
} }
@ -90,7 +90,7 @@ Future<bool> sentryReportMessage(String message, {Map<String, String>? context})
if (isInDebugMode()) { if (isInDebugMode()) {
print('----- In dev mode. Not sending message to Sentry.io -----'); print("----- In dev mode. Not sending message to Sentry.io -----");
return true; return true;
} }
@ -117,7 +117,7 @@ Future<bool> sentryReportMessage(String message, {Map<String, String>? context})
Future<void> sentryReportError(dynamic error, dynamic stackTrace) async { Future<void> sentryReportError(dynamic error, dynamic stackTrace) async {
print('----- Sentry Intercepted error: $error -----'); print("----- Sentry Intercepted error: $error -----");
print(stackTrace); print(stackTrace);
// Errors thrown in development mode are unlikely to be interesting. You can // 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. // the report.
if (isInDebugMode()) { if (isInDebugMode()) {
print('----- In dev mode. Not sending report to Sentry.io -----'); print("----- In dev mode. Not sending report to Sentry.io -----");
return; return;
} }

View File

@ -1,15 +1,13 @@
import 'package:intl/intl.dart'; import "dart:async";
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 "package:intl/intl.dart";
import "package:inventree/inventree/part.dart";
import "package:flutter/cupertino.dart";
import 'dart:async'; import "package:inventree/inventree/model.dart";
import 'dart:io'; import "package:inventree/l10.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
class InvenTreeStockItemTestResult extends InvenTreeModel { 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(); 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 { bool get hasPurchasePrice {
@ -223,14 +219,14 @@ class InvenTreeStockItem extends InvenTreeModel {
return pp.isNotEmpty && pp.trim() != "-"; 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 // Date of last update
DateTime? get updatedDate { DateTime? get updatedDate {
if (jsondata.containsKey("updated")) { if (jsondata.containsKey("updated")) {
return DateTime.tryParse((jsondata["updated"] ?? '') as String); return DateTime.tryParse((jsondata["updated"] ?? "") as String);
} else { } else {
return null; return null;
} }
@ -250,7 +246,7 @@ class InvenTreeStockItem extends InvenTreeModel {
DateTime? get stocktakeDate { DateTime? get stocktakeDate {
if (jsondata.containsKey("stocktake_date")) { if (jsondata.containsKey("stocktake_date")) {
return DateTime.tryParse((jsondata["stocktake_date"] ?? '') as String); return DateTime.tryParse((jsondata["stocktake_date"] ?? "") as String);
} else { } else {
return null; return null;
} }
@ -270,45 +266,45 @@ class InvenTreeStockItem extends InvenTreeModel {
String get partName { String get partName {
String nm = ''; String nm = "";
// Use the detailed part information as priority // Use the detailed part information as priority
if (jsondata.containsKey('part_detail')) { if (jsondata.containsKey("part_detail")) {
nm = (jsondata['part_detail']['full_name'] ?? '') as String; nm = (jsondata["part_detail"]["full_name"] ?? "") as String;
} }
// Backup if first value fails // Backup if first value fails
if (nm.isEmpty) { if (nm.isEmpty) {
nm = (jsondata['part__name'] ?? '') as String; nm = (jsondata["part__name"] ?? "") as String;
} }
return nm; return nm;
} }
String get partDescription { String get partDescription {
String desc = ''; String desc = "";
// Use the detailed part description as priority // Use the detailed part description as priority
if (jsondata.containsKey('part_detail')) { if (jsondata.containsKey("part_detail")) {
desc = (jsondata['part_detail']['description'] ?? '') as String; desc = (jsondata["part_detail"]["description"] ?? "") as String;
} }
if (desc.isEmpty) { if (desc.isEmpty) {
desc = (jsondata['part__description'] ?? '') as String; desc = (jsondata["part__description"] ?? "") as String;
} }
return desc; return desc;
} }
String get partImage { String get partImage {
String img = ''; String img = "";
if (jsondata.containsKey('part_detail')) { if (jsondata.containsKey("part_detail")) {
img = (jsondata['part_detail']['thumbnail'] ?? '') as String; img = (jsondata["part_detail"]["thumbnail"] ?? "") as String;
} }
if (img.isEmpty) { if (img.isEmpty) {
img = (jsondata['part__thumbnail'] ?? '') as String; img = (jsondata["part__thumbnail"] ?? "") as String;
} }
return img; return img;
@ -321,63 +317,63 @@ class InvenTreeStockItem extends InvenTreeModel {
String thumb = ""; 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) { if (thumb.isEmpty) {
thumb = (jsondata['part_detail']?['image'] ?? '') as String; thumb = (jsondata["part_detail"]?["image"] ?? "") as String;
} }
// Try a different approach // Try a different approach
if (thumb.isEmpty) { 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; if (thumb.isEmpty) thumb = InvenTreeAPI.staticThumb;
return thumb; return thumb;
} }
int get supplierPartId => (jsondata['supplier_part'] ?? -1) as int; int get supplierPartId => (jsondata["supplier_part"] ?? -1) as int;
String get supplierImage { String get supplierImage {
String thumb = ''; String thumb = "";
if (jsondata.containsKey("supplier_detail")) { if (jsondata.containsKey("supplier_detail")) {
thumb = (jsondata['supplier_detail']['supplier_logo'] ?? '') as String; thumb = (jsondata["supplier_detail"]["supplier_logo"] ?? "") as String;
} }
return thumb; return thumb;
} }
String get supplierName { String get supplierName {
String sname = ''; String sname = "";
if (jsondata.containsKey("supplier_detail")) { if (jsondata.containsKey("supplier_detail")) {
sname = (jsondata["supplier_detail"]["supplier_name"] ?? '') as String; sname = (jsondata["supplier_detail"]["supplier_name"] ?? "") as String;
} }
return sname; return sname;
} }
String get units { String get units {
return (jsondata['part_detail']?['units'] ?? '') as String; return (jsondata["part_detail"]?["units"] ?? "") as String;
} }
String get supplierSKU { String get supplierSKU {
String sku = ''; String sku = "";
if (jsondata.containsKey("supplier_detail")) { if (jsondata.containsKey("supplier_detail")) {
sku = (jsondata["supplier_detail"]["SKU"] ?? '') as String; sku = (jsondata["supplier_detail"]["SKU"] ?? "") as String;
} }
return sku; 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 { String get quantityString {
@ -395,33 +391,33 @@ class InvenTreeStockItem extends InvenTreeModel {
return q; 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; bool isSerialized() => serialNumber.isNotEmpty && quantity.toInt() == 1;
String serialOrQuantityDisplay() { String serialOrQuantityDisplay() {
if (isSerialized()) { if (isSerialized()) {
return 'SN ${serialNumber}'; return "SN ${serialNumber}";
} }
// Is an integer? // Is an integer?
if (quantity.toInt() == quantity) { if (quantity.toInt() == quantity) {
return '${quantity.toInt()}'; return "${quantity.toInt()}";
} }
return '${quantity}'; return "${quantity}";
} }
String get locationName { 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 // Old-style name
if (loc.isEmpty) { if (loc.isEmpty) {
loc = (jsondata['location__name'] ?? '') as String; loc = (jsondata["location__name"] ?? "") as String;
} }
return loc; return loc;
@ -429,9 +425,9 @@ class InvenTreeStockItem extends InvenTreeModel {
String get locationPathString { 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) { if (_loc.isNotEmpty) {
return _loc; return _loc;
@ -483,7 +479,7 @@ class InvenTreeStockItem extends InvenTreeModel {
"pk": "${pk}", "pk": "${pk}",
"quantity": "${q}", "quantity": "${q}",
}, },
"notes": notes ?? '', "notes": notes ?? "",
}, },
expectedStatusCode: 200 expectedStatusCode: 200
); );
@ -540,7 +536,7 @@ class InvenTreeStockLocation extends InvenTreeModel {
@override @override
String get URL => "stock/location/"; String get URL => "stock/location/";
String get pathstring => (jsondata['pathstring'] ?? '') as String; String get pathstring => (jsondata["pathstring"] ?? "") as String;
@override @override
Map<String, dynamic> formFields() { Map<String, dynamic> formFields() {
@ -553,13 +549,13 @@ class InvenTreeStockLocation extends InvenTreeModel {
String get parentpathstring { String get parentpathstring {
// TODO - Drive the refactor tractor through this // TODO - Drive the refactor tractor through this
List<String> psplit = pathstring.split('/'); List<String> psplit = pathstring.split("/");
if (psplit.length > 0) { if (psplit.length > 0) {
psplit.removeLast(); psplit.removeLast();
} }
String p = psplit.join('/'); String p = psplit.join("/");
if (p.isEmpty) { if (p.isEmpty) {
p = "Top level stock location"; p = "Top level stock location";
@ -568,7 +564,7 @@ class InvenTreeStockLocation extends InvenTreeModel {
return p; return p;
} }
int get itemcount => (jsondata['items'] ?? 0) as int; int get itemcount => (jsondata["items"] ?? 0) as int;
InvenTreeStockLocation() : super(); InvenTreeStockLocation() : super();

View File

@ -1,8 +1,8 @@
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 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_en.dart";
import 'package:one_context/one_context.dart'; import "package:one_context/one_context.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
// Shortcut function to reduce boilerplate! // Shortcut function to reduce boilerplate!
I18N L10() I18N L10()

View File

@ -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_localizations/flutter_localizations.dart'; import "package:flutter_gen/gen_l10n/app_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/cupertino.dart'; import "package:flutter/material.dart";
import 'package:flutter/material.dart'; import "package:one_context/one_context.dart";
import 'package:one_context/one_context.dart'; import "package:package_info_plus/package_info_plus.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:inventree/inventree/sentry.dart";
import "package:inventree/dsn.dart";
import 'package:flutter/foundation.dart'; import "package:inventree/widget/home.dart";
import 'package:sentry_flutter/sentry_flutter.dart';
Future<void> main() async { Future<void> main() async {
@ -75,24 +74,24 @@ class InvenTreeApp extends StatelessWidget {
GlobalCupertinoLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
], ],
supportedLocales: [ supportedLocales: [
const Locale('de', ''), // German const Locale("de", ""), // German
const Locale('el', ''), // Greek const Locale("el", ""), // Greek
const Locale('en', ''), // English const Locale("en", ""), // English
const Locale('es', ''), // Spanish const Locale("es", ""), // Spanish
const Locale('fr', ''), // French const Locale("fr", ""), // French
const Locale('he', ''), // Hebrew const Locale("he", ""), // Hebrew
const Locale('it', ''), // Italian const Locale("it", ""), // Italian
const Locale('ja', ''), // Japanese const Locale("ja", ""), // Japanese
const Locale('ko', ''), // Korean const Locale("ko", ""), // Korean
const Locale('nl', ''), // Dutch const Locale("nl", ""), // Dutch
const Locale('no', ''), // Norwegian const Locale("no", ""), // Norwegian
const Locale('pl', ''), // Polish const Locale("pl", ""), // Polish
const Locale('ru', ''), // Russian const Locale("ru", ""), // Russian
const Locale('sv', ''), // Swedish const Locale("sv", ""), // Swedish
const Locale('th', ''), // Thai const Locale("th", ""), // Thai
const Locale('tr', ''), // Turkish const Locale("tr", ""), // Turkish
const Locale('vi', ''), // Vietnamese const Locale("vi", ""), // Vietnamese
const Locale('zh-CN', ''), // Chinese const Locale("zh-CN", ""), // Chinese
], ],
); );

View File

@ -1,8 +1,10 @@
import 'package:path_provider/path_provider.dart'; import "dart:async";
import 'package:sembast/sembast.dart';
import 'package:sembast/sembast_io.dart'; import "package:path_provider/path_provider.dart";
import 'package:path/path.dart'; import "package:sembast/sembast.dart";
import 'dart:async'; import "package:sembast/sembast_io.dart";
import "package:path/path.dart";
/* /*
* Class for storing InvenTree preferences in a NoSql DB * Class for storing InvenTree preferences in a NoSql DB
@ -43,7 +45,7 @@ class InvenTreePreferencesDB {
print("Path: ${appDocumentDir.path}"); print("Path: ${appDocumentDir.path}");
// Path with the form: /platform-specific-directory/demo.db // 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); final database = await databaseFactoryIo.openDatabase(dbPath);
@ -55,7 +57,7 @@ class InvenTreePreferencesDB {
class InvenTreePreferences { class InvenTreePreferences {
/* The following settings are not stored to persistent storage, /* 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. * They are kept here as a convenience only.
*/ */

View File

@ -1,22 +1,22 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/settings/release.dart'; import "package:inventree/settings/release.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter/services.dart'; import "package:flutter/services.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:package_info_plus/package_info_plus.dart'; import "package:package_info_plus/package_info_plus.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
class InvenTreeAboutWidget extends StatelessWidget { class InvenTreeAboutWidget extends StatelessWidget {
final PackageInfo info; 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 // Load release notes from external file
String notes = await rootBundle.loadString("assets/release_notes.md"); 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"); String notes = await rootBundle.loadString("assets/credits.md");

View File

@ -1,12 +1,12 @@
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter/cupertino.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 { class InvenTreeAppSettingsWidget extends StatefulWidget {
@override @override
@ -31,7 +31,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
loadSettings(); loadSettings();
} }
void loadSettings() async { Future <void> loadSettings() async {
barcodeSounds = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool; barcodeSounds = await InvenTreeSettingsManager().getValue("barcodeSounds", true) as bool;
serverSounds = await InvenTreeSettingsManager().getValue("serverSounds", 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); await InvenTreeSettingsManager().setValue("barcodeSounds", en);
barcodeSounds = await InvenTreeSettingsManager().getBool("barcodeSounds", true); 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); await InvenTreeSettingsManager().setValue("serverSounds", en);
serverSounds = await InvenTreeSettingsManager().getBool("serverSounds", true); 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); await InvenTreeSettingsManager().setValue("partSubcategory", en);
partSubcategory = await InvenTreeSettingsManager().getBool("partSubcategory", true); 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); await InvenTreeSettingsManager().setValue("stockSublocation", en);
stockSublocation = await InvenTreeSettingsManager().getBool("stockSublocation", true); stockSublocation = await InvenTreeSettingsManager().getBool("stockSublocation", true);

View File

@ -1,15 +1,12 @@
import 'package:inventree/app_colors.dart'; import "package:flutter/material.dart";
import 'package:inventree/widget/dialogs.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/widget/fields.dart';
import 'package:inventree/widget/spinner.dart';
import 'package:flutter/material.dart'; import "package:inventree/app_colors.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:inventree/widget/dialogs.dart";
import "package:inventree/widget/spinner.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import "package:inventree/api.dart";
import '../api.dart'; import "package:inventree/user_profile.dart";
import '../user_profile.dart';
class InvenTreeLoginSettingsWidget extends StatefulWidget { class InvenTreeLoginSettingsWidget extends StatefulWidget {
@ -22,15 +19,13 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
final GlobalKey<_InvenTreeLoginSettingsState> _loginKey = GlobalKey<_InvenTreeLoginSettingsState>(); final GlobalKey<_InvenTreeLoginSettingsState> _loginKey = GlobalKey<_InvenTreeLoginSettingsState>();
final GlobalKey<FormState> _addProfileKey = new GlobalKey<FormState>();
List<UserProfile> profiles = []; List<UserProfile> profiles = [];
_InvenTreeLoginSettingsState() { _InvenTreeLoginSettingsState() {
_reload(); _reload();
} }
void _reload() async { Future <void> _reload() async {
profiles = await UserProfileDBManager().getAllProfiles(); 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 // Disconnect InvenTree
InvenTreeAPI().disconnectFromServer(); InvenTreeAPI().disconnectFromServer();
@ -73,18 +68,18 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
_reload(); _reload();
} }
void _deleteProfile(UserProfile profile) async { Future <void> _deleteProfile(UserProfile profile) async {
await UserProfileDBManager().deleteProfile(profile); await UserProfileDBManager().deleteProfile(profile);
_reload(); _reload();
if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? '')) { if (InvenTreeAPI().isConnected() && profile.key == (InvenTreeAPI().profile?.key ?? "")) {
InvenTreeAPI().disconnectFromServer(); InvenTreeAPI().disconnectFromServer();
} }
} }
void _updateProfile(UserProfile? profile) async { Future <void> _updateProfile(UserProfile? profile) async {
if (profile == null) { if (profile == null) {
return; return;
@ -92,7 +87,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
_reload(); _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 // Attempt server login (this will load the newly selected profile
InvenTreeAPI().connectToServer().then((result) { InvenTreeAPI().connectToServer().then((result) {
@ -108,7 +103,7 @@ class _InvenTreeLoginSettingsState extends State<InvenTreeLoginSettingsWidget> {
if (!profile.selected) return null; if (!profile.selected) return null;
// Selected, but (for some reason) not the same as the API... // 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( return FaIcon(
FontAwesomeIcons.questionCircle, FontAwesomeIcons.questionCircle,
color: COLOR_WARNING color: COLOR_WARNING

View File

@ -1,14 +1,14 @@
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter_markdown/flutter_markdown.dart'; import "package:flutter_markdown/flutter_markdown.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
class ReleaseNotesWidget extends StatelessWidget { class ReleaseNotesWidget extends StatelessWidget {
final String releaseNotes; final String releaseNotes;
ReleaseNotesWidget(this.releaseNotes); const ReleaseNotesWidget(this.releaseNotes);
@override @override
Widget build (BuildContext context) { Widget build (BuildContext context) {
@ -29,7 +29,7 @@ class CreditsWidget extends StatelessWidget {
final String credits; final String credits;
CreditsWidget(this.credits); const CreditsWidget(this.credits);
@override @override
Widget build (BuildContext context) { Widget build (BuildContext context) {

View File

@ -1,18 +1,16 @@
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/settings/about.dart'; import "package:inventree/settings/about.dart";
import 'package:inventree/settings/app_settings.dart'; import "package:inventree/settings/app_settings.dart";
import 'package:inventree/settings/login.dart'; import "package:inventree/settings/login.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:inventree/widget/submit_feedback.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 { class InvenTreeSettingsWidget extends StatefulWidget {
// InvenTree settings view // InvenTree settings view
@ -95,30 +93,30 @@ class _InvenTreeSettingsState extends State<InvenTreeSettingsWidget> {
} }
void _openDocs() async { Future <void> _openDocs() async {
if (await canLaunch(docsUrl)) { if (await canLaunch(docsUrl)) {
await launch(docsUrl); await launch(docsUrl);
} }
} }
void _translate() async { Future <void> _translate() async {
final String url = "https://crowdin.com/project/inventree"; const String url = "https://crowdin.com/project/inventree";
if (await canLaunch(url)) { if (await canLaunch(url)) {
await launch(url); await launch(url);
} }
} }
void _editServerSettings() async { Future <void> _editServerSettings() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget())); Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeLoginSettingsWidget()));
} }
void _editAppSettings() async { Future <void> _editAppSettings() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget())); Navigator.push(context, MaterialPageRoute(builder: (context) => InvenTreeAppSettingsWidget()));
} }
void _about() async { Future <void> _about() async {
PackageInfo.fromPlatform().then((PackageInfo info) { PackageInfo.fromPlatform().then((PackageInfo info) {
Navigator.push(context, 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( Navigator.push(
context, context,

View File

@ -2,8 +2,8 @@
/* /*
* Class for InvenTree user / login details * Class for InvenTree user / login details
*/ */
import 'package:sembast/sembast.dart'; import "package:sembast/sembast.dart";
import 'preferences.dart'; import "preferences.dart";
class UserProfile { class UserProfile {
@ -38,10 +38,10 @@ class UserProfile {
factory UserProfile.fromJson(int key, Map<String, dynamic> json, bool isSelected) => UserProfile( factory UserProfile.fromJson(int key, Map<String, dynamic> json, bool isSelected) => UserProfile(
key: key, key: key,
name: json['name'] as String, name: json["name"] as String,
server: json['server'] as String, server: json["server"] as String,
username: json['username'] as String, username: json["username"] as String,
password: json['password'] as String, password: json["password"] as String,
selected: isSelected, selected: isSelected,
); );
@ -70,7 +70,7 @@ class UserProfileDBManager {
final profiles = await store.find(await _db, finder: finder); final profiles = await store.find(await _db, finder: finder);
return profiles.length > 0; return profiles.isNotEmpty;
} }
Future<void> addProfile(UserProfile profile) async { Future<void> addProfile(UserProfile profile) async {

View File

@ -1,27 +1,27 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/app_settings.dart'; import "package:inventree/app_settings.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/widget/progress.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/part_detail.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/paginator.dart'; import "package:inventree/widget/paginator.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/foundation.dart'; import "package:flutter/foundation.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart";
class CategoryDisplayWidget extends StatefulWidget { class CategoryDisplayWidget extends StatefulWidget {
CategoryDisplayWidget(this.category, {Key? key}) : super(key: key); const CategoryDisplayWidget(this.category, {Key? key}) : super(key: key);
final InvenTreePartCategory? category; final InvenTreePartCategory? category;
@ -41,7 +41,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
List<Widget> actions = []; List<Widget> actions = [];
if ((category != null) && InvenTreeAPI().checkPermission('part_category', 'change')) { if ((category != null) && InvenTreeAPI().checkPermission("part_category", "change")) {
actions.add( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),
@ -278,7 +278,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
getCategoryDescriptionCard(extra: false), getCategoryDescriptionCard(extra: false),
]; ];
if (InvenTreeAPI().checkPermission('part', 'add')) { if (InvenTreeAPI().checkPermission("part", "add")) {
tiles.add( tiles.add(
ListTile( ListTile(
title: Text(L10().categoryCreate), title: Text(L10().categoryCreate),
@ -331,7 +331,9 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
); );
case 1: case 1:
return PaginatedPartList( return PaginatedPartList(
{"category": "${category?.pk ?? null}"}, {
"category": "${category?.pk ?? 'null'}"
},
); );
case 2: case 2:
return ListView( return ListView(
@ -350,7 +352,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
class SubcategoryList extends StatelessWidget { class SubcategoryList extends StatelessWidget {
final List<InvenTreePartCategory> _categories; final List<InvenTreePartCategory> _categories;
SubcategoryList(this._categories); const SubcategoryList(this._categories);
void _openCategory(BuildContext context, int pk) { void _openCategory(BuildContext context, int pk) {

View File

@ -1,18 +1,18 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/inventree/company.dart'; import "package:inventree/inventree/company.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
class CompanyDetailWidget extends StatefulWidget { class CompanyDetailWidget extends StatefulWidget {
final InvenTreeCompany company; final InvenTreeCompany company;
CompanyDetailWidget(this.company, {Key? key}) : super(key: key); const CompanyDetailWidget(this.company, {Key? key}) : super(key: key);
@override @override
_CompanyDetailState createState() => _CompanyDetailState(company); _CompanyDetailState createState() => _CompanyDetailState(company);
@ -62,7 +62,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
await company.reload(); await company.reload();
} }
void editCompany(BuildContext context) async { Future <void> editCompany(BuildContext context) async {
company.editForm( company.editForm(
context, context,

View File

@ -1,16 +1,16 @@
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/inventree/company.dart'; import "package:inventree/inventree/company.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/widget/paginator.dart'; import "package:inventree/widget/paginator.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/company_detail.dart'; import "package:inventree/widget/company_detail.dart";
import '../l10.dart'; import "package:inventree/l10.dart";
class CompanyListWidget extends StatefulWidget { class CompanyListWidget extends StatefulWidget {

View File

@ -1,12 +1,12 @@
import 'package:inventree/app_settings.dart'; import "package:inventree/app_settings.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import 'package:audioplayers/audioplayers.dart'; import "package:audioplayers/audioplayers.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:one_context/one_context.dart'; import "package:one_context/one_context.dart";
Future<void> confirmationDialog(String title, String text, {String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async { Future<void> confirmationDialog(String title, String text, {String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async {

View File

@ -1,21 +1,21 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/barcode.dart'; import "package:inventree/barcode.dart";
import 'package:inventree/widget/company_list.dart'; import "package:inventree/widget/company_list.dart";
import 'package:inventree/widget/search.dart'; import "package:inventree/widget/search.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:inventree/widget/category_display.dart'; import "package:inventree/widget/category_display.dart";
import 'package:inventree/widget/location_display.dart'; import "package:inventree/widget/location_display.dart";
import 'package:inventree/settings/settings.dart'; import "package:inventree/settings/settings.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
class InvenTreeDrawer extends StatelessWidget { class InvenTreeDrawer extends StatelessWidget {
final BuildContext context; final BuildContext context;
InvenTreeDrawer(this.context); const InvenTreeDrawer(this.context);
void _closeDrawer() { void _closeDrawer() {
// Close the drawer // Close the drawer
@ -50,7 +50,7 @@ class InvenTreeDrawer extends StatelessWidget {
* Launch the camera to scan a QR code. * Launch the camera to scan a QR code.
* Upon successful scan, data are passed off to be decoded. * Upon successful scan, data are passed off to be decoded.
*/ */
void _scan() async { Future <void> _scan() async {
if (!InvenTreeAPI().checkConnection(context)) return; if (!InvenTreeAPI().checkConnection(context)) return;
_closeDrawer(); _closeDrawer();

View File

@ -1,15 +1,13 @@
import "dart:async";
import "dart:io";
import 'package:file_picker/file_picker.dart'; import "package:file_picker/file_picker.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:image_picker/image_picker.dart'; import "package:image_picker/image_picker.dart";
import 'package:inventree/l10.dart'; import "package:one_context/one_context.dart";
import 'dart:async';
import 'dart:io';
import 'package:one_context/one_context.dart';
import "package:inventree/l10.dart";
class FilePickerDialog { class FilePickerDialog {
@ -167,7 +165,7 @@ class CheckBoxField extends FormField<bool> {
class StringField extends TextFormField { 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( super(
decoration: InputDecoration( decoration: InputDecoration(
labelText: allowEmpty ? label : label + "*", labelText: allowEmpty ? label : label + "*",
@ -182,7 +180,7 @@ class StringField extends TextFormField {
} }
if (validator != null) { if (validator != null) {
return validator(value); return validator(value) as String?;
} }
return null; return null;

View File

@ -1,29 +1,29 @@
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/user_profile.dart'; import "package:inventree/user_profile.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.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/barcode.dart";
import 'package:inventree/api.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/category_display.dart";
import 'package:inventree/widget/company_list.dart'; import "package:inventree/widget/company_list.dart";
import 'package:inventree/widget/location_display.dart'; import "package:inventree/widget/location_display.dart";
import 'package:inventree/widget/purchase_order_list.dart'; import "package:inventree/widget/purchase_order_list.dart";
import 'package:inventree/widget/search.dart'; import "package:inventree/widget/search.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import 'package:inventree/widget/spinner.dart'; import "package:inventree/widget/spinner.dart";
import 'package:inventree/widget/drawer.dart'; import "package:inventree/widget/drawer.dart";
class InvenTreeHomePage extends StatefulWidget { class InvenTreeHomePage extends StatefulWidget {
InvenTreeHomePage({Key? key}) : super(key: key); const InvenTreeHomePage({Key? key}) : super(key: key);
@override @override
_InvenTreeHomePageState createState() => _InvenTreeHomePageState(); _InvenTreeHomePageState createState() => _InvenTreeHomePageState();
@ -125,7 +125,7 @@ class _InvenTreeHomePageState extends State<InvenTreeHomePage> {
}); });
} }
void _loadProfile() async { Future <void> _loadProfile() async {
_profile = await UserProfileDBManager().getSelectedProfile(); _profile = await UserProfileDBManager().getSelectedProfile();

View File

@ -1,21 +1,21 @@
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/app_settings.dart'; import "package:inventree/app_settings.dart";
import 'package:inventree/barcode.dart'; import "package:inventree/barcode.dart";
import 'package:inventree/inventree/sentry.dart'; import "package:inventree/inventree/sentry.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/widget/progress.dart'; import "package:inventree/widget/progress.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/stock_detail.dart'; import "package:inventree/widget/stock_detail.dart";
import 'package:inventree/widget/paginator.dart'; import "package:inventree/widget/paginator.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter/foundation.dart'; import "package:flutter/foundation.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import "package:infinite_scroll_pagination/infinite_scroll_pagination.dart";
class LocationDisplayWidget extends StatefulWidget { 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( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),
@ -96,7 +96,7 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
List<InvenTreeStockLocation> _sublocations = []; List<InvenTreeStockLocation> _sublocations = [];
String _locationFilter = ''; String _locationFilter = "";
List<InvenTreeStockLocation> get sublocations { List<InvenTreeStockLocation> get sublocations {
@ -340,7 +340,7 @@ List<Widget> detailTiles() {
tiles.add(locationDescriptionCard(includeActions: false)); tiles.add(locationDescriptionCard(includeActions: false));
if (InvenTreeAPI().checkPermission('stock', 'add')) { if (InvenTreeAPI().checkPermission("stock", "add")) {
tiles.add( tiles.add(
ListTile( ListTile(
@ -368,7 +368,7 @@ List<Widget> detailTiles() {
if (location != null) { if (location != null) {
// Stock adjustment actions // Stock adjustment actions
if (InvenTreeAPI().checkPermission('stock', 'change')) { if (InvenTreeAPI().checkPermission("stock", "change")) {
// Scan items into location // Scan items into location
tiles.add( tiles.add(
ListTile( ListTile(
@ -430,7 +430,7 @@ List<Widget> detailTiles() {
class SublocationList extends StatelessWidget { class SublocationList extends StatelessWidget {
final List<InvenTreeStockLocation> _locations; final List<InvenTreeStockLocation> _locations;
SublocationList(this._locations); const SublocationList(this._locations);
void _openLocation(BuildContext context, int pk) { void _openLocation(BuildContext context, int pk) {
@ -446,7 +446,7 @@ class SublocationList extends StatelessWidget {
InvenTreeStockLocation loc = _locations[index]; InvenTreeStockLocation loc = _locations[index];
return ListTile( return ListTile(
title: Text('${loc.name}'), title: Text("${loc.name}"),
subtitle: Text("${loc.description}"), subtitle: Text("${loc.description}"),
trailing: Text("${loc.itemcount}"), trailing: Text("${loc.itemcount}"),
onTap: () { onTap: () {
@ -477,7 +477,7 @@ class PaginatedStockList extends StatefulWidget {
final Map<String, String> filters; final Map<String, String> filters;
PaginatedStockList(this.filters); const PaginatedStockList(this.filters);
@override @override
_PaginatedStockListState createState() => _PaginatedStockListState(filters); _PaginatedStockListState createState() => _PaginatedStockListState(filters);
@ -516,7 +516,7 @@ class _PaginatedStockListState extends State<PaginatedStockList> {
Future<void> _fetchPage(int pageKey) async { Future<void> _fetchPage(int pageKey) async {
try { try {
Map<String, String> params = this.filters; Map<String, String> params = filters;
params["search"] = "${_searchTerm}"; params["search"] = "${_searchTerm}";

View File

@ -1,8 +1,6 @@
// Pagination related widgets import "package:flutter/material.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:flutter/material.dart'; import "package:inventree/l10.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:inventree/l10.dart';
class PaginatedSearchWidget extends StatelessWidget { class PaginatedSearchWidget extends StatelessWidget {
@ -44,9 +42,9 @@ class PaginatedSearchWidget extends StatelessWidget {
class NoResultsWidget extends StatelessWidget { class NoResultsWidget extends StatelessWidget {
final String description; const NoResultsWidget(this.description);
NoResultsWidget(this.description); final String description;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -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:inventree/api.dart";
import 'package:flutter/cupertino.dart'; import "package:inventree/l10.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';
class PartAttachmentsWidget extends StatefulWidget { class PartAttachmentsWidget extends StatefulWidget {
PartAttachmentsWidget(this.part, {Key? key}) : super(key: key); const PartAttachmentsWidget(this.part, {Key? key}) : super(key: key);
final InvenTreePart part; final InvenTreePart part;
@ -42,7 +38,7 @@ class _PartAttachmentDisplayState extends RefreshableState<PartAttachmentsWidget
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('part', 'change')) { if (InvenTreeAPI().checkPermission("part", "change")) {
// File upload // File upload
actions.add( actions.add(

View File

@ -1,28 +1,28 @@
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/foundation.dart'; import "package:flutter/foundation.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:inventree/widget/part_attachments_widget.dart'; import "package:inventree/widget/part_attachments_widget.dart";
import 'package:inventree/widget/part_notes.dart'; import "package:inventree/widget/part_notes.dart";
import 'package:inventree/widget/progress.dart'; import "package:inventree/widget/progress.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/widget/category_display.dart'; import "package:inventree/widget/category_display.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/part_image_widget.dart'; import "package:inventree/widget/part_image_widget.dart";
import 'package:inventree/widget/stock_detail.dart'; import "package:inventree/widget/stock_detail.dart";
import 'location_display.dart'; import "pcakage:inventree/widget/location_display.dart";
class PartDetailWidget extends StatefulWidget { class PartDetailWidget extends StatefulWidget {
PartDetailWidget(this.part, {Key? key}) : super(key: key); const PartDetailWidget(this.part, {Key? key}) : super(key: key);
final InvenTreePart part; final InvenTreePart part;
@ -46,7 +46,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('part', 'view')) { if (InvenTreeAPI().checkPermission("part", "view")) {
actions.add( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.globe), 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( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),
@ -89,9 +89,9 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
await part.getTestTemplates(); 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}"}); await part.update(values: {"starred": "${!part.starred}"});
refresh(); refresh();
} }
@ -327,7 +327,8 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
} }
// TODO - Add request tests? // TODO - Add request tests?
if (false && part.isTrackable) { /*
if (part.isTrackable) {
tiles.add(ListTile( tiles.add(ListTile(
title: Text(L10().testsRequired), title: Text(L10().testsRequired),
leading: FaIcon(FontAwesomeIcons.tasks), leading: FaIcon(FontAwesomeIcons.tasks),
@ -336,6 +337,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
) )
); );
} }
*/
// Notes field // Notes field
tiles.add( 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( tiles.add(
ListTile( ListTile(
title: Text(L10().deletePart), title: Text(L10().deletePart),

View File

@ -1,23 +1,21 @@
import 'dart:io'; import "dart:io";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/foundation.dart'; import "package:flutter/foundation.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:image_picker/image_picker.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/api.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/widget/fields.dart'; import "package:inventree/widget/fields.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import "package:inventree/l10.dart";
import '../l10.dart';
class PartImageWidget extends StatefulWidget { class PartImageWidget extends StatefulWidget {
PartImageWidget(this.part, {Key? key}) : super(key: key); const PartImageWidget(this.part, {Key? key}) : super(key: key);
final InvenTreePart part; final InvenTreePart part;
@ -46,7 +44,7 @@ class _PartImageState extends RefreshableState<PartImageWidget> {
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('part', 'change')) { if (InvenTreeAPI().checkPermission("part", "change")) {
// File upload // File upload
actions.add( actions.add(

View File

@ -1,18 +1,18 @@
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/api.dart'; import "package:inventree/api.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter_markdown/flutter_markdown.dart'; import "package:flutter_markdown/flutter_markdown.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
class PartNotesWidget extends StatefulWidget { class PartNotesWidget extends StatefulWidget {
final InvenTreePart part; final InvenTreePart part;
PartNotesWidget(this.part, {Key? key}) : super(key: key); const PartNotesWidget(this.part, {Key? key}) : super(key: key);
@override @override
_PartNotesState createState() => _PartNotesState(part); _PartNotesState createState() => _PartNotesState(part);
@ -38,7 +38,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> {
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('part', 'change')) { if (InvenTreeAPI().checkPermission("part", "change")) {
actions.add( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),

View File

@ -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/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/inventree/company.dart'; import "package:inventree/inventree/company.dart";
import 'package:inventree/widget/company_detail.dart'; import "package:inventree/widget/company_detail.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
class PartSupplierWidget extends StatefulWidget { class PartSupplierWidget extends StatefulWidget {
PartSupplierWidget(this.part, {Key? key}) : super(key: key); const PartSupplierWidget(this.part, {Key? key}) : super(key: key);
final InvenTreePart part; final InvenTreePart part;

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
/* /*
* Construct a circular progress indicator * Construct a circular progress indicator

View File

@ -1,21 +1,20 @@
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.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 '../l10.dart'; import "package:inventree/api.dart";
import 'location_display.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 { class PurchaseOrderDetailWidget extends StatefulWidget {
PurchaseOrderDetailWidget(this.order, {Key? key}): super(key: key); const PurchaseOrderDetailWidget(this.order, {Key? key}): super(key: key);
final InvenTreePurchaseOrder order; 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( order.editForm(
context, context,

View File

@ -1,23 +1,22 @@
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.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 '../l10.dart'; import "package:inventree/inventree/company.dart";
import "package:inventree/inventree/sentry.dart";
import 'package:inventree/api.dart'; import "package:inventree/widget/paginator.dart";
import 'package:inventree/inventree/purchase_order.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 * Widget class for displaying a list of Purchase Orders
*/ */
class PurchaseOrderListWidget extends StatefulWidget { 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; final Map<String, String> filters;
@ -100,7 +99,7 @@ class _PaginatedPurchaseOrderListState extends State<_PaginatedPurchaseOrderList
// Copy across provided filters // Copy across provided filters
for (String key in filters.keys) { for (String key in filters.keys) {
params[key] = filters[key] ?? ''; params[key] = filters[key] ?? "";
} }
final page = await InvenTreePurchaseOrder().listPaginated( final page = await InvenTreePurchaseOrder().listPaginated(

View File

@ -1,7 +1,7 @@
import 'package:inventree/widget/drawer.dart'; import "package:inventree/widget/drawer.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter/widgets.dart'; import "package:flutter/widgets.dart";
abstract class RefreshableState<T extends StatefulWidget> extends State<T> { 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"; } String getAppBarTitle(BuildContext context) { return "App Bar Title"; }
@override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) => onBuild(_context!)); WidgetsBinding.instance?.addPostFrameCallback((_) => onBuild(_context!));

View File

@ -1,17 +1,17 @@
import 'package:inventree/widget/part_detail.dart'; import "package:inventree/widget/part_detail.dart";
import 'package:inventree/widget/progress.dart'; import "package:inventree/widget/progress.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import 'package:inventree/widget/stock_detail.dart'; import "package:inventree/widget/stock_detail.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import '../api.dart'; import "package:inventree/api.dart";
// TODO - Refactor duplicate code in this file! // TODO - Refactor duplicate code in this file!
@ -101,7 +101,7 @@ class PartSearchDelegate extends SearchDelegate<InvenTreePart?> {
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.backspace), icon: FaIcon(FontAwesomeIcons.backspace),
onPressed: () { onPressed: () {
query = ''; query = "";
search(context); search(context);
}, },
), ),
@ -119,7 +119,7 @@ class PartSearchDelegate extends SearchDelegate<InvenTreePart?> {
return IconButton( return IconButton(
icon: Icon(Icons.arrow_back), icon: Icon(Icons.arrow_back),
onPressed: () { onPressed: () {
this.close(context, null); close(context, null);
} }
); );
} }
@ -289,7 +289,7 @@ class StockSearchDelegate extends SearchDelegate<InvenTreeStockItem?> {
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.backspace), icon: FaIcon(FontAwesomeIcons.backspace),
onPressed: () { onPressed: () {
query = ''; query = "";
search(context); search(context);
}, },
), ),
@ -307,7 +307,7 @@ class StockSearchDelegate extends SearchDelegate<InvenTreeStockItem?> {
return IconButton( return IconButton(
icon: Icon(Icons.arrow_back), icon: Icon(Icons.arrow_back),
onPressed: () { onPressed: () {
this.close(context, null); close(context, null);
} }
); );
} }

View File

@ -8,11 +8,11 @@
* | Text <icon> | * | Text <icon> |
*/ */
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:one_context/one_context.dart'; import "package:one_context/one_context.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
void showSnackIcon(String text, {IconData? icon, Function()? onAction, bool? success, String? actionText}) { void showSnackIcon(String text, {IconData? icon, Function()? onAction, bool? success, String? actionText}) {

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
class Spinner extends StatefulWidget { class Spinner extends StatefulWidget {
final IconData? icon; final IconData? icon;

View File

@ -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/api.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';
class StarredPartWidget extends StatefulWidget { class StarredPartWidget extends StatefulWidget {
StarredPartWidget({Key? key}) : super(key: key); const StarredPartWidget({Key? key}) : super(key: key);
@override @override
_StarredPartState createState() => _StarredPartState(); _StarredPartState createState() => _StarredPartState();

View File

@ -1,30 +1,30 @@
import 'package:inventree/app_colors.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/barcode.dart'; import "package:inventree/barcode.dart";
import 'package:inventree/inventree/model.dart'; import "package:inventree/inventree/model.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/widget/dialogs.dart'; import "package:inventree/widget/dialogs.dart";
import 'package:inventree/widget/fields.dart'; import "package:inventree/widget/fields.dart";
import 'package:inventree/widget/location_display.dart'; import "package:inventree/widget/location_display.dart";
import 'package:inventree/widget/part_detail.dart'; import "package:inventree/widget/part_detail.dart";
import 'package:inventree/widget/progress.dart'; import "package:inventree/widget/progress.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:inventree/widget/snacks.dart'; import "package:inventree/widget/snacks.dart";
import 'package:inventree/widget/stock_item_test_results.dart'; import "package:inventree/widget/stock_item_test_results.dart";
import 'package:inventree/widget/stock_notes.dart'; import "package:inventree/widget/stock_notes.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter/material.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:dropdown_search/dropdown_search.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
class StockDetailWidget extends StatefulWidget { class StockDetailWidget extends StatefulWidget {
StockDetailWidget(this.item, {Key? key}) : super(key: key); const StockDetailWidget(this.item, {Key? key}) : super(key: key);
final InvenTreeStockItem item; final InvenTreeStockItem item;
@ -53,7 +53,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('stock', 'view')) { if (InvenTreeAPI().checkPermission("stock", "view")) {
actions.add( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.globe), 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( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),
@ -99,13 +99,13 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
await item.reload(); await item.reload();
// Request part information // Request part information
part = await InvenTreePart().get(item.partId) as InvenTreePart; part = await InvenTreePart().get(item.partId) as InvenTreePart?;
// Request test results... // Request test results...
await item.getTestResults(); await item.getTestResults();
} }
void _editStockItem(BuildContext context) async { Future <void> _editStockItem(BuildContext context) async {
var fields = InvenTreeStockItem().formFields(); 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); double quantity = double.parse(_quantityController.text);
_quantityController.clear(); _quantityController.clear();
@ -138,7 +138,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
refresh(); refresh();
} }
void _addStockDialog() async { Future <void> _addStockDialog() async {
_quantityController.clear(); _quantityController.clear();
_notesController.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); double quantity = double.parse(_quantityController.text);
_quantityController.clear(); _quantityController.clear();
@ -211,7 +211,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
); );
} }
void _countStock() async { Future <void> _countStock() async {
double quantity = double.parse(_quantityController.text); double quantity = double.parse(_quantityController.text);
_quantityController.clear(); _quantityController.clear();
@ -223,7 +223,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
refresh(); refresh();
} }
void _countStockDialog() async { Future <void> _countStockDialog() async {
_quantityController.text = item.quantity.toString(); _quantityController.text = item.quantity.toString();
_notesController.clear(); _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) { if (result) {
showSnackIcon( 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; double quantity = double.tryParse(_quantityController.text) ?? item.quantity;
String notes = _notesController.text; 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; int? location_pk;
@ -349,13 +349,13 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
hint: L10().searchLocation, hint: L10().searchLocation,
onChanged: null, onChanged: null,
itemAsString: (dynamic location) { itemAsString: (dynamic location) {
return (location['pathstring'] ?? '') as String; return (location["pathstring"] ?? "") as String;
}, },
onSaved: (dynamic location) { onSaved: (dynamic location) {
if (location == null) { if (location == null) {
location_pk = null; location_pk = null;
} else { } else {
location_pk = location['pk'] as int; location_pk = location["pk"] as int;
} }
}, },
isFilteredOnline: true, isFilteredOnline: true,
@ -503,7 +503,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
// Supplier part? // Supplier part?
// TODO: Display supplier part info page? // TODO: Display supplier part info page?
if (false && item.supplierPartId > 0) { /*
if (item.supplierPartId > 0) {
tiles.add( tiles.add(
ListTile( ListTile(
title: Text("${item.supplierName}"), title: Text("${item.supplierName}"),
@ -514,6 +515,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
) )
); );
} }
*/
if (item.link.isNotEmpty) { if (item.link.isNotEmpty) {
tiles.add( tiles.add(
@ -559,7 +561,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
// TODO - Is this stock item linked to a PurchaseOrder? // TODO - Is this stock item linked to a PurchaseOrder?
// TODO - Re-enable stock item history display // TODO - Re-enable stock item history display
if (false && item.trackingItemCount > 0) { /*
if (item.trackingItemCount > 0) {
tiles.add( tiles.add(
ListTile( ListTile(
title: Text(L10().history), title: Text(L10().history),
@ -574,6 +577,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
) )
); );
} }
*/
// Notes field // Notes field
tiles.add( tiles.add(
@ -600,7 +604,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
tiles.add(headerTile()); tiles.add(headerTile());
// First check that the user has the required permissions to adjust stock // First check that the user has the required permissions to adjust stock
if (!InvenTreeAPI().checkPermission('stock', 'change')) { if (!InvenTreeAPI().checkPermission("stock", "change")) {
tiles.add( tiles.add(
ListTile( ListTile(
title: Text(L10().permissionRequired), title: Text(L10().permissionRequired),
@ -710,12 +714,11 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
items: <BottomNavigationBarItem> [ items: <BottomNavigationBarItem> [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.infoCircle), icon: FaIcon(FontAwesomeIcons.infoCircle),
title: Text(L10().details), label: L10().details,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: FaIcon(FontAwesomeIcons.wrench), icon: FaIcon(FontAwesomeIcons.wrench),
title: Text(L10().actions), label: L10().actions, ),
),
] ]
); );
} }

View File

@ -1,27 +1,21 @@
import 'package:inventree/api_form.dart'; import "package:inventree/app_colors.dart";
import 'package:inventree/app_colors.dart'; import "package:inventree/inventree/part.dart";
import 'package:inventree/inventree/part.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/model.dart";
import 'package:inventree/inventree/model.dart'; import "package:inventree/api.dart";
import 'package:inventree/api.dart'; import "package:inventree/widget/progress.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/l10.dart'; import "package:inventree/l10.dart";
import 'dart:io'; import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import 'package:flutter/cupertino.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:flutter/material.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/widget/refreshable_state.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class StockItemTestResultsWidget extends StatefulWidget { class StockItemTestResultsWidget extends StatefulWidget {
StockItemTestResultsWidget(this.item, {Key? key}) : super(key: key); const StockItemTestResultsWidget(this.item, {Key? key}) : super(key: key);
final InvenTreeStockItem item; final InvenTreeStockItem item;
@ -32,8 +26,6 @@ class StockItemTestResultsWidget extends StatefulWidget {
class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestResultsWidget> { class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestResultsWidget> {
final _addResultKey = GlobalKey<FormState>();
@override @override
String getAppBarTitle(BuildContext context) => L10().testResults; String getAppBarTitle(BuildContext context) => L10().testResults;
@ -59,7 +51,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
_StockItemTestResultDisplayState(this.item); _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( InvenTreeStockItemTestResult().createForm(
context, context,
@ -165,7 +157,6 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
String _test = ""; String _test = "";
bool _result = false; bool _result = false;
String _value = ""; String _value = "";
String _notes = "";
FaIcon _icon = FaIcon(FontAwesomeIcons.questionCircle, color: COLOR_BLUE); FaIcon _icon = FaIcon(FontAwesomeIcons.questionCircle, color: COLOR_BLUE);
bool _valueRequired = false; bool _valueRequired = false;
@ -175,8 +166,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
_result = item.passFailStatus(); _result = item.passFailStatus();
_test = item.testName; _test = item.testName;
_required = item.required; _required = item.required;
_value = item.latestResult()?.value ?? ''; _value = item.latestResult()?.value ?? "";
_notes = item.latestResult()?.notes ?? '';
_valueRequired = item.requiresValue; _valueRequired = item.requiresValue;
_attachmentRequired = item.requiresAttachment; _attachmentRequired = item.requiresAttachment;
} else if (item is InvenTreeStockItemTestResult) { } else if (item is InvenTreeStockItemTestResult) {
@ -184,7 +174,6 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
_test = item.testName; _test = item.testName;
_required = false; _required = false;
_value = item.value; _value = item.value;
_notes = item.notes;
} }
if (_result == true) { if (_result == true) {

View File

@ -1,20 +1,20 @@
import 'package:flutter/material.dart'; import "package:flutter/material.dart";
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import "package:font_awesome_flutter/font_awesome_flutter.dart";
import 'package:inventree/inventree/stock.dart'; import "package:inventree/inventree/stock.dart";
import 'package:inventree/widget/refreshable_state.dart'; import "package:inventree/widget/refreshable_state.dart";
import 'package:flutter/cupertino.dart'; import "package:flutter/cupertino.dart";
import 'package:flutter_markdown/flutter_markdown.dart'; import "package:flutter_markdown/flutter_markdown.dart";
import 'package:inventree/l10.dart'; import "package:inventree/l10.dart";
import '../api.dart'; import "package:inventree/api.dart";
class StockNotesWidget extends StatefulWidget { class StockNotesWidget extends StatefulWidget {
final InvenTreeStockItem item; final InvenTreeStockItem item;
StockNotesWidget(this.item, {Key? key}) : super(key: key); const StockNotesWidget(this.item, {Key? key}) : super(key: key);
@override @override
_StockNotesState createState() => _StockNotesState(item); _StockNotesState createState() => _StockNotesState(item);
@ -39,7 +39,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> {
List<Widget> getAppBarActions(BuildContext context) { List<Widget> getAppBarActions(BuildContext context) {
List<Widget> actions = []; List<Widget> actions = [];
if (InvenTreeAPI().checkPermission('stock', 'change')) { if (InvenTreeAPI().checkPermission("stock", "change")) {
actions.add( actions.add(
IconButton( IconButton(
icon: FaIcon(FontAwesomeIcons.edit), icon: FaIcon(FontAwesomeIcons.edit),

View File

@ -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:inventree/l10.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';
class SubmitFeedbackWidget extends StatefulWidget { class SubmitFeedbackWidget extends StatefulWidget {
@ -18,7 +16,7 @@ class SubmitFeedbackWidget extends StatefulWidget {
class _SubmitFeedbackState extends State<SubmitFeedbackWidget> { class _SubmitFeedbackState extends State<SubmitFeedbackWidget> {
final _formkey = new GlobalKey<FormState>(); final _formkey = GlobalKey<FormState>();
String message = ""; String message = "";
@ -61,8 +59,6 @@ class _SubmitFeedbackState extends State<SubmitFeedbackWidget> {
key: _formkey, key: _formkey,
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
TextFormField( TextFormField(

View File

@ -13,41 +13,42 @@ environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
dependencies: dependencies:
audioplayers: ^0.20.1 # Play audio files
cached_network_image: ^3.1.0 # Download and cache remote images
camera: # Camera
cupertino_icons: ^1.0.3
date_field: ^2.1.2 # Date / time picker
device_info_plus: ^2.1.0 # Information about the device
dropdown_search: 0.6.3 # Dropdown autocomplete form fields
file_picker: ^4.0.0 # Select files from the device
flutter: flutter:
sdk: flutter sdk: flutter
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
intl: ^0.17.0
cupertino_icons: ^1.0.3
http: ^0.13.0
cached_network_image: ^3.1.0 # Download and cache remote images
qr_code_scanner: ^0.5.2 # Barcode scanning
package_info_plus: ^1.0.4 # App information introspection
device_info_plus: ^2.1.0 # Information about the device
font_awesome_flutter: ^9.1.0 # FontAwesome icon set
sentry_flutter: 5.0.0 # Error reporting
image_picker: ^0.8.3 # Select or take photos
file_picker: ^4.0.0 # Select files from the device
date_field: ^2.1.2 # Date / time picker
url_launcher: 6.0.9 # Open link in system browser
open_file: 3.2.1 # Open local files
flutter_markdown: ^0.6.2 # Rendering markdown flutter_markdown: ^0.6.2 # Rendering markdown
camera: # Camera font_awesome_flutter: ^9.1.0 # FontAwesome icon set
path_provider: 2.0.2 # Local file storage http: ^0.13.0
sembast: ^3.1.0+2 # NoSQL data storage image_picker: ^0.8.3 # Select or take photos
one_context: ^1.1.0 # Dialogs without requiring context
infinite_scroll_pagination: ^3.1.0 # Let the server do all the work! infinite_scroll_pagination: ^3.1.0 # Let the server do all the work!
audioplayers: ^0.20.1 # Play audio files intl: ^0.17.0
dropdown_search: 0.6.3 # Dropdown autocomplete form fields one_context: ^1.1.0 # Dialogs without requiring context
open_file: 3.2.1 # Open local files
package_info_plus: ^1.0.4 # App information introspection
path: path:
path_provider: 2.0.2 # Local file storage
qr_code_scanner: ^0.5.2 # Barcode scanning
sembast: ^3.1.0+2 # NoSQL data storage
sentry_flutter: 5.0.0 # Error reporting
url_launcher: 6.0.9 # Open link in system browser
dev_dependencies: dev_dependencies:
flutter_launcher_icons:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_launcher_icons:
lint: ^1.0.0 lint: ^1.0.0
flutter_icons: flutter_icons:

View File

@ -5,9 +5,9 @@
// gestures. You can also use WidgetTester to find child widgets in the widget // gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
import 'package:flutter_test/flutter_test.dart'; import "package:flutter_test/flutter_test.dart";
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { testWidgets("Counter increments smoke test", (WidgetTester tester) async {
}); });
} }