mirror of
https://github.com/inventree/inventree-app.git
synced 2025-12-15 08:38:12 +00:00
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
This commit is contained in:
@@ -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<InvenTreePlugin> _plugins = [];
|
||||
|
||||
|
||||
77
lib/inventree/parameter.dart
Normal file
77
lib/inventree/parameter.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
import "package:inventree/inventree/model.dart";
|
||||
|
||||
class InvenTreeParameter extends InvenTreeModel {
|
||||
InvenTreeParameter() : super();
|
||||
|
||||
InvenTreeParameter.fromJson(Map<String, dynamic> json) : super.fromJson(json);
|
||||
|
||||
@override
|
||||
InvenTreeParameter createFromJson(Map<String, dynamic> json) =>
|
||||
InvenTreeParameter.fromJson(json);
|
||||
|
||||
@override
|
||||
String get URL => "parameter/";
|
||||
|
||||
@override
|
||||
Map<String, Map<String, dynamic>> formFields() {
|
||||
Map<String, Map<String, dynamic>> 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<int> countParameters(String modelType, int modelId) async {
|
||||
Map<String, String> filters = {};
|
||||
|
||||
if (!api.supportsModernParameters) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
filters["model_type"] = modelType;
|
||||
filters["model_id"] = modelId.toString();
|
||||
|
||||
return count(filters: filters);
|
||||
}
|
||||
}
|
||||
@@ -132,68 +132,6 @@ 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
|
||||
List<String> get rolesRequired => ["part"];
|
||||
|
||||
@override
|
||||
InvenTreeModel createFromJson(Map<String, dynamic> json) =>
|
||||
InvenTreePartParameter.fromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, Map<String, dynamic>> formFields() {
|
||||
Map<String, Map<String, dynamic>> 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
|
||||
*/
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ class InvenTreePartSettingsWidget extends StatefulWidget {
|
||||
class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
||||
_InvenTreePartSettingsState();
|
||||
|
||||
bool partShowParameters = true;
|
||||
bool partShowBom = true;
|
||||
bool partShowPricing = true;
|
||||
bool stockShowHistory = false;
|
||||
@@ -28,10 +27,6 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
||||
}
|
||||
|
||||
Future<void> 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<InvenTreePartSettingsWidget> {
|
||||
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),
|
||||
|
||||
@@ -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<CompanyDetailWidget> {
|
||||
int outstandingPurchaseOrders = 0;
|
||||
int outstandingSalesOrders = 0;
|
||||
|
||||
int parameterCount = 0;
|
||||
int attachmentCount = 0;
|
||||
|
||||
@override
|
||||
@@ -185,6 +188,16 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
|
||||
}
|
||||
});
|
||||
|
||||
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<CompanyDetailWidget> {
|
||||
);
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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<ManufacturerPartDetailWidget> {
|
||||
_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<void> editManufacturerPart(BuildContext context) async {
|
||||
@@ -91,11 +125,6 @@ class _ManufacturerPartDisplayState
|
||||
List<Widget> getTiles(BuildContext context) {
|
||||
List<Widget> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SupplierPartDetailWidget> {
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<SalesOrderDetailWidget> {
|
||||
bool showCameraShortcut = true;
|
||||
bool supportsProjectCodes = false;
|
||||
int attachmentCount = 0;
|
||||
int parameterCount = 0;
|
||||
|
||||
@override
|
||||
String getAppBarTitle() {
|
||||
@@ -271,6 +274,16 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
|
||||
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<SalesOrderDetailWidget> {
|
||||
),
|
||||
);
|
||||
|
||||
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,
|
||||
|
||||
@@ -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<PartParameterWidget> {
|
||||
class _ParameterWidgetState extends RefreshableState<ParameterWidget> {
|
||||
_ParameterWidgetState();
|
||||
|
||||
@override
|
||||
@@ -34,9 +40,16 @@ class _ParameterWidgetState extends RefreshableState<PartParameterWidget> {
|
||||
|
||||
@override
|
||||
Widget getBody(BuildContext context) {
|
||||
Map<String, String> filters = {"part": widget.part.pk.toString()};
|
||||
Map<String, String> 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<PartParameterWidget> {
|
||||
* Widget for displaying a paginated list of Part parameters
|
||||
*/
|
||||
class PaginatedParameterList extends PaginatedSearchWidget {
|
||||
const PaginatedParameterList(Map<String, String> filters)
|
||||
const PaginatedParameterList(Map<String, String> filters, this.editable)
|
||||
: super(filters: filters);
|
||||
|
||||
final bool editable;
|
||||
|
||||
@override
|
||||
String get searchTitle => L10().parameters;
|
||||
|
||||
@@ -75,7 +90,7 @@ class _PaginatedParameterState
|
||||
int offset,
|
||||
Map<String, String> 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<void> editParameter(InvenTreePartParameter parameter) async {
|
||||
Future<void> 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),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -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<PartDetailWidget> {
|
||||
|
||||
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<PartDetailWidget> {
|
||||
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<PartDetailWidget> {
|
||||
}
|
||||
|
||||
// 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<PartDetailWidget> {
|
||||
),
|
||||
);
|
||||
|
||||
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<PartDetailWidget> {
|
||||
List<Widget> getTabIcons(BuildContext context) {
|
||||
List<Widget> 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<PartDetailWidget> {
|
||||
),
|
||||
PaginatedStockItemList({"part": part.pk.toString()}),
|
||||
];
|
||||
|
||||
if (showParameters) {
|
||||
tabs.add(PaginatedParameterList({"part": part.pk.toString()}));
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user