2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 13:36:50 +00:00

Part parameters (#224)

* Adds class representing the PartParameter model

* Adds API method for determining support for PartParmaters

* Display part parameter count in part detail widget

* Adds user setting for controlling if part parameters are displayed

* Fix URL for model

* Widget for displaying part parameters

* linting
This commit is contained in:
Oliver 2022-12-04 20:51:48 +11:00 committed by GitHub
parent 207e5ec6c5
commit c2574e9fa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 230 additions and 15 deletions

View File

@ -4,6 +4,7 @@
### - December 2022 ### - December 2022
--- ---
- Support Part parameters
- Add support for structural part categories - Add support for structural part categories
- Add support for structural stock locations - Add support for structural stock locations
- Allow deletion of attachments via app - Allow deletion of attachments via app

View File

@ -262,6 +262,9 @@ class InvenTreeAPI {
// Structural categories requires API v83 or newer // Structural categories requires API v83 or newer
bool get supportsStructuralCategories => isConnected() && apiVersion >= 83; bool get supportsStructuralCategories => isConnected() && apiVersion >= 83;
// Part parameter support requires API v56 or newer
bool get supportsPartParameters => isConnected() && apiVersion >= 56;
// Are plugins enabled on the server? // Are plugins enabled on the server?
bool _pluginsEnabled = false; bool _pluginsEnabled = false;

View File

@ -125,6 +125,49 @@ class InvenTreePartTestTemplate extends InvenTreeModel {
} }
/*
Class representing the PartParameter database model
*/
class InvenTreePartParameter extends InvenTreeModel {
InvenTreePartParameter() : super();
InvenTreePartParameter.fromJson(Map<String, dynamic> json) : super.fromJson(json);
@override
String get URL => "part/parameter/";
@override
InvenTreeModel createFromJson(Map<String, dynamic> json) {
return InvenTreePartParameter.fromJson(json);
}
@override
Map<String, dynamic> formFields() {
return {};
}
@override
String get name => (jsondata["template_detail"]?["name"] ?? "") as String;
@override
String get description => (jsondata["template_detail"]?["description"] ?? "") as String;
String get value => jsondata["data"] as String;
String get valueString {
String v = value;
if (units.isNotEmpty) {
v += " ";
v += units;
}
return v;
}
String get units => (jsondata["template_detail"]?["units"] ?? "") as String;
}
/* /*
* Class representing the Part database model * Class representing the Part database model

View File

@ -579,6 +579,12 @@
"packageName": "Package Name", "packageName": "Package Name",
"@packageName": {}, "@packageName": {},
"parameters": "Parameters",
"@parameters": {},
"parametersSettingDetail": "Display part parameters",
"@parametersSettingDetail": {},
"parent": "Parent", "parent": "Parent",
"@parent": {}, "@parent": {},

View File

@ -18,6 +18,10 @@ const String INV_HOME_SHOW_SUPPLIERS = "homeShowSuppliers";
const String INV_SOUNDS_BARCODE = "barcodeSounds"; const String INV_SOUNDS_BARCODE = "barcodeSounds";
const String INV_SOUNDS_SERVER = "serverSounds"; const String INV_SOUNDS_SERVER = "serverSounds";
// Part settings
const String INV_PART_SHOW_PARAMETERS = "partShowParameters";
// Stock settings
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory"; const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
const String INV_REPORT_ERRORS = "reportErrors"; const String INV_REPORT_ERRORS = "reportErrors";

View File

@ -25,6 +25,9 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
bool barcodeSounds = true; bool barcodeSounds = true;
bool serverSounds = true; bool serverSounds = true;
// Part settings
bool partShowParameters = true;
// Stock settings // Stock settings
bool stockShowHistory = false; bool stockShowHistory = false;
@ -47,6 +50,8 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool; barcodeSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_BARCODE, true) as bool;
serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool; serverSounds = await InvenTreeSettingsManager().getValue(INV_SOUNDS_SERVER, true) as bool;
partShowParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool; stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool; reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
@ -132,6 +137,26 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
body: Container( body: Container(
child: ListView( child: ListView(
children: [ children: [
/* Part Settings */
ListTile(
title: Text(L10().part, style: TextStyle(fontWeight: FontWeight.bold)),
leading: FaIcon(FontAwesomeIcons.shapes),
),
ListTile(
title: Text(L10().parameters),
subtitle: Text(L10().parametersSettingDetail),
leading: FaIcon(FontAwesomeIcons.thList),
trailing: Switch(
value: partShowParameters,
onChanged: (bool value) {
InvenTreeSettingsManager().setValue(INV_PART_SHOW_PARAMETERS, value);
setState(() {
partShowParameters = value;
});
},
),
),
Divider(),
/* Stock Settings */ /* Stock Settings */
ListTile( ListTile(
title: Text(L10().stock, title: Text(L10().stock,

View File

@ -10,11 +10,13 @@ import "package:inventree/helpers.dart";
import "package:inventree/inventree/bom.dart"; import "package:inventree/inventree/bom.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/preferences.dart";
import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/attachment_widget.dart";
import "package:inventree/widget/bom_list.dart"; import "package:inventree/widget/bom_list.dart";
import "package:inventree/widget/part_list.dart"; import "package:inventree/widget/part_list.dart";
import "package:inventree/widget/part_notes.dart"; import "package:inventree/widget/part_notes.dart";
import "package:inventree/widget/part_parameter_widget.dart";
import "package:inventree/widget/progress.dart"; import "package:inventree/widget/progress.dart";
import "package:inventree/widget/category_display.dart"; import "package:inventree/widget/category_display.dart";
import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/refreshable_state.dart";
@ -47,6 +49,10 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
InvenTreePart? parentPart; InvenTreePart? parentPart;
int parameterCount = 0;
bool showParameters = false;
int attachmentCount = 0; int attachmentCount = 0;
int bomCount = 0; int bomCount = 0;
@ -132,6 +138,24 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
} }
}); });
// Request the number of parameters for this part
if (InvenTreeAPI().supportsPartParameters) {
showParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
InvenTreePartParameter().count(
filters: {
"part": part.pk.toString(),
}
).then((int value) {
if (mounted) {
setState(() {
parameterCount = value;
});
}
});
}
// Request the number of attachments // Request the number of attachments
InvenTreePartAttachment().count( InvenTreePartAttachment().count(
filters: { filters: {
@ -510,20 +534,6 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
); );
} }
// TODO - Add request tests?
/*
if (part.isTrackable) {
tiles.add(ListTile(
title: Text(L10().testsRequired),
leading: FaIcon(FontAwesomeIcons.tasks),
trailing: Text("${part.testTemplateCount}"),
onTap: null,
)
);
}
*/
// Notes field // Notes field
tiles.add( tiles.add(
ListTile( ListTile(
@ -539,6 +549,24 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
) )
); );
if (showParameters) {
tiles.add(
ListTile(
title: Text(L10().parameters),
leading: FaIcon(FontAwesomeIcons.thList, color: COLOR_CLICK),
trailing: parameterCount > 0 ? Text(parameterCount.toString()) : null,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PartParameterWidget(part)
)
);
}
)
);
}
tiles.add( tiles.add(
ListTile( ListTile(
title: Text(L10().attachments), title: Text(L10().attachments),

View File

@ -0,0 +1,105 @@
import "package:flutter/material.dart";
import "package:inventree/inventree/model.dart";
import "package:inventree/l10.dart";
import "package:inventree/inventree/part.dart";
import "package:inventree/widget/paginator.dart";
import "package:inventree/widget/refreshable_state.dart";
/*
* Widget for displaying a list of parameters associated with a given Part instance
*/
class PartParameterWidget extends StatefulWidget {
const PartParameterWidget(this.part);
final InvenTreePart part;
@override
_ParameterWidgetState createState() => _ParameterWidgetState();
}
class _ParameterWidgetState extends RefreshableState<PartParameterWidget> {
_ParameterWidgetState();
@override
String getAppBarTitle(BuildContext context) {
return L10().parameters;
}
@override
List<Widget> getAppBarActions(BuildContext context) {
return [];
}
@override
Widget getBody(BuildContext context) {
Map<String, String> filters = {
"part": widget.part.pk.toString()
};
return Column(
children: [
Expanded(
child: PaginatedParameterList(
filters,
false,
)
)
],
);
}
}
/*
* Widget for displaying a paginated list of Part parameters
*/
class PaginatedParameterList extends PaginatedSearchWidget {
const PaginatedParameterList(Map<String, String> filters, bool showSearch) : super(filters: filters, showSearch: showSearch);
@override
_PaginatedParameterState createState() => _PaginatedParameterState();
}
class _PaginatedParameterState extends PaginatedSearchState<PaginatedParameterList> {
_PaginatedParameterState() : super();
@override
String get prefix => "parameters_";
@override
Map<String, String> get orderingOptions => {
// TODO
};
@override
Map<String, Map<String, dynamic>> get filterOptions => {
// TODO
};
@override
Future<InvenTreePageResponse?> requestPage(int limit, int offset, Map<String, String> params) async {
final page = await InvenTreePartParameter().listPaginated(limit, offset, filters: params);
return page;
}
@override
Widget buildItem(BuildContext context, InvenTreeModel model) {
InvenTreePartParameter parameter = model as InvenTreePartParameter;
return ListTile(
title: Text(parameter.name),
subtitle: Text(parameter.description),
trailing: Text(parameter.valueString),
);
}
}