From 864c3eea76c2303e285b043e8a58c363b32a6d6d Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 4 Dec 2025 18:34:05 +1100 Subject: [PATCH] Parameters refactor (#738) * refactor attachment code into its own file * Add getters * Remove custom models for each type of attachment * Refactor existing widgets * Fix double camera open bug * Add check for modern parameter API * Add generic parameter type * Remove old code * Remove dead code * Refactor previous widget * Remove unused imports * Refactor common code * format * Update release notes * Helper func to render parameters list tile * Display parameters on part page * parameters for company * Supplier more model types: - ManufacturerPart - SupplierPart - PurchaseOrder - SalesOrder * dart format * Fix image prefix * Remove unused import * Adjust API version --- lib/api.dart | 4 + lib/inventree/parameter.dart | 77 ++++++++++++++++++ lib/inventree/part.dart | 62 --------------- lib/preferences.dart | 1 - lib/settings/part_settings.dart | 22 ------ lib/widget/company/company_detail.dart | 25 ++++++ .../company/manufacturer_part_detail.dart | 64 +++++++++++++-- lib/widget/company/supplier_part_detail.dart | 59 ++++++++++++++ lib/widget/order/purchase_order_detail.dart | 25 ++++++ lib/widget/order/sales_order_detail.dart | 25 ++++++ ...eter_widget.dart => parameter_widget.dart} | 78 +++++++++++++++---- lib/widget/part/part_detail.dart | 65 +++++++++------- 12 files changed, 378 insertions(+), 129 deletions(-) create mode 100644 lib/inventree/parameter.dart rename lib/widget/{part/part_parameter_widget.dart => parameter_widget.dart} (58%) diff --git a/lib/api.dart b/lib/api.dart index 1d24b397..61a63798 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -353,6 +353,10 @@ class InvenTreeAPI { // Supports separate search against "supplier" / "customer" / "manufacturer" bool get supportsSplitCompanySearch => apiVersion >= 315; + // Does the server support the "modern" (consolidated) parameter API? + // Ref: https://github.com/inventree/InvenTree/pull/10699 + bool get supportsModernParameters => apiVersion >= 429; + // Cached list of plugins (refreshed when we connect to the server) List _plugins = []; diff --git a/lib/inventree/parameter.dart b/lib/inventree/parameter.dart new file mode 100644 index 00000000..22006d78 --- /dev/null +++ b/lib/inventree/parameter.dart @@ -0,0 +1,77 @@ +import "package:inventree/inventree/model.dart"; + +class InvenTreeParameter extends InvenTreeModel { + InvenTreeParameter() : super(); + + InvenTreeParameter.fromJson(Map json) : super.fromJson(json); + + @override + InvenTreeParameter createFromJson(Map json) => + InvenTreeParameter.fromJson(json); + + @override + String get URL => "parameter/"; + + @override + Map> formFields() { + Map> fields = { + "header": { + "type": "string", + "read_only": true, + "label": name, + "help_text": description, + "value": "", + }, + "data": {"type": "string"}, + "note": {}, + }; + + return fields; + } + + @override + String get name => getString("name", subKey: "template_detail"); + + @override + String get description => getString("description", subKey: "template_detail"); + + String get value => getString("data"); + + String get valueString { + String v = value; + + if (units.isNotEmpty) { + v += " "; + v += units; + } + + return v; + } + + bool get as_bool => value.toLowerCase() == "true"; + + String get units => getString("units", subKey: "template_detail"); + + bool get is_checkbox => + getBool("checkbox", subKey: "template_detail", backup: false); + + // The model type of the instance this attachment is associated with + String get modelType => getString("model_type"); + + // The ID of the instance this attachment is associated with + int get modelId => getInt("model_id"); + + // Return a count of how many parameters exist against the specified model ID + Future countParameters(String modelType, int modelId) async { + Map filters = {}; + + if (!api.supportsModernParameters) { + return 0; + } + + filters["model_type"] = modelType; + filters["model_id"] = modelId.toString(); + + return count(filters: filters); + } +} diff --git a/lib/inventree/part.dart b/lib/inventree/part.dart index fc523992..033fae99 100644 --- a/lib/inventree/part.dart +++ b/lib/inventree/part.dart @@ -132,68 +132,6 @@ class InvenTreePartTestTemplate extends InvenTreeModel { } } -/* - Class representing the PartParameter database model - */ -class InvenTreePartParameter extends InvenTreeModel { - InvenTreePartParameter() : super(); - - InvenTreePartParameter.fromJson(Map json) - : super.fromJson(json); - - @override - String get URL => "part/parameter/"; - - @override - List get rolesRequired => ["part"]; - - @override - InvenTreeModel createFromJson(Map json) => - InvenTreePartParameter.fromJson(json); - - @override - Map> formFields() { - Map> fields = { - "header": { - "type": "string", - "read_only": true, - "label": name, - "help_text": description, - "value": "", - }, - "data": {"type": "string"}, - }; - - return fields; - } - - @override - String get name => getString("name", subKey: "template_detail"); - - @override - String get description => getString("description", subKey: "template_detail"); - - String get value => getString("data"); - - String get valueString { - String v = value; - - if (units.isNotEmpty) { - v += " "; - v += units; - } - - return v; - } - - bool get as_bool => value.toLowerCase() == "true"; - - String get units => getString("units", subKey: "template_detail"); - - bool get is_checkbox => - getBool("checkbox", subKey: "template_detail", backup: false); -} - /* * Class representing the Part database model */ diff --git a/lib/preferences.dart b/lib/preferences.dart index de7bb0f0..92eda1fe 100644 --- a/lib/preferences.dart +++ b/lib/preferences.dart @@ -32,7 +32,6 @@ const String INV_LABEL_DEFAULT_PRINTER = "defaultLabelPrinter"; const String INV_LABEL_DEFAULT_PLUGIN = "defaultLabelPlugin"; // Part settings -const String INV_PART_SHOW_PARAMETERS = "partShowParameters"; const String INV_PART_SHOW_BOM = "partShowBom"; const String INV_PART_SHOW_PRICING = "partShowPricing"; diff --git a/lib/settings/part_settings.dart b/lib/settings/part_settings.dart index b0919316..aa136782 100644 --- a/lib/settings/part_settings.dart +++ b/lib/settings/part_settings.dart @@ -13,7 +13,6 @@ class InvenTreePartSettingsWidget extends StatefulWidget { class _InvenTreePartSettingsState extends State { _InvenTreePartSettingsState(); - bool partShowParameters = true; bool partShowBom = true; bool partShowPricing = true; bool stockShowHistory = false; @@ -28,10 +27,6 @@ class _InvenTreePartSettingsState extends State { } Future loadSettings() async { - partShowParameters = await InvenTreeSettingsManager().getBool( - INV_PART_SHOW_PARAMETERS, - true, - ); partShowBom = await InvenTreeSettingsManager().getBool( INV_PART_SHOW_BOM, true, @@ -68,23 +63,6 @@ class _InvenTreePartSettingsState extends State { body: Container( child: ListView( children: [ - ListTile( - title: Text(L10().parameters), - subtitle: Text(L10().parametersSettingDetail), - leading: Icon(TablerIcons.list), - trailing: Switch( - value: partShowParameters, - onChanged: (bool value) { - InvenTreeSettingsManager().setValue( - INV_PART_SHOW_PARAMETERS, - value, - ); - setState(() { - partShowParameters = value; - }); - }, - ), - ), ListTile( title: Text(L10().bom), subtitle: Text(L10().bomEnable), diff --git a/lib/widget/company/company_detail.dart b/lib/widget/company/company_detail.dart index 8947104b..9a6d233f 100644 --- a/lib/widget/company/company_detail.dart +++ b/lib/widget/company/company_detail.dart @@ -2,6 +2,7 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/inventree/attachment.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/l10.dart"; import "package:inventree/api.dart"; @@ -14,6 +15,7 @@ import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/purchase_order_list.dart"; import "package:inventree/widget/order/sales_order_list.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/company/supplier_part_list.dart"; @@ -38,6 +40,7 @@ class _CompanyDetailState extends RefreshableState { int outstandingPurchaseOrders = 0; int outstandingSalesOrders = 0; + int parameterCount = 0; int attachmentCount = 0; @override @@ -185,6 +188,16 @@ class _CompanyDetailState extends RefreshableState { } }); + InvenTreeParameter() + .countParameters(InvenTreeCompany.MODEL_TYPE, widget.company.pk) + .then((value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + InvenTreeAttachment() .countAttachments(InvenTreeCompany.MODEL_TYPE, widget.company.pk) .then((value) { @@ -394,6 +407,18 @@ class _CompanyDetailState extends RefreshableState { ); } + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreeCompany.MODEL_TYPE, + widget.company.pk, + parameterCount, + widget.company.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + ListTile? attachmentTile = ShowAttachmentsItem( context, InvenTreeCompany.MODEL_TYPE, diff --git a/lib/widget/company/manufacturer_part_detail.dart b/lib/widget/company/manufacturer_part_detail.dart index 9cc6bc23..57a7e48f 100644 --- a/lib/widget/company/manufacturer_part_detail.dart +++ b/lib/widget/company/manufacturer_part_detail.dart @@ -1,6 +1,8 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; +import "package:inventree/inventree/attachment.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/l10.dart"; import "package:inventree/api.dart"; @@ -8,6 +10,8 @@ import "package:inventree/app_colors.dart"; import "package:inventree/inventree/company.dart"; import "package:inventree/inventree/part.dart"; +import "package:inventree/widget/attachment_widget.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -31,6 +35,9 @@ class _ManufacturerPartDisplayState extends RefreshableState { _ManufacturerPartDisplayState(); + int parameterCount = 0; + int attachmentCount = 0; + @override String getAppBarTitle() => L10().manufacturerPart; @@ -42,7 +49,34 @@ class _ManufacturerPartDisplayState if (!result) { Navigator.of(context).pop(); + return; } + + InvenTreeParameter() + .countParameters( + InvenTreeManufacturerPart.MODEL_TYPE, + widget.manufacturerPart.pk, + ) + .then((value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + + InvenTreeAttachment() + .countAttachments( + InvenTreeManufacturerPart.MODEL_TYPE, + widget.manufacturerPart.pk, + ) + .then((value) { + if (mounted) { + setState(() { + attachmentCount = value; + }); + } + }); } Future editManufacturerPart(BuildContext context) async { @@ -91,11 +125,6 @@ class _ManufacturerPartDisplayState List getTiles(BuildContext context) { List tiles = []; - if (loading) { - tiles.add(progressIndicator()); - return tiles; - } - // Internal Part tiles.add( ListTile( @@ -174,6 +203,31 @@ class _ManufacturerPartDisplayState ); } + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreeManufacturerPart.MODEL_TYPE, + widget.manufacturerPart.pk, + parameterCount, + widget.manufacturerPart.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + + ListTile? attachmentTile = ShowAttachmentsItem( + context, + InvenTreeManufacturerPart.MODEL_TYPE, + widget.manufacturerPart.pk, + widget.manufacturerPart.MPN, + attachmentCount, + widget.manufacturerPart.canEdit, + ); + + if (attachmentTile != null) { + tiles.add(attachmentTile); + } + return tiles; } } diff --git a/lib/widget/company/supplier_part_detail.dart b/lib/widget/company/supplier_part_detail.dart index 77e29ab4..ed607483 100644 --- a/lib/widget/company/supplier_part_detail.dart +++ b/lib/widget/company/supplier_part_detail.dart @@ -2,6 +2,9 @@ import "package:flutter/material.dart"; import "package:flutter_speed_dial/flutter_speed_dial.dart"; import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/helpers.dart"; +import "package:inventree/inventree/attachment.dart"; +import "package:inventree/inventree/parameter.dart"; +import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/link_icon.dart"; import "package:inventree/app_colors.dart"; @@ -11,6 +14,7 @@ import "package:inventree/barcode/barcode.dart"; import "package:inventree/inventree/part.dart"; import "package:inventree/inventree/company.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -35,6 +39,9 @@ class _SupplierPartDisplayState extends RefreshableState { _SupplierPartDisplayState(); + int parameterCount = 0; + int attachmentCount = 0; + @override String getAppBarTitle() => L10().supplierPart; @@ -97,7 +104,34 @@ class _SupplierPartDisplayState if (!result) { Navigator.of(context).pop(); + return; } + + InvenTreeParameter() + .countParameters( + InvenTreeSupplierPart.MODEL_TYPE, + widget.supplierPart.pk, + ) + .then((value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + + InvenTreeAttachment() + .countAttachments( + InvenTreeSupplierPart.MODEL_TYPE, + widget.supplierPart.pk, + ) + .then((value) { + if (mounted) { + setState(() { + attachmentCount = value; + }); + } + }); } /* @@ -286,6 +320,31 @@ class _SupplierPartDisplayState ); } + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreeSupplierPart.MODEL_TYPE, + widget.supplierPart.pk, + parameterCount, + widget.supplierPart.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + + ListTile? attachmentTile = ShowAttachmentsItem( + context, + InvenTreeSupplierPart.MODEL_TYPE, + widget.supplierPart.pk, + widget.supplierPart.SKU, + attachmentCount, + widget.supplierPart.canEdit, + ); + + if (attachmentTile != null) { + tiles.add(attachmentTile); + } + return tiles; } } diff --git a/lib/widget/order/purchase_order_detail.dart b/lib/widget/order/purchase_order_detail.dart index 0829e06c..d309a4b3 100644 --- a/lib/widget/order/purchase_order_detail.dart +++ b/lib/widget/order/purchase_order_detail.dart @@ -8,6 +8,7 @@ import "package:inventree/barcode/barcode.dart"; import "package:inventree/barcode/purchase_order.dart"; import "package:inventree/helpers.dart"; import "package:inventree/inventree/attachment.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/l10.dart"; import "package:inventree/inventree/model.dart"; @@ -22,6 +23,7 @@ import "package:inventree/widget/order/po_line_list.dart"; import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/notes_widget.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/widget/snacks.dart"; @@ -51,6 +53,7 @@ class _PurchaseOrderDetailState int completedLines = 0; int attachmentCount = 0; + int parameterCount = 0; bool showCameraShortcut = true; bool supportProjectCodes = false; @@ -300,6 +303,16 @@ class _PurchaseOrderDetailState } } + InvenTreeParameter() + .countParameters(InvenTreePurchaseOrder.MODEL_TYPE, widget.order.pk) + .then((int value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + InvenTreeAttachment() .countAttachments(InvenTreePurchaseOrder.MODEL_TYPE, widget.order.pk) .then((int value) { @@ -570,6 +583,18 @@ class _PurchaseOrderDetailState ), ); + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreePurchaseOrder.MODEL_TYPE, + widget.order.pk, + parameterCount, + widget.order.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + ListTile? attachmentTile = ShowAttachmentsItem( context, InvenTreePurchaseOrder.MODEL_TYPE, diff --git a/lib/widget/order/sales_order_detail.dart b/lib/widget/order/sales_order_detail.dart index 30692f2b..79a3620b 100644 --- a/lib/widget/order/sales_order_detail.dart +++ b/lib/widget/order/sales_order_detail.dart @@ -5,12 +5,14 @@ import "package:inventree/barcode/barcode.dart"; import "package:inventree/barcode/sales_order.dart"; import "package:inventree/inventree/attachment.dart"; import "package:inventree/inventree/company.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/inventree/sales_order.dart"; import "package:inventree/preferences.dart"; import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/order/so_extra_line_list.dart"; import "package:inventree/widget/order/so_line_list.dart"; import "package:inventree/widget/order/so_shipment_list.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/refreshable_state.dart"; import "package:inventree/l10.dart"; @@ -43,6 +45,7 @@ class _SalesOrderDetailState extends RefreshableState { bool showCameraShortcut = true; bool supportsProjectCodes = false; int attachmentCount = 0; + int parameterCount = 0; @override String getAppBarTitle() { @@ -271,6 +274,16 @@ class _SalesOrderDetailState extends RefreshableState { true, ); + InvenTreeParameter() + .countParameters(InvenTreeSalesOrder.MODEL_TYPE, widget.order.pk) + .then((int value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + InvenTreeAttachment() .countAttachments(InvenTreeSalesOrder.MODEL_TYPE, widget.order.pk) .then((int value) { @@ -497,6 +510,18 @@ class _SalesOrderDetailState extends RefreshableState { ), ); + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreeSalesOrder.MODEL_TYPE, + widget.order.pk, + parameterCount, + widget.order.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + ListTile? attachmentTile = ShowAttachmentsItem( context, InvenTreeSalesOrder.MODEL_TYPE, diff --git a/lib/widget/part/part_parameter_widget.dart b/lib/widget/parameter_widget.dart similarity index 58% rename from lib/widget/part/part_parameter_widget.dart rename to lib/widget/parameter_widget.dart index c4df1890..07a38fcd 100644 --- a/lib/widget/part/part_parameter_widget.dart +++ b/lib/widget/parameter_widget.dart @@ -1,8 +1,12 @@ import "package:flutter/material.dart"; +import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; +import "package:inventree/api.dart"; +import "package:inventree/app_colors.dart"; import "package:inventree/inventree/model.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/l10.dart"; -import "package:inventree/inventree/part.dart"; +import "package:inventree/widget/link_icon.dart"; import "package:inventree/widget/paginator.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/refreshable_state.dart"; @@ -10,16 +14,18 @@ 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); +class ParameterWidget extends StatefulWidget { + const ParameterWidget(this.modelType, this.modelId, this.editable) : super(); - final InvenTreePart part; + final String modelType; + final int modelId; + final bool editable; @override _ParameterWidgetState createState() => _ParameterWidgetState(); } -class _ParameterWidgetState extends RefreshableState { +class _ParameterWidgetState extends RefreshableState { _ParameterWidgetState(); @override @@ -34,9 +40,16 @@ class _ParameterWidgetState extends RefreshableState { @override Widget getBody(BuildContext context) { - Map filters = {"part": widget.part.pk.toString()}; + Map filters = { + "model_type": widget.modelType, + "model_id": widget.modelId.toString(), + }; - return Column(children: [Expanded(child: PaginatedParameterList(filters))]); + return Column( + children: [ + Expanded(child: PaginatedParameterList(filters, widget.editable)), + ], + ); } } @@ -44,9 +57,11 @@ class _ParameterWidgetState extends RefreshableState { * Widget for displaying a paginated list of Part parameters */ class PaginatedParameterList extends PaginatedSearchWidget { - const PaginatedParameterList(Map filters) + const PaginatedParameterList(Map filters, this.editable) : super(filters: filters); + final bool editable; + @override String get searchTitle => L10().parameters; @@ -75,7 +90,7 @@ class _PaginatedParameterState int offset, Map params, ) async { - final page = await InvenTreePartParameter().listPaginated( + final page = await InvenTreeParameter().listPaginated( limit, offset, filters: params, @@ -84,7 +99,7 @@ class _PaginatedParameterState return page; } - Future editParameter(InvenTreePartParameter parameter) async { + Future editParameter(InvenTreeParameter parameter) async { // Checkbox values are handled separately if (parameter.is_checkbox) { return; @@ -101,7 +116,7 @@ class _PaginatedParameterState @override Widget buildItem(BuildContext context, InvenTreeModel model) { - InvenTreePartParameter parameter = model as InvenTreePartParameter; + InvenTreeParameter parameter = model as InvenTreeParameter; String title = parameter.name; @@ -116,7 +131,7 @@ class _PaginatedParameterState ? Switch( value: parameter.as_bool, onChanged: (bool value) { - if (parameter.canEdit) { + if (widget.editable) { showLoadingOverlay(); parameter.update(values: {"data": value.toString()}).then(( value, @@ -131,10 +146,47 @@ class _PaginatedParameterState onTap: parameter.is_checkbox ? null : () async { - if (parameter.canEdit) { + if (widget.editable) { editParameter(parameter); } }, ); } } + +/* + * Return a ListTile to display parameters for the specified model + */ +ListTile? ShowParametersItem( + BuildContext context, + String modelType, + int modelId, + int parameterCount, + bool editable, +) { + // Note: Currently cannot add parameters from the app, + // So, if there are no parameters, do not show the item + if (parameterCount == 0) { + return null; + } + + if (!InvenTreeAPI().supportsModernParameters) { + return null; + } + + return ListTile( + title: Text(L10().parameters), + leading: Icon(TablerIcons.list_details, color: COLOR_ACTION), + trailing: LinkIcon( + text: parameterCount > 0 ? parameterCount.toString() : null, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ParameterWidget(modelType, modelId, editable), + ), + ); + }, + ); +} diff --git a/lib/widget/part/part_detail.dart b/lib/widget/part/part_detail.dart index 30b697c4..73a299f8 100644 --- a/lib/widget/part/part_detail.dart +++ b/lib/widget/part/part_detail.dart @@ -5,6 +5,7 @@ import "package:flutter_tabler_icons/flutter_tabler_icons.dart"; import "package:inventree/app_colors.dart"; import "package:inventree/barcode/barcode.dart"; import "package:inventree/inventree/attachment.dart"; +import "package:inventree/inventree/parameter.dart"; import "package:inventree/l10.dart"; import "package:inventree/helpers.dart"; @@ -16,10 +17,10 @@ import "package:inventree/preferences.dart"; import "package:inventree/widget/attachment_widget.dart"; import "package:inventree/widget/link_icon.dart"; +import "package:inventree/widget/parameter_widget.dart"; import "package:inventree/widget/part/bom_list.dart"; import "package:inventree/widget/part/part_list.dart"; import "package:inventree/widget/notes_widget.dart"; -import "package:inventree/widget/part/part_parameter_widget.dart"; import "package:inventree/widget/part/part_pricing.dart"; import "package:inventree/widget/progress.dart"; import "package:inventree/widget/part/category_display.dart"; @@ -50,13 +51,11 @@ class _PartDisplayState extends RefreshableState { InvenTreeStockLocation? defaultLocation; - int parameterCount = 0; - bool allowLabelPrinting = false; - bool showParameters = false; bool showBom = false; bool showPricing = false; + int parameterCount = 0; int attachmentCount = 0; int bomCount = 0; int usedInCount = 0; @@ -153,10 +152,6 @@ class _PartDisplayState extends RefreshableState { INV_PART_SHOW_PRICING, true, ); - showParameters = await InvenTreeSettingsManager().getBool( - INV_PART_SHOW_PARAMETERS, - true, - ); showBom = await InvenTreeSettingsManager().getBool(INV_PART_SHOW_BOM, true); allowLabelPrinting = await InvenTreeSettingsManager().getBool( INV_ENABLE_LABEL_PRINTING, @@ -213,15 +208,30 @@ class _PartDisplayState extends RefreshableState { } // Request the number of attachments - InvenTreeAttachment() - .countAttachments(InvenTreePart.MODEL_TYPE, part.pk) - .then((int value) { - if (mounted) { - setState(() { - attachmentCount = value; - }); - } - }); + if (api.supportsModernAttachments) { + InvenTreeAttachment() + .countAttachments(InvenTreePart.MODEL_TYPE, part.pk) + .then((int value) { + if (mounted) { + setState(() { + attachmentCount = value; + }); + } + }); + } + + // Request the number of parameters + if (api.supportsModernParameters) { + InvenTreeParameter() + .countParameters(InvenTreePart.MODEL_TYPE, part.pk) + .then((int value) { + if (mounted) { + setState(() { + parameterCount = value; + }); + } + }); + } // If show pricing information? if (showPricing) { @@ -599,6 +609,18 @@ class _PartDisplayState extends RefreshableState { ), ); + ListTile? parameterTile = ShowParametersItem( + context, + InvenTreePart.MODEL_TYPE, + part.pk, + parameterCount, + part.canEdit, + ); + + if (parameterTile != null) { + tiles.add(parameterTile); + } + ListTile? attachmentTile = ShowAttachmentsItem( context, InvenTreePart.MODEL_TYPE, @@ -705,10 +727,6 @@ class _PartDisplayState extends RefreshableState { List getTabIcons(BuildContext context) { List icons = [Tab(text: L10().details), Tab(text: L10().stock)]; - if (showParameters) { - icons.add(Tab(text: L10().parameters)); - } - return icons; } @@ -721,11 +739,6 @@ class _PartDisplayState extends RefreshableState { ), PaginatedStockItemList({"part": part.pk.toString()}), ]; - - if (showParameters) { - tabs.add(PaginatedParameterList({"part": part.pk.toString()})); - } - return tabs; } }