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

Working on implementation of a related field

This commit is contained in:
Oliver 2021-07-25 23:26:27 +10:00
parent a002ce1e8a
commit ca4297ae6d
4 changed files with 113 additions and 2 deletions

View File

@ -128,7 +128,13 @@ class InvenTreeAPI {
String get imageUrl => _makeUrl("/image/");
String makeApiUrl(String endpoint) => _makeUrl("/api/" + endpoint);
String makeApiUrl(String endpoint) {
if (endpoint.startsWith("/api/") || endpoint.startsWith("api/")) {
return _makeUrl(endpoint);
} else {
return _makeUrl("/api/" + endpoint);
}
}
String makeUrl(String endpoint) => _makeUrl(endpoint);

View File

@ -1,3 +1,4 @@
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:inventree/api.dart';
import 'package:inventree/app_colors.dart';
@ -26,6 +27,9 @@ class APIFormField {
// JSON data which defines the field
final dynamic data;
// Get the "api_url" associated with a related field
String get api_url => data["api_url"] ?? "";
// Is this field hidden?
bool get hidden => (data['hidden'] ?? false) as bool;
@ -53,6 +57,9 @@ class APIFormField {
return messages;
}
// TODO
dynamic get filters => null;
// Is this field required?
bool get required => (data['required'] ?? false) as bool;
@ -72,13 +79,32 @@ class APIFormField {
return _constructString();
case "boolean":
return _constructBoolean();
case "related field":
return _constructRelatedField();
default:
return ListTile(
title: Text("Unsupported field type: '${type}'")
title: Text(
"Unsupported field type: '${type}'",
style: TextStyle(
color: COLOR_DANGER,
fontStyle: FontStyle.italic),
)
);
}
}
// Construct an input for a related field
Widget _constructRelatedField() {
return AutocompleteFormField(
required ? label + "*" : label,
api_url,
filters: filters,
hint: helpText,
renderer: null,
);
}
// Consturct a string input element
Widget _constructString() {

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:image_picker/image_picker.dart';
import 'package:inventree/api.dart';
import 'package:inventree/l10.dart';
@ -115,6 +117,81 @@ class CheckBoxField extends FormField<bool> {
}
class AutocompleteFormField extends TypeAheadFormField {
final String label;
final _controller = TextEditingController();
final String url;
dynamic filters = {};
AutocompleteFormField(
this.label,
this.url,
{
this.filters,
Widget Function(dynamic)? renderer,
String? hint,
}) :
super(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
decoration: InputDecoration(
hintText: hint,
border: OutlineInputBorder(),
),
),
suggestionsCallback: (String pattern) async {
Map<String, String> _filters = {};
if (filters != null) {
for (String key in filters) {
_filters[key] = filters[key].toString();
}
}
_filters["search"] = pattern;
_filters["offset"] = "0";
_filters["limit"] = "25";
final APIResponse response = await InvenTreeAPI().get(
url,
params: _filters
);
if (response.isValid()) {
List<dynamic> results = [];
for (var result in response.data['results'] ?? []) {
results.add(result);
}
return results;
} else {
return [];
}
},
itemBuilder: (context, suggestion) {
print("item builder: " + suggestion.toString());
return ListTile(
title: Text(suggestion['name']),
);
},
onSuggestionSelected: (suggestion) {
// TODO
},
onSaved: (value) {
// TODO
}
);
}
class StringField extends TextFormField {
StringField({String label = "", String? hint, String? initial, Function(String?)? onSaved, Function? validator, bool allowEmpty = false, bool isEnabled = true}) :

View File

@ -187,6 +187,8 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
"keywords": {},
"link": {},
"category": {},
// Checkbox fields
"active": {},
"assembly": {},