mirror of
https://github.com/inventree/inventree-app.git
synced 2025-12-16 09:08:05 +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"
|
// Supports separate search against "supplier" / "customer" / "manufacturer"
|
||||||
bool get supportsSplitCompanySearch => apiVersion >= 315;
|
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)
|
// Cached list of plugins (refreshed when we connect to the server)
|
||||||
List<InvenTreePlugin> _plugins = [];
|
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
|
* Class representing the Part database model
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ const String INV_LABEL_DEFAULT_PRINTER = "defaultLabelPrinter";
|
|||||||
const String INV_LABEL_DEFAULT_PLUGIN = "defaultLabelPlugin";
|
const String INV_LABEL_DEFAULT_PLUGIN = "defaultLabelPlugin";
|
||||||
|
|
||||||
// Part settings
|
// Part settings
|
||||||
const String INV_PART_SHOW_PARAMETERS = "partShowParameters";
|
|
||||||
const String INV_PART_SHOW_BOM = "partShowBom";
|
const String INV_PART_SHOW_BOM = "partShowBom";
|
||||||
const String INV_PART_SHOW_PRICING = "partShowPricing";
|
const String INV_PART_SHOW_PRICING = "partShowPricing";
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class InvenTreePartSettingsWidget extends StatefulWidget {
|
|||||||
class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
||||||
_InvenTreePartSettingsState();
|
_InvenTreePartSettingsState();
|
||||||
|
|
||||||
bool partShowParameters = true;
|
|
||||||
bool partShowBom = true;
|
bool partShowBom = true;
|
||||||
bool partShowPricing = true;
|
bool partShowPricing = true;
|
||||||
bool stockShowHistory = false;
|
bool stockShowHistory = false;
|
||||||
@@ -28,10 +27,6 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadSettings() async {
|
Future<void> loadSettings() async {
|
||||||
partShowParameters = await InvenTreeSettingsManager().getBool(
|
|
||||||
INV_PART_SHOW_PARAMETERS,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
partShowBom = await InvenTreeSettingsManager().getBool(
|
partShowBom = await InvenTreeSettingsManager().getBool(
|
||||||
INV_PART_SHOW_BOM,
|
INV_PART_SHOW_BOM,
|
||||||
true,
|
true,
|
||||||
@@ -68,23 +63,6 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
|||||||
body: Container(
|
body: Container(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
children: [
|
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(
|
ListTile(
|
||||||
title: Text(L10().bom),
|
title: Text(L10().bom),
|
||||||
subtitle: Text(L10().bomEnable),
|
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_speed_dial/flutter_speed_dial.dart";
|
||||||
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
|
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
|
||||||
import "package:inventree/inventree/attachment.dart";
|
import "package:inventree/inventree/attachment.dart";
|
||||||
|
import "package:inventree/inventree/parameter.dart";
|
||||||
|
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
import "package:inventree/api.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/link_icon.dart";
|
||||||
import "package:inventree/widget/order/purchase_order_list.dart";
|
import "package:inventree/widget/order/purchase_order_list.dart";
|
||||||
import "package:inventree/widget/order/sales_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/refreshable_state.dart";
|
||||||
import "package:inventree/widget/snacks.dart";
|
import "package:inventree/widget/snacks.dart";
|
||||||
import "package:inventree/widget/company/supplier_part_list.dart";
|
import "package:inventree/widget/company/supplier_part_list.dart";
|
||||||
@@ -38,6 +40,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
|
|||||||
int outstandingPurchaseOrders = 0;
|
int outstandingPurchaseOrders = 0;
|
||||||
int outstandingSalesOrders = 0;
|
int outstandingSalesOrders = 0;
|
||||||
|
|
||||||
|
int parameterCount = 0;
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
|
|
||||||
@override
|
@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()
|
InvenTreeAttachment()
|
||||||
.countAttachments(InvenTreeCompany.MODEL_TYPE, widget.company.pk)
|
.countAttachments(InvenTreeCompany.MODEL_TYPE, widget.company.pk)
|
||||||
.then((value) {
|
.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(
|
ListTile? attachmentTile = ShowAttachmentsItem(
|
||||||
context,
|
context,
|
||||||
InvenTreeCompany.MODEL_TYPE,
|
InvenTreeCompany.MODEL_TYPE,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
||||||
import "package:flutter_tabler_icons/flutter_tabler_icons.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/l10.dart";
|
||||||
import "package:inventree/api.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/company.dart";
|
||||||
import "package:inventree/inventree/part.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/refreshable_state.dart";
|
||||||
import "package:inventree/widget/snacks.dart";
|
import "package:inventree/widget/snacks.dart";
|
||||||
@@ -31,6 +35,9 @@ class _ManufacturerPartDisplayState
|
|||||||
extends RefreshableState<ManufacturerPartDetailWidget> {
|
extends RefreshableState<ManufacturerPartDetailWidget> {
|
||||||
_ManufacturerPartDisplayState();
|
_ManufacturerPartDisplayState();
|
||||||
|
|
||||||
|
int parameterCount = 0;
|
||||||
|
int attachmentCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getAppBarTitle() => L10().manufacturerPart;
|
String getAppBarTitle() => L10().manufacturerPart;
|
||||||
|
|
||||||
@@ -42,7 +49,34 @@ class _ManufacturerPartDisplayState
|
|||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
Navigator.of(context).pop();
|
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 {
|
Future<void> editManufacturerPart(BuildContext context) async {
|
||||||
@@ -91,11 +125,6 @@ class _ManufacturerPartDisplayState
|
|||||||
List<Widget> getTiles(BuildContext context) {
|
List<Widget> getTiles(BuildContext context) {
|
||||||
List<Widget> tiles = [];
|
List<Widget> tiles = [];
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
tiles.add(progressIndicator());
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal Part
|
// Internal Part
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
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;
|
return tiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ import "package:flutter/material.dart";
|
|||||||
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
||||||
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
|
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
|
||||||
import "package:inventree/helpers.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/widget/link_icon.dart";
|
||||||
|
|
||||||
import "package:inventree/app_colors.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/part.dart";
|
||||||
import "package:inventree/inventree/company.dart";
|
import "package:inventree/inventree/company.dart";
|
||||||
|
import "package:inventree/widget/parameter_widget.dart";
|
||||||
|
|
||||||
import "package:inventree/widget/progress.dart";
|
import "package:inventree/widget/progress.dart";
|
||||||
import "package:inventree/widget/refreshable_state.dart";
|
import "package:inventree/widget/refreshable_state.dart";
|
||||||
@@ -35,6 +39,9 @@ class _SupplierPartDisplayState
|
|||||||
extends RefreshableState<SupplierPartDetailWidget> {
|
extends RefreshableState<SupplierPartDetailWidget> {
|
||||||
_SupplierPartDisplayState();
|
_SupplierPartDisplayState();
|
||||||
|
|
||||||
|
int parameterCount = 0;
|
||||||
|
int attachmentCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getAppBarTitle() => L10().supplierPart;
|
String getAppBarTitle() => L10().supplierPart;
|
||||||
|
|
||||||
@@ -97,7 +104,34 @@ class _SupplierPartDisplayState
|
|||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
Navigator.of(context).pop();
|
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;
|
return tiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import "package:inventree/barcode/barcode.dart";
|
|||||||
import "package:inventree/barcode/purchase_order.dart";
|
import "package:inventree/barcode/purchase_order.dart";
|
||||||
import "package:inventree/helpers.dart";
|
import "package:inventree/helpers.dart";
|
||||||
import "package:inventree/inventree/attachment.dart";
|
import "package:inventree/inventree/attachment.dart";
|
||||||
|
import "package:inventree/inventree/parameter.dart";
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
|
|
||||||
import "package:inventree/inventree/model.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/attachment_widget.dart";
|
||||||
import "package:inventree/widget/notes_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/progress.dart";
|
||||||
import "package:inventree/widget/refreshable_state.dart";
|
import "package:inventree/widget/refreshable_state.dart";
|
||||||
import "package:inventree/widget/snacks.dart";
|
import "package:inventree/widget/snacks.dart";
|
||||||
@@ -51,6 +53,7 @@ class _PurchaseOrderDetailState
|
|||||||
|
|
||||||
int completedLines = 0;
|
int completedLines = 0;
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
|
int parameterCount = 0;
|
||||||
|
|
||||||
bool showCameraShortcut = true;
|
bool showCameraShortcut = true;
|
||||||
bool supportProjectCodes = false;
|
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()
|
InvenTreeAttachment()
|
||||||
.countAttachments(InvenTreePurchaseOrder.MODEL_TYPE, widget.order.pk)
|
.countAttachments(InvenTreePurchaseOrder.MODEL_TYPE, widget.order.pk)
|
||||||
.then((int value) {
|
.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(
|
ListTile? attachmentTile = ShowAttachmentsItem(
|
||||||
context,
|
context,
|
||||||
InvenTreePurchaseOrder.MODEL_TYPE,
|
InvenTreePurchaseOrder.MODEL_TYPE,
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ import "package:inventree/barcode/barcode.dart";
|
|||||||
import "package:inventree/barcode/sales_order.dart";
|
import "package:inventree/barcode/sales_order.dart";
|
||||||
import "package:inventree/inventree/attachment.dart";
|
import "package:inventree/inventree/attachment.dart";
|
||||||
import "package:inventree/inventree/company.dart";
|
import "package:inventree/inventree/company.dart";
|
||||||
|
import "package:inventree/inventree/parameter.dart";
|
||||||
import "package:inventree/inventree/sales_order.dart";
|
import "package:inventree/inventree/sales_order.dart";
|
||||||
import "package:inventree/preferences.dart";
|
import "package:inventree/preferences.dart";
|
||||||
import "package:inventree/widget/link_icon.dart";
|
import "package:inventree/widget/link_icon.dart";
|
||||||
import "package:inventree/widget/order/so_extra_line_list.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_line_list.dart";
|
||||||
import "package:inventree/widget/order/so_shipment_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/widget/refreshable_state.dart";
|
||||||
|
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
@@ -43,6 +45,7 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
|
|||||||
bool showCameraShortcut = true;
|
bool showCameraShortcut = true;
|
||||||
bool supportsProjectCodes = false;
|
bool supportsProjectCodes = false;
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
|
int parameterCount = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String getAppBarTitle() {
|
String getAppBarTitle() {
|
||||||
@@ -271,6 +274,16 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
InvenTreeParameter()
|
||||||
|
.countParameters(InvenTreeSalesOrder.MODEL_TYPE, widget.order.pk)
|
||||||
|
.then((int value) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
parameterCount = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
InvenTreeAttachment()
|
InvenTreeAttachment()
|
||||||
.countAttachments(InvenTreeSalesOrder.MODEL_TYPE, widget.order.pk)
|
.countAttachments(InvenTreeSalesOrder.MODEL_TYPE, widget.order.pk)
|
||||||
.then((int value) {
|
.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(
|
ListTile? attachmentTile = ShowAttachmentsItem(
|
||||||
context,
|
context,
|
||||||
InvenTreeSalesOrder.MODEL_TYPE,
|
InvenTreeSalesOrder.MODEL_TYPE,
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import "package:flutter/material.dart";
|
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/model.dart";
|
||||||
|
import "package:inventree/inventree/parameter.dart";
|
||||||
|
|
||||||
import "package:inventree/l10.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/paginator.dart";
|
||||||
import "package:inventree/widget/progress.dart";
|
import "package:inventree/widget/progress.dart";
|
||||||
import "package:inventree/widget/refreshable_state.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
|
* Widget for displaying a list of parameters associated with a given Part instance
|
||||||
*/
|
*/
|
||||||
class PartParameterWidget extends StatefulWidget {
|
class ParameterWidget extends StatefulWidget {
|
||||||
const PartParameterWidget(this.part);
|
const ParameterWidget(this.modelType, this.modelId, this.editable) : super();
|
||||||
|
|
||||||
final InvenTreePart part;
|
final String modelType;
|
||||||
|
final int modelId;
|
||||||
|
final bool editable;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ParameterWidgetState createState() => _ParameterWidgetState();
|
_ParameterWidgetState createState() => _ParameterWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ParameterWidgetState extends RefreshableState<PartParameterWidget> {
|
class _ParameterWidgetState extends RefreshableState<ParameterWidget> {
|
||||||
_ParameterWidgetState();
|
_ParameterWidgetState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -34,9 +40,16 @@ class _ParameterWidgetState extends RefreshableState<PartParameterWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget getBody(BuildContext context) {
|
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
|
* Widget for displaying a paginated list of Part parameters
|
||||||
*/
|
*/
|
||||||
class PaginatedParameterList extends PaginatedSearchWidget {
|
class PaginatedParameterList extends PaginatedSearchWidget {
|
||||||
const PaginatedParameterList(Map<String, String> filters)
|
const PaginatedParameterList(Map<String, String> filters, this.editable)
|
||||||
: super(filters: filters);
|
: super(filters: filters);
|
||||||
|
|
||||||
|
final bool editable;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get searchTitle => L10().parameters;
|
String get searchTitle => L10().parameters;
|
||||||
|
|
||||||
@@ -75,7 +90,7 @@ class _PaginatedParameterState
|
|||||||
int offset,
|
int offset,
|
||||||
Map<String, String> params,
|
Map<String, String> params,
|
||||||
) async {
|
) async {
|
||||||
final page = await InvenTreePartParameter().listPaginated(
|
final page = await InvenTreeParameter().listPaginated(
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
filters: params,
|
filters: params,
|
||||||
@@ -84,7 +99,7 @@ class _PaginatedParameterState
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> editParameter(InvenTreePartParameter parameter) async {
|
Future<void> editParameter(InvenTreeParameter parameter) async {
|
||||||
// Checkbox values are handled separately
|
// Checkbox values are handled separately
|
||||||
if (parameter.is_checkbox) {
|
if (parameter.is_checkbox) {
|
||||||
return;
|
return;
|
||||||
@@ -101,7 +116,7 @@ class _PaginatedParameterState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildItem(BuildContext context, InvenTreeModel model) {
|
Widget buildItem(BuildContext context, InvenTreeModel model) {
|
||||||
InvenTreePartParameter parameter = model as InvenTreePartParameter;
|
InvenTreeParameter parameter = model as InvenTreeParameter;
|
||||||
|
|
||||||
String title = parameter.name;
|
String title = parameter.name;
|
||||||
|
|
||||||
@@ -116,7 +131,7 @@ class _PaginatedParameterState
|
|||||||
? Switch(
|
? Switch(
|
||||||
value: parameter.as_bool,
|
value: parameter.as_bool,
|
||||||
onChanged: (bool value) {
|
onChanged: (bool value) {
|
||||||
if (parameter.canEdit) {
|
if (widget.editable) {
|
||||||
showLoadingOverlay();
|
showLoadingOverlay();
|
||||||
parameter.update(values: {"data": value.toString()}).then((
|
parameter.update(values: {"data": value.toString()}).then((
|
||||||
value,
|
value,
|
||||||
@@ -131,10 +146,47 @@ class _PaginatedParameterState
|
|||||||
onTap: parameter.is_checkbox
|
onTap: parameter.is_checkbox
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
if (parameter.canEdit) {
|
if (widget.editable) {
|
||||||
editParameter(parameter);
|
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/app_colors.dart";
|
||||||
import "package:inventree/barcode/barcode.dart";
|
import "package:inventree/barcode/barcode.dart";
|
||||||
import "package:inventree/inventree/attachment.dart";
|
import "package:inventree/inventree/attachment.dart";
|
||||||
|
import "package:inventree/inventree/parameter.dart";
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
import "package:inventree/helpers.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/attachment_widget.dart";
|
||||||
import "package:inventree/widget/link_icon.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/bom_list.dart";
|
||||||
import "package:inventree/widget/part/part_list.dart";
|
import "package:inventree/widget/part/part_list.dart";
|
||||||
import "package:inventree/widget/notes_widget.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/part/part_pricing.dart";
|
||||||
import "package:inventree/widget/progress.dart";
|
import "package:inventree/widget/progress.dart";
|
||||||
import "package:inventree/widget/part/category_display.dart";
|
import "package:inventree/widget/part/category_display.dart";
|
||||||
@@ -50,13 +51,11 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
|
|
||||||
InvenTreeStockLocation? defaultLocation;
|
InvenTreeStockLocation? defaultLocation;
|
||||||
|
|
||||||
int parameterCount = 0;
|
|
||||||
|
|
||||||
bool allowLabelPrinting = false;
|
bool allowLabelPrinting = false;
|
||||||
bool showParameters = false;
|
|
||||||
bool showBom = false;
|
bool showBom = false;
|
||||||
bool showPricing = false;
|
bool showPricing = false;
|
||||||
|
|
||||||
|
int parameterCount = 0;
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
int bomCount = 0;
|
int bomCount = 0;
|
||||||
int usedInCount = 0;
|
int usedInCount = 0;
|
||||||
@@ -153,10 +152,6 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
INV_PART_SHOW_PRICING,
|
INV_PART_SHOW_PRICING,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
showParameters = await InvenTreeSettingsManager().getBool(
|
|
||||||
INV_PART_SHOW_PARAMETERS,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
showBom = await InvenTreeSettingsManager().getBool(INV_PART_SHOW_BOM, true);
|
showBom = await InvenTreeSettingsManager().getBool(INV_PART_SHOW_BOM, true);
|
||||||
allowLabelPrinting = await InvenTreeSettingsManager().getBool(
|
allowLabelPrinting = await InvenTreeSettingsManager().getBool(
|
||||||
INV_ENABLE_LABEL_PRINTING,
|
INV_ENABLE_LABEL_PRINTING,
|
||||||
@@ -213,15 +208,30 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request the number of attachments
|
// Request the number of attachments
|
||||||
InvenTreeAttachment()
|
if (api.supportsModernAttachments) {
|
||||||
.countAttachments(InvenTreePart.MODEL_TYPE, part.pk)
|
InvenTreeAttachment()
|
||||||
.then((int value) {
|
.countAttachments(InvenTreePart.MODEL_TYPE, part.pk)
|
||||||
if (mounted) {
|
.then((int value) {
|
||||||
setState(() {
|
if (mounted) {
|
||||||
attachmentCount = value;
|
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 show pricing information?
|
||||||
if (showPricing) {
|
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(
|
ListTile? attachmentTile = ShowAttachmentsItem(
|
||||||
context,
|
context,
|
||||||
InvenTreePart.MODEL_TYPE,
|
InvenTreePart.MODEL_TYPE,
|
||||||
@@ -705,10 +727,6 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
List<Widget> getTabIcons(BuildContext context) {
|
List<Widget> getTabIcons(BuildContext context) {
|
||||||
List<Widget> icons = [Tab(text: L10().details), Tab(text: L10().stock)];
|
List<Widget> icons = [Tab(text: L10().details), Tab(text: L10().stock)];
|
||||||
|
|
||||||
if (showParameters) {
|
|
||||||
icons.add(Tab(text: L10().parameters));
|
|
||||||
}
|
|
||||||
|
|
||||||
return icons;
|
return icons;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,11 +739,6 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
),
|
),
|
||||||
PaginatedStockItemList({"part": part.pk.toString()}),
|
PaginatedStockItemList({"part": part.pk.toString()}),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (showParameters) {
|
|
||||||
tabs.add(PaginatedParameterList({"part": part.pk.toString()}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tabs;
|
return tabs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user