mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-29 05:56:47 +00:00
Working on implementation of a related field
This commit is contained in:
parent
a002ce1e8a
commit
ca4297ae6d
@ -128,7 +128,13 @@ class InvenTreeAPI {
|
|||||||
|
|
||||||
String get imageUrl => _makeUrl("/image/");
|
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);
|
String makeUrl(String endpoint) => _makeUrl(endpoint);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter_typeahead/flutter_typeahead.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/app_colors.dart';
|
import 'package:inventree/app_colors.dart';
|
||||||
@ -26,6 +27,9 @@ class APIFormField {
|
|||||||
// JSON data which defines the field
|
// JSON data which defines the field
|
||||||
final dynamic data;
|
final dynamic data;
|
||||||
|
|
||||||
|
// Get the "api_url" associated with a related field
|
||||||
|
String get api_url => data["api_url"] ?? "";
|
||||||
|
|
||||||
// Is this field hidden?
|
// Is this field hidden?
|
||||||
bool get hidden => (data['hidden'] ?? false) as bool;
|
bool get hidden => (data['hidden'] ?? false) as bool;
|
||||||
|
|
||||||
@ -53,6 +57,9 @@ class APIFormField {
|
|||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
dynamic get filters => null;
|
||||||
|
|
||||||
// Is this field required?
|
// Is this field required?
|
||||||
bool get required => (data['required'] ?? false) as bool;
|
bool get required => (data['required'] ?? false) as bool;
|
||||||
|
|
||||||
@ -72,13 +79,32 @@ class APIFormField {
|
|||||||
return _constructString();
|
return _constructString();
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return _constructBoolean();
|
return _constructBoolean();
|
||||||
|
case "related field":
|
||||||
|
return _constructRelatedField();
|
||||||
default:
|
default:
|
||||||
return ListTile(
|
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
|
// Consturct a string input element
|
||||||
Widget _constructString() {
|
Widget _constructString() {
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:inventree/api.dart';
|
||||||
|
|
||||||
import 'package:inventree/l10.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 {
|
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? validator, bool allowEmpty = false, bool isEnabled = true}) :
|
||||||
|
@ -187,6 +187,8 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
"keywords": {},
|
"keywords": {},
|
||||||
"link": {},
|
"link": {},
|
||||||
|
|
||||||
|
"category": {},
|
||||||
|
|
||||||
// Checkbox fields
|
// Checkbox fields
|
||||||
"active": {},
|
"active": {},
|
||||||
"assembly": {},
|
"assembly": {},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user