diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py
index 6da3962224..2667352515 100644
--- a/InvenTree/stock/api.py
+++ b/InvenTree/stock/api.py
@@ -320,6 +320,11 @@ class StockLocationList(generics.ListCreateAPIView):
'description',
]
+ ordering_fields = [
+ 'name',
+ 'items',
+ ]
+
class StockList(generics.ListCreateAPIView):
""" API endpoint for list view of Stock objects
diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py
index 5b00c1dd17..2439bb9330 100644
--- a/InvenTree/stock/serializers.py
+++ b/InvenTree/stock/serializers.py
@@ -244,6 +244,7 @@ class LocationSerializer(InvenTreeModelSerializer):
items = serializers.IntegerField(source='item_count', read_only=True)
+
class Meta:
model = StockLocation
fields = [
diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html
index 74e43f88bb..396a433566 100644
--- a/InvenTree/stock/templates/stock/location.html
+++ b/InvenTree/stock/templates/stock/location.html
@@ -2,8 +2,15 @@
{% load static %}
{% load inventree_extras %}
{% load i18n %}
+
+{% block menubar %}
+{% include "stock/location_navbar.html" with tab="stock" %}
+{% endblock %}
+
{% block content %}
+
+
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners location.owner as owners %}
@@ -120,36 +127,29 @@
+
-{% if location and location.children.all|length > 0 %}
-{% include 'stock/location_list.html' with children=location.children.all collapse_id="locations" %}
-{% elif locations|length > 0 %}
-{% include 'stock/location_list.html' with children=locations collapse_id="locations" %}
-{% endif %}
+{% block location_content %}
-
-
-{% include "stock_table.html" %}
+
+
+
{% trans "Stock Items" %}
+
+ {% include "stock_table.html" %}
{% endblock %}
-{% block js_load %}
-{{ block.super }}
+
+
{% endblock %}
+
{% block js_ready %}
{{ block.super }}
- if (inventreeLoadInt("show-part-locs") == 1) {
- $("#collapse-item-locations").collapse('show');
- }
-
- $("#collapse-item-locations").on('shown.bs.collapse', function() {
- inventreeSave('show-part-locs', 1);
- });
-
- $("#collapse-item-locations").on('hidden.bs.collapse', function() {
- inventreeDel('show-part-locs');
+ enableNavbar({
+ label: 'location',
+ toggleId: '#location-menu-toggle'
});
{% if location %}
@@ -261,7 +261,7 @@
],
params: {
{% if location %}
- location: {{ location.id }},
+ location: {{ location.pk }},
{% endif %}
part_detail: true,
location_detail: true,
diff --git a/InvenTree/stock/templates/stock/location_list.html b/InvenTree/stock/templates/stock/location_list.html
deleted file mode 100644
index f9464c5fa3..0000000000
--- a/InvenTree/stock/templates/stock/location_list.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% extends "collapse.html" %}
-{% load i18n %}
-
-{% if roles.stock_location.view or roles.stock.view %}
-{% block collapse_title %}
-{% trans 'Sub-Locations' %}{{ children|length }}
-{% endblock %}
-
-{% block collapse_content %}
-
-{% for child in children %}
-- {{ child.name }} - {{ child.description }}
- {% if child.item_count > 0 %}
-
-
- {% comment %}Translators: pluralize with counter{% endcomment %}
- {% blocktrans count counter=child.item_count %}{{ counter }} Item{% plural %}{{ counter }} Items{% endblocktrans %}
-
- {% endif %}
-
-{% endfor %}
-
-{% endblock %}
-{% endif %}
\ No newline at end of file
diff --git a/InvenTree/stock/templates/stock/location_navbar.html b/InvenTree/stock/templates/stock/location_navbar.html
new file mode 100644
index 0000000000..0cb0c9d1eb
--- /dev/null
+++ b/InvenTree/stock/templates/stock/location_navbar.html
@@ -0,0 +1,33 @@
+{% load i18n %}
+
+
\ No newline at end of file
diff --git a/InvenTree/stock/templates/stock/sublocation.html b/InvenTree/stock/templates/stock/sublocation.html
new file mode 100644
index 0000000000..b8b32328a2
--- /dev/null
+++ b/InvenTree/stock/templates/stock/sublocation.html
@@ -0,0 +1,36 @@
+{% extends "stock/location.html" %}
+
+{% load static %}
+{% load i18n %}
+{% load inventree_extras %}
+
+{% block menubar %}
+{% include "stock/location_navbar.html" with tab="sublocations" %}
+{% endblock %}
+
+
+{% block location_content %}
+
+
+
+
{% trans "Sublocations" %}
+
+
+
+
+{% endblock %}
+
+{% block js_ready %}
+{{ block.super }}
+
+loadStockLocationTable($('#sublocation-table'), {
+ params: {
+ {% if location %}
+ parent: {{ location.pk }},
+ {% else %}
+ parent: 'null',
+ {% endif %}
+ }
+});
+
+{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py
index 5c6c678978..24e609fa4f 100644
--- a/InvenTree/stock/urls.py
+++ b/InvenTree/stock/urls.py
@@ -6,14 +6,21 @@ from django.conf.urls import url, include
from . import views
-# URL list for web interface
-stock_location_detail_urls = [
- url(r'^edit/?', views.StockLocationEdit.as_view(), name='stock-location-edit'),
- url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'),
- url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'),
+location_urls = [
+
+ url(r'^new/', views.StockLocationCreate.as_view(), name='stock-location-create'),
+
+ url(r'^(?P\d+)/', include([
+ url(r'^edit/?', views.StockLocationEdit.as_view(), name='stock-location-edit'),
+ url(r'^delete/?', views.StockLocationDelete.as_view(), name='stock-location-delete'),
+ url(r'^qr_code/?', views.StockLocationQRCode.as_view(), name='stock-location-qr'),
+
+ url(r'sublocation/', views.StockLocationDetail.as_view(template_name='stock/sublocation.html'), name='stock-location-sublocation'),
+
+ # Anything else
+ url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
+ ])),
- # Anything else
- url('^.*$', views.StockLocationDetail.as_view(), name='stock-location-detail'),
]
stock_item_detail_urls = [
@@ -49,9 +56,7 @@ stock_tracking_urls = [
stock_urls = [
# Stock location
- url(r'^location/(?P\d+)/', include(stock_location_detail_urls)),
-
- url(r'^location/new/', views.StockLocationCreate.as_view(), name='stock-location-create'),
+ url(r'^location/', include(location_urls)),
url(r'^item/new/?', views.StockItemCreate.as_view(), name='stock-item-create'),
@@ -81,5 +86,7 @@ stock_urls = [
# Individual stock items
url(r'^item/(?P\d+)/', include(stock_item_detail_urls)),
+ url(r'^sublocations/', views.StockIndex.as_view(template_name='stock/sublocation.html'), name='stock-sublocations'),
+
url(r'^.*$', views.StockIndex.as_view(), name='stock-index'),
]
diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js
index 33f2dae8d6..990acf65ba 100644
--- a/InvenTree/templates/js/stock.js
+++ b/InvenTree/templates/js/stock.js
@@ -897,6 +897,77 @@ function loadStockTable(table, options) {
});
}
+function loadStockLocationTable(table, options) {
+ /* Display a table of stock locations */
+
+ var params = options.params || {};
+
+ var filterListElement = options.filterList || '#filter-list-location';
+
+ var filters = {};
+
+ var filterKey = options.filterKey || options.name || 'location';
+
+ if (!options.disableFilters) {
+ filters = loadTableFilters(filterKey);
+ }
+
+ var original = {};
+
+ for (var key in params) {
+ original[key] = params[key];
+ }
+
+ setupFilterList(filterKey, table, filterListElement);
+
+ for (var key in params) {
+ filters[key] = params[key];
+ }
+
+ table.inventreeTable({
+ method: 'get',
+ url: options.url || '{% url "api-location-list" %}',
+ queryParams: filters,
+ sidePagination: 'server',
+ name: 'location',
+ original: original,
+ showColumns: true,
+ columns: [
+ {
+ checkbox: true,
+ title: '{% trans "Select" %}',
+ searchable: false,
+ switchable: false,
+ },
+ {
+ field: 'name',
+ title: '{% trans "Name" %}',
+ switchable: true,
+ sortable: true,
+ formatter: function(value, row) {
+ return renderLink(
+ value,
+ `/stock/location/${row.pk}/`
+ );
+ },
+ },
+ {
+ field: 'description',
+ title: '{% trans "Description" %}',
+ switchable: true,
+ sortable: false,
+ },
+ {
+ field: 'items',
+ title: '{% trans "Stock Items" %}',
+ switchable: true,
+ sortable: false,
+ sortName: 'item_count',
+ }
+ ]
+ });
+}
+
function loadStockTrackingTable(table, options) {
var cols = [