mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'inventree:master' into webhooks
This commit is contained in:
commit
f6d43946b3
@ -215,7 +215,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.treeview .list-group-item {
|
.treeview .list-group-item {
|
||||||
padding: 10px 5px;
|
padding: 3px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.treeview .list-group-item .indent {
|
.treeview .list-group-item .indent {
|
||||||
@ -539,7 +539,7 @@
|
|||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrump {
|
.breadcrumb {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
@ -1150,7 +1150,7 @@ class BuildItem(models.Model):
|
|||||||
|
|
||||||
bom_item_valid = False
|
bom_item_valid = False
|
||||||
|
|
||||||
if self.bom_item:
|
if self.bom_item and self.build:
|
||||||
"""
|
"""
|
||||||
A BomItem object has already been assigned. This is valid if:
|
A BomItem object has already been assigned. This is valid if:
|
||||||
|
|
||||||
@ -1162,8 +1162,11 @@ class BuildItem(models.Model):
|
|||||||
iii) The Part referenced by the StockItem is a valid substitute for the BomItem
|
iii) The Part referenced by the StockItem is a valid substitute for the BomItem
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.build and self.build.part == self.bom_item.part:
|
if self.build.part == self.bom_item.part:
|
||||||
|
bom_item_valid = self.bom_item.is_stock_item_valid(self.stock_item)
|
||||||
|
|
||||||
|
elif self.bom_item.inherited:
|
||||||
|
if self.build.part in self.bom_item.part.get_descendants(include_self=False):
|
||||||
bom_item_valid = self.bom_item.is_stock_item_valid(self.stock_item)
|
bom_item_valid = self.bom_item.is_stock_item_valid(self.stock_item)
|
||||||
|
|
||||||
# If the existing BomItem is *not* valid, try to find a match
|
# If the existing BomItem is *not* valid, try to find a match
|
||||||
|
@ -309,13 +309,19 @@ class BuildAllocationItemSerializer(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def validate_bom_item(self, bom_item):
|
def validate_bom_item(self, bom_item):
|
||||||
|
"""
|
||||||
# TODO: Fix this validation - allow for variants and substitutes!
|
Check if the parts match!
|
||||||
|
"""
|
||||||
|
|
||||||
build = self.context['build']
|
build = self.context['build']
|
||||||
|
|
||||||
# BomItem must point to the same 'part' as the parent build
|
# BomItem should point to the same 'part' as the parent build
|
||||||
if build.part != bom_item.part:
|
if build.part != bom_item.part:
|
||||||
|
|
||||||
|
# If not, it may be marked as "inherited" from a parent part
|
||||||
|
if bom_item.inherited and build.part in bom_item.part.get_descendants(include_self=False):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
raise ValidationError(_("bom_item.part must point to the same part as the build order"))
|
raise ValidationError(_("bom_item.part must point to the same part as the build order"))
|
||||||
|
|
||||||
return bom_item
|
return bom_item
|
||||||
|
@ -77,6 +77,11 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
<td>{% trans "Part" %}</td>
|
<td>{% trans "Part" %}</td>
|
||||||
<td><a href="{% url 'part-detail' build.part.id %}?display=build-orders">{{ build.part.full_name }}</a></td>
|
<td><a href="{% url 'part-detail' build.part.id %}?display=build-orders">{{ build.part.full_name }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td>{% trans "Quantity" %}</td>
|
||||||
|
<td>{{ build.quantity }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-info-circle'></span></td>
|
<td><span class='fas fa-info-circle'></span></td>
|
||||||
<td>{% trans "Build Description" %}</td>
|
<td>{% trans "Build Description" %}</td>
|
||||||
@ -127,11 +132,6 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
{% block details_right %}
|
{% block details_right %}
|
||||||
<table class='table table-striped table-condensed'>
|
<table class='table table-striped table-condensed'>
|
||||||
<col width='25'>
|
<col width='25'>
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td>{% trans "Quantity" %}</td>
|
|
||||||
<td>{{ build.quantity }}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-info'></span></td>
|
<td><span class='fas fa-info'></span></td>
|
||||||
<td>{% trans "Status" %}</td>
|
<td>{% trans "Status" %}</td>
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -239,6 +239,23 @@ class CategoryParameterList(generics.ListAPIView):
|
|||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryTree(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
API endpoint for accessing a list of PartCategory objects ready for rendering a tree.
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = PartCategory.objects.all()
|
||||||
|
serializer_class = part_serializers.CategoryTree
|
||||||
|
|
||||||
|
filter_backends = [
|
||||||
|
DjangoFilterBackend,
|
||||||
|
filters.OrderingFilter,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Order by tree level (top levels first) and then name
|
||||||
|
ordering = ['level', 'name']
|
||||||
|
|
||||||
|
|
||||||
class PartSalePriceList(generics.ListCreateAPIView):
|
class PartSalePriceList(generics.ListCreateAPIView):
|
||||||
"""
|
"""
|
||||||
API endpoint for list view of PartSalePriceBreak model
|
API endpoint for list view of PartSalePriceBreak model
|
||||||
@ -1515,6 +1532,7 @@ part_api_urls = [
|
|||||||
|
|
||||||
# Base URL for PartCategory API endpoints
|
# Base URL for PartCategory API endpoints
|
||||||
url(r'^category/', include([
|
url(r'^category/', include([
|
||||||
|
url(r'^tree/', CategoryTree.as_view(), name='api-part-category-tree'),
|
||||||
url(r'^parameters/', CategoryParameterList.as_view(), name='api-part-category-parameter-list'),
|
url(r'^parameters/', CategoryParameterList.as_view(), name='api-part-category-parameter-list'),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'),
|
url(r'^(?P<pk>\d+)/?', CategoryDetail.as_view(), name='api-part-category-detail'),
|
||||||
|
@ -70,6 +70,20 @@ class CategorySerializer(InvenTreeModelSerializer):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryTree(InvenTreeModelSerializer):
|
||||||
|
"""
|
||||||
|
Serializer for PartCategory tree
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = PartCategory
|
||||||
|
fields = [
|
||||||
|
'pk',
|
||||||
|
'name',
|
||||||
|
'parent',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PartAttachmentSerializer(InvenTreeAttachmentSerializer):
|
class PartAttachmentSerializer(InvenTreeAttachmentSerializer):
|
||||||
"""
|
"""
|
||||||
Serializer for the PartAttachment class
|
Serializer for the PartAttachment class
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
{% include 'part/category_sidebar.html' %}
|
{% include 'part/category_sidebar.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumb_tree %}
|
||||||
|
<div id="breadcrumb-tree"></div>
|
||||||
|
{% endblock breadcrumb_tree %}
|
||||||
|
|
||||||
{% block heading %}
|
{% block heading %}
|
||||||
{% if category %}
|
{% if category %}
|
||||||
{% trans "Part Category" %}: {{ category.name }}
|
{% trans "Part Category" %}: {{ category.name }}
|
||||||
@ -239,8 +243,24 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
// Enable left-hand navigation sidebar
|
||||||
enableSidebar('category');
|
enableSidebar('category');
|
||||||
|
|
||||||
|
// Enable breadcrumb tree view
|
||||||
|
enableBreadcrumbTree({
|
||||||
|
label: 'category',
|
||||||
|
url: '{% url "api-part-category-tree" %}',
|
||||||
|
{% if category %}
|
||||||
|
selected: {{ category.pk }},
|
||||||
|
{% endif %}
|
||||||
|
processNode: function(node) {
|
||||||
|
node.text = node.name;
|
||||||
|
node.href = `/part/category/${node.pk}/`;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
loadPartCategoryTable(
|
loadPartCategoryTable(
|
||||||
$('#subcategory-table'), {
|
$('#subcategory-table'), {
|
||||||
params: {
|
params: {
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
{% include 'part/part_sidebar.html' %}
|
{% include 'part/part_sidebar.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumb_tree %}
|
||||||
|
<div id="breadcrumb-tree"></div>
|
||||||
|
{% endblock breadcrumb_tree %}
|
||||||
|
|
||||||
{% block page_content %}
|
{% block page_content %}
|
||||||
|
|
||||||
<div class='panel panel-hidden' id='panel-part-stock'>
|
<div class='panel panel-hidden' id='panel-part-stock'>
|
||||||
@ -132,10 +136,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='panel panel-hidden' id='panel-pricing'>
|
|
||||||
<!-- TODO -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class='panel panel-hidden' id='panel-variants'>
|
<div class='panel panel-hidden' id='panel-variants'>
|
||||||
<div class='panel-heading'>
|
<div class='panel-heading'>
|
||||||
<div class='d-flex flex-wrap'>
|
<div class='d-flex flex-wrap'>
|
||||||
@ -1066,4 +1066,18 @@
|
|||||||
|
|
||||||
enableSidebar('part');
|
enableSidebar('part');
|
||||||
|
|
||||||
|
enableBreadcrumbTree({
|
||||||
|
label: 'part',
|
||||||
|
url: '{% url "api-part-category-tree" %}',
|
||||||
|
{% if part.category %}
|
||||||
|
selected: {{ part.category.pk }},
|
||||||
|
{% endif %}
|
||||||
|
processNode: function(node) {
|
||||||
|
node.text = node.name;
|
||||||
|
node.href = `/part/category/${node.pk}/`;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -14,9 +14,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
|
<a href='#' id='breadcrumb-tree-toggle' class="breadcrumb-item"><i class="fas fa-bars"></i></a>
|
||||||
{% if part %}
|
{% if part %}
|
||||||
{% include "part/cat_link.html" with category=part.category part=part %}
|
{% include "part/cat_link.html" with category=part.category part=part %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% include 'part/cat_link.html' with category=category %}
|
{% include 'part/cat_link.html' with category=category %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock breadcrumbs %}
|
||||||
|
@ -277,6 +277,24 @@ class StockLocationList(generics.ListCreateAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class StockLocationTree(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
API endpoint for accessing a list of StockLocation objects,
|
||||||
|
ready for rendering as a tree
|
||||||
|
"""
|
||||||
|
|
||||||
|
queryset = StockLocation.objects.all()
|
||||||
|
serializer_class = StockSerializers.LocationTreeSerializer
|
||||||
|
|
||||||
|
filter_backends = [
|
||||||
|
DjangoFilterBackend,
|
||||||
|
filters.OrderingFilter,
|
||||||
|
]
|
||||||
|
|
||||||
|
# Order by tree level (top levels first) and then name
|
||||||
|
ordering = ['level', 'name']
|
||||||
|
|
||||||
|
|
||||||
class StockFilter(rest_filters.FilterSet):
|
class StockFilter(rest_filters.FilterSet):
|
||||||
"""
|
"""
|
||||||
FilterSet for StockItem LIST API
|
FilterSet for StockItem LIST API
|
||||||
@ -1182,6 +1200,9 @@ class LocationDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
stock_api_urls = [
|
stock_api_urls = [
|
||||||
url(r'^location/', include([
|
url(r'^location/', include([
|
||||||
|
|
||||||
|
url(r'^tree/', StockLocationTree.as_view(), name='api-location-tree'),
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/', LocationDetail.as_view(), name='api-location-detail'),
|
url(r'^(?P<pk>\d+)/', LocationDetail.as_view(), name='api-location-detail'),
|
||||||
url(r'^.*$', StockLocationList.as_view(), name='api-location-list'),
|
url(r'^.*$', StockLocationList.as_view(), name='api-location-list'),
|
||||||
])),
|
])),
|
||||||
|
@ -390,6 +390,20 @@ class SerializeStockItemSerializer(serializers.Serializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LocationTreeSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
||||||
|
"""
|
||||||
|
Serializer for a simple tree view
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = StockLocation
|
||||||
|
fields = [
|
||||||
|
'pk',
|
||||||
|
'name',
|
||||||
|
'parent',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class LocationSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
class LocationSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
||||||
""" Detailed information about a stock location
|
""" Detailed information about a stock location
|
||||||
"""
|
"""
|
||||||
|
@ -9,9 +9,15 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
|
<a href='#' id='breadcrumb-tree-toggle' class="breadcrumb-item"><i class="fas fa-bars"></i></a>
|
||||||
{% include 'stock/loc_link.html' with location=item.location %}
|
{% include 'stock/loc_link.html' with location=item.location %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumb_tree %}
|
||||||
|
<div id="breadcrumb-tree"></div>
|
||||||
|
{% endblock breadcrumb_tree %}
|
||||||
|
|
||||||
|
|
||||||
{% block heading %}
|
{% block heading %}
|
||||||
{% trans "Stock Item" %}: {{ item.part.full_name}}
|
{% trans "Stock Item" %}: {{ item.part.full_name}}
|
||||||
{% endblock heading %}
|
{% endblock heading %}
|
||||||
@ -611,4 +617,18 @@ $('#serial-number-search').click(function() {
|
|||||||
findStockItemBySerialNumber({{ item.part.pk }});
|
findStockItemBySerialNumber({{ item.part.pk }});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
enableBreadcrumbTree({
|
||||||
|
label: 'stockitem',
|
||||||
|
url: '{% url "api-location-tree" %}',
|
||||||
|
{% if item.location %}
|
||||||
|
selected: {{ item.location.pk }},
|
||||||
|
{% endif %}
|
||||||
|
processNode: function(node) {
|
||||||
|
node.text = node.name;
|
||||||
|
node.href = `/stock/item/${node.pk}/`;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
{% include "stock/location_sidebar.html" %}
|
{% include "stock/location_sidebar.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumb_tree %}
|
||||||
|
<div id="breadcrumb-tree"></div>
|
||||||
|
{% endblock breadcrumb_tree %}
|
||||||
|
|
||||||
{% block heading %}
|
{% block heading %}
|
||||||
{% if location %}
|
{% if location %}
|
||||||
{% trans "Stock Location" %}: {{ location.name }}
|
{% trans "Stock Location" %}: {{ location.name }}
|
||||||
@ -348,4 +352,19 @@
|
|||||||
|
|
||||||
enableSidebar('stocklocation');
|
enableSidebar('stocklocation');
|
||||||
|
|
||||||
|
// Enable breadcrumb tree view
|
||||||
|
enableBreadcrumbTree({
|
||||||
|
label: 'location',
|
||||||
|
url: '{% url "api-location-tree" %}',
|
||||||
|
{% if location %}
|
||||||
|
selected: {{ location.pk }},
|
||||||
|
{% endif %}
|
||||||
|
processNode: function(node) {
|
||||||
|
node.text = node.name;
|
||||||
|
node.href = `/stock/location/${node.pk}/`;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
|
<a href='#' id='breadcrumb-tree-toggle' class="breadcrumb-item"><i class="fas fa-bars"></i></a>
|
||||||
{% if item %}
|
{% if item %}
|
||||||
{% include 'stock/loc_link.html' with location=item.location %}
|
{% include 'stock/loc_link.html' with location=item.location %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% include 'stock/loc_link.html' with location=location %}
|
{% include 'stock/loc_link.html' with location=location %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock breadcrumbs %}
|
||||||
|
@ -74,13 +74,13 @@
|
|||||||
|
|
||||||
<div class='row flex-nowrap inventree-body'>
|
<div class='row flex-nowrap inventree-body'>
|
||||||
<div class='col-auto px-1 sidebar-wrapper'>
|
<div class='col-auto px-1 sidebar-wrapper'>
|
||||||
<div id='sidebar' class='collapse collapse-horizontal show border-end' style='display: none;'>
|
<div id='sidebar' class='collapse collapse-horizontal show' style='display: none;'>
|
||||||
<div id='sidebar-nav' class='list-group text-sm-start'>
|
<div id='sidebar-nav' class='list-group text-sm-start'>
|
||||||
<ul id='sidebar-list-group' class='list-group sidebar-list-group'>
|
<ul id='sidebar-list-group' class='list-group sidebar-list-group'>
|
||||||
{% block sidebar %}
|
{% block sidebar %}
|
||||||
<!-- Sidebar goes here -->
|
<!-- Sidebar goes here -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% include "sidebar_toggle.html" %}
|
{% include "sidebar_toggle.html" with target='sidebar' %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -104,14 +104,20 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block breadcrumb_list %}
|
{% block breadcrumb_list %}
|
||||||
<div class='container-fluid navigation'>
|
<div class='container-fluid navigation' id='breadcrumb-div'>
|
||||||
<nav aria-label='breadcrumb'>
|
<nav aria-label='breadcrumb'>
|
||||||
<ol class='breadcrumb'>
|
<ol class='breadcrumb' id='breadcrumb-list'>
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<div id='breadcrumb-tree-collapse' class='collapse collapse-horizontal show border' style='display: none;'>
|
||||||
|
{% block breadcrumb_tree %}
|
||||||
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
addSidebarHeader,
|
addSidebarHeader,
|
||||||
addSidebarItem,
|
addSidebarItem,
|
||||||
addSidebarLink,
|
addSidebarLink,
|
||||||
|
enableBreadcrumbTree,
|
||||||
enableSidebar,
|
enableSidebar,
|
||||||
onPanelLoad,
|
onPanelLoad,
|
||||||
*/
|
*/
|
||||||
@ -145,6 +146,101 @@ function enableSidebar(label, options={}) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable support for breadcrumb tree navigation on this page
|
||||||
|
*/
|
||||||
|
function enableBreadcrumbTree(options) {
|
||||||
|
|
||||||
|
var label = options.label;
|
||||||
|
|
||||||
|
if (!label) {
|
||||||
|
console.log('ERROR: enableBreadcrumbTree called without supplying label');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filters = options.filters || {};
|
||||||
|
|
||||||
|
inventreeGet(
|
||||||
|
options.url,
|
||||||
|
filters,
|
||||||
|
{
|
||||||
|
success: function(data) {
|
||||||
|
|
||||||
|
// Data are returned from the InvenTree server as a flattened list;
|
||||||
|
// We need to convert this into a tree structure
|
||||||
|
|
||||||
|
var nodes = {};
|
||||||
|
var roots = [];
|
||||||
|
var node = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
node = data[i];
|
||||||
|
node.nodes = [];
|
||||||
|
nodes[node.pk] = node;
|
||||||
|
node.selectable = false;
|
||||||
|
|
||||||
|
if (options.processNode) {
|
||||||
|
node = options.processNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.state = {
|
||||||
|
expanded: node.pk == options.selected,
|
||||||
|
selected: node.pk == options.selected,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
node = data[i];
|
||||||
|
|
||||||
|
if (node.parent != null) {
|
||||||
|
nodes[node.parent].nodes.push(node);
|
||||||
|
|
||||||
|
if (node.state.expanded) {
|
||||||
|
nodes[node.parent].state.expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
roots.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#breadcrumb-tree').treeview({
|
||||||
|
data: roots,
|
||||||
|
showTags: true,
|
||||||
|
enableLinks: true,
|
||||||
|
expandIcon: 'fas fa-chevron-right',
|
||||||
|
collapseIcon: 'fa fa-chevron-down',
|
||||||
|
});
|
||||||
|
|
||||||
|
setBreadcrumbTreeState(label, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$('#breadcrumb-tree-toggle').click(function() {
|
||||||
|
// Add callback to "collapse" and "expand" the sidebar
|
||||||
|
|
||||||
|
// By default, the menu is "expanded"
|
||||||
|
var state = localStorage.getItem(`inventree-tree-state-${label}`) || 'expanded';
|
||||||
|
|
||||||
|
// We wish to "toggle" the state!
|
||||||
|
setBreadcrumbTreeState(label, state == 'expanded' ? 'collapsed' : 'expanded');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the initial state (default = expanded)
|
||||||
|
var state = localStorage.getItem(`inventree-tree-state-${label}`) || 'expanded';
|
||||||
|
|
||||||
|
function setBreadcrumbTreeState(label, state) {
|
||||||
|
|
||||||
|
if (state == 'collapsed') {
|
||||||
|
$('#breadcrumb-tree-collapse').hide(100);
|
||||||
|
} else {
|
||||||
|
$('#breadcrumb-tree-collapse').show(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem(`inventree-tree-state-${label}`, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the "toggle" state of the sidebar
|
* Set the "toggle" state of the sidebar
|
||||||
@ -180,7 +276,7 @@ function setSidebarState(label, state) {
|
|||||||
function addSidebarItem(options={}) {
|
function addSidebarItem(options={}) {
|
||||||
|
|
||||||
var html = `
|
var html = `
|
||||||
<a href='#' id='select-${options.label}' title='${options.text}' class='list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-selector' data-bs-parent='#sidebar'>
|
<a href='#' id='select-${options.label}' title='${options.text}' class='list-group-item sidebar-list-group-item border-end d-inline-block text-truncate sidebar-selector' data-bs-parent='#sidebar'>
|
||||||
<i class='bi bi-bootstrap'></i>
|
<i class='bi bi-bootstrap'></i>
|
||||||
${options.content_before || ''}
|
${options.content_before || ''}
|
||||||
<span class='sidebar-item-icon fas ${options.icon}'></span>
|
<span class='sidebar-item-icon fas ${options.icon}'></span>
|
||||||
@ -199,7 +295,7 @@ function addSidebarItem(options={}) {
|
|||||||
function addSidebarHeader(options={}) {
|
function addSidebarHeader(options={}) {
|
||||||
|
|
||||||
var html = `
|
var html = `
|
||||||
<span title='${options.text}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate" data-bs-parent="#sidebar">
|
<span title='${options.text}' class="list-group-item sidebar-list-group-item border-end d-inline-block text-truncate" data-bs-parent="#sidebar">
|
||||||
<h6>
|
<h6>
|
||||||
<i class="bi bi-bootstrap"></i>
|
<i class="bi bi-bootstrap"></i>
|
||||||
<span class='sidebar-item-text' style='display: none;'>${options.text}</span>
|
<span class='sidebar-item-text' style='display: none;'>${options.text}</span>
|
||||||
|
@ -1658,7 +1658,7 @@ function allocateStockToSalesOrder(order_id, line_items, options={}) {
|
|||||||
var available = Math.max((data.quantity || 0) - (data.allocated || 0), 0);
|
var available = Math.max((data.quantity || 0) - (data.allocated || 0), 0);
|
||||||
|
|
||||||
// Remaining quantity to be allocated?
|
// Remaining quantity to be allocated?
|
||||||
var remaining = opts.quantity || available;
|
var remaining = Math.max(line_item.quantity - line_item.shipped - line_item.allocated, 0);
|
||||||
|
|
||||||
// Maximum amount that we need
|
// Maximum amount that we need
|
||||||
var desired = Math.min(available, remaining);
|
var desired = Math.min(available, remaining);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<span title='{{ text }}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate bg-light" data-bs-parent="#sidebar">
|
<span title='{{ text }}' class="list-group-item sidebar-list-group-item border-end d-inline-block text-truncate bg-light" data-bs-parent="#sidebar">
|
||||||
<h6>
|
<h6>
|
||||||
<i class="bi bi-bootstrap"></i>
|
<i class="bi bi-bootstrap"></i>
|
||||||
{% if icon %}<span class='sidebar-item-icon fas {{ icon }}'></span>{% endif %}
|
{% if icon %}<span class='sidebar-item-icon fas {{ icon }}'></span>{% endif %}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<a href="#" id='select-{{ label }}' title='{{ text }}' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-selector" data-bs-parent="#sidebar">
|
<a href="#" id='select-{{ label }}' title='{{ text }}' class="list-group-item sidebar-list-group-item border-end d-inline-block text-truncate sidebar-selector" data-bs-parent="#sidebar">
|
||||||
<i class="bi bi-bootstrap"></i>
|
<i class="bi bi-bootstrap"></i>
|
||||||
<span class='sidebar-item-icon fas {{ icon|default:"fa-circle" }}'></span>
|
<span class='sidebar-item-icon fas {{ icon|default:"fa-circle" }}'></span>
|
||||||
<span class='sidebar-item-text' style='display: none;'>{{ text }}</span>
|
<span class='sidebar-item-text' style='display: none;'>{{ text }}</span>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<a href="{{ url }}" class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate" data-bs-parent="#sidebar">
|
<a href="{{ url }}" class="list-group-item sidebar-list-group-item border-end d-inline-block text-truncate" data-bs-parent="#sidebar">
|
||||||
<i class="bi bi-bootstrap"></i><span class='sidebar-item-icon fas {{ icon }}'></span><span class='sidebar-item-text' style='display: none;'>{{ text }}</span>
|
<i class="bi bi-bootstrap"></i><span class='sidebar-item-icon fas {{ icon }}'></span><span class='sidebar-item-text' style='display: none;'>{{ text }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
<a href="#" id='sidebar-toggle' class="list-group-item sidebar-list-group-item border-end-0 d-inline-block text-truncate sidebar-toggle" data-bs-parent="#sidebar" style='display: none;'>
|
<a href="#" id='{{ target }}-toggle' class="list-group-item sidebar-list-group-item border-end d-inline-block text-truncate sidebar-toggle" data-bs-parent="#sidebar" style='display: none;'>
|
||||||
<i class="bi bi-bootstrap"></i><span id='sidebar-toggle-icon' class='sidebar-item-icon fas fa-chevron-left'></span>
|
<i class="bi bi-bootstrap"></i><span id='sidebar-toggle-icon' class='sidebar-item-icon fas fa-chevron-left'></span>
|
||||||
|
{% if text %}<span class='sidebar-item-text' style='display: none;'>{{ text }}</span>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
|
Loading…
Reference in New Issue
Block a user