mirror of
https://github.com/inventree/InvenTree.git
synced 2026-10-24 02:30:13 +00:00
Merge branch 'bootstrap-table'
This commit is contained in:
commit
ffdcfdf51f
27 files changed
+619
-7985
No files matched your search
@@ -34,8 +34,6 @@ apipatterns = [
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
# API URL
|
||||
url(r'^api/', include(apipatterns)),
|
||||
# url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||
|
||||
url(r'^part/', include(part_urls)),
|
||||
@@ -50,6 +48,8 @@ urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
|
||||
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
|
||||
url(r'^api/', include(apipatterns)),
|
||||
]
|
||||
|
||||
# Static file access
|
||||
|
||||
@@ -81,14 +81,11 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
|
||||
$("#build-list").footable();
|
||||
|
||||
$("#edit-build").click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
"{% url 'build-edit' build.id %}",
|
||||
|
||||
@@ -29,12 +29,10 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#build-list').footable();
|
||||
|
||||
|
||||
$("#new-build").click(function() {
|
||||
launchModalForm("#modal-form",
|
||||
"{% url 'build-create' %}",
|
||||
|
||||
@@ -3,7 +3,21 @@ from rest_framework import serializers
|
||||
from .models import Company
|
||||
|
||||
|
||||
class CompanySerializer(serializers.HyperlinkedModelSerializer):
|
||||
class CompanyBriefSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Company
|
||||
fields = [
|
||||
'pk',
|
||||
'url',
|
||||
'name'
|
||||
]
|
||||
|
||||
class CompanySerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Company
|
||||
|
||||
@@ -6,29 +6,7 @@
|
||||
|
||||
<h3>Company Parts</h3>
|
||||
|
||||
<table class='table table-striped' id='part-list' data-sorting='true' data-filtering='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SKU</th>
|
||||
<th>Part</th>
|
||||
<th>MPN</th>
|
||||
<th>URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for part in company.parts.all %}
|
||||
<tr>
|
||||
<td><a href="{% url 'supplier-part-detail' part.id %}">{{ part.SKU }}</a></td>
|
||||
<td>
|
||||
{% if part.part %}
|
||||
<a href="{% url 'part-suppliers' part.part.id %}">{{ part.part.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ part.manufacturer_string }}</td>
|
||||
<td>{{ part.URL }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<table clas='table table-striped table-condensed' id='part-table'>
|
||||
</table>
|
||||
|
||||
<div class='container-fluid'>
|
||||
@@ -40,11 +18,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$("#part-list").footable();
|
||||
|
||||
$("#part-create").click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -56,4 +32,39 @@
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
|
||||
$("#part-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
supplier: {{ company.id }}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
sortable: true,
|
||||
field: 'part',
|
||||
title: 'Part',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value.name, value.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'SKU',
|
||||
title: 'SKU',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'manufacturer',
|
||||
title: 'Manufacturer',
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-part-supplier-list' %}"
|
||||
});
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,26 +6,7 @@
|
||||
|
||||
<h3>Companies</h3>
|
||||
|
||||
|
||||
<table class='table table-striped' id='company-table' data-sorting='true' data-filtering='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for company in companies %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'company-detail' company.id %}">
|
||||
{{ company.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ company.description }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<table class='table table-striped' id='company-table'>
|
||||
</table>
|
||||
|
||||
<div class='container-fluid'>
|
||||
@@ -37,11 +18,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#company-table').footable();
|
||||
|
||||
$('#new-company').click(function () {
|
||||
launchModalForm('#modal-form',
|
||||
@@ -50,4 +29,40 @@
|
||||
follow: true
|
||||
});
|
||||
});
|
||||
|
||||
$("#company-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
columns: [
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
title: 'Company',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'description',
|
||||
title: 'Description',
|
||||
},
|
||||
{
|
||||
field: 'website',
|
||||
title: 'Website',
|
||||
formatter: function(value, row, index, field) {
|
||||
if (value) {
|
||||
return renderLink(value, value);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-company-list' %}"
|
||||
});
|
||||
|
||||
{% endblock %}
|
||||
+49
-2
@@ -7,8 +7,11 @@ from rest_framework import generics, permissions
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .models import Part, PartCategory
|
||||
from .serializers import PartSerializer
|
||||
from .models import Part, PartCategory, BomItem
|
||||
from .models import SupplierPart
|
||||
|
||||
from .serializers import PartSerializer, BomItemSerializer
|
||||
from .serializers import SupplierPartSerializer
|
||||
|
||||
from InvenTree.views import TreeSerializer
|
||||
|
||||
@@ -49,9 +52,53 @@ class PartList(generics.ListCreateAPIView):
|
||||
]
|
||||
|
||||
|
||||
class BomList(generics.ListAPIView):
|
||||
|
||||
queryset = BomItem.objects.all()
|
||||
serializer_class = BomItemSerializer
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticatedOrReadOnly,
|
||||
]
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
filters.SearchFilter,
|
||||
filters.OrderingFilter,
|
||||
]
|
||||
|
||||
filter_fields = [
|
||||
'part',
|
||||
'sub_part'
|
||||
]
|
||||
|
||||
|
||||
class SupplierPartList(generics.ListAPIView):
|
||||
|
||||
queryset = SupplierPart.objects.all()
|
||||
serializer_class = SupplierPartSerializer
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticatedOrReadOnly,
|
||||
]
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
filters.SearchFilter,
|
||||
filters.OrderingFilter,
|
||||
]
|
||||
|
||||
filter_fields = [
|
||||
'part',
|
||||
'supplier'
|
||||
]
|
||||
|
||||
|
||||
part_api_urls = [
|
||||
|
||||
url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'),
|
||||
|
||||
url(r'^supplier/?', SupplierPartList.as_view(), name='api-part-supplier-list'),
|
||||
url(r'^bom/?', BomList.as_view(), name='api-bom-list'),
|
||||
url(r'^.*$', PartList.as_view(), name='api-part-list'),
|
||||
]
|
||||
@@ -1,6 +1,37 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import Part
|
||||
from .models import Part, PartCategory, BomItem
|
||||
from .models import SupplierPart
|
||||
|
||||
from company.serializers import CompanyBriefSerializer
|
||||
|
||||
class CategoryBriefSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = PartCategory
|
||||
fields = [
|
||||
'pk',
|
||||
'name',
|
||||
'description',
|
||||
'pathstring',
|
||||
'url',
|
||||
]
|
||||
|
||||
|
||||
class PartBriefSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Part
|
||||
fields = [
|
||||
'pk',
|
||||
'url',
|
||||
'name',
|
||||
'description',
|
||||
]
|
||||
|
||||
|
||||
class PartSerializer(serializers.ModelSerializer):
|
||||
@@ -8,16 +39,19 @@ class PartSerializer(serializers.ModelSerializer):
|
||||
Used when displaying all details of a single component.
|
||||
"""
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
category = CategoryBriefSerializer(many=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Part
|
||||
fields = [
|
||||
'pk',
|
||||
'url', # Link to the part detail page
|
||||
'name',
|
||||
'IPN',
|
||||
'URL', # Link to an external URL (optional)
|
||||
'description',
|
||||
'category',
|
||||
'category_path',
|
||||
'total_stock',
|
||||
'available_stock',
|
||||
'units',
|
||||
@@ -26,3 +60,41 @@ class PartSerializer(serializers.ModelSerializer):
|
||||
'trackable',
|
||||
'salable',
|
||||
]
|
||||
|
||||
|
||||
class BomItemSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
part = PartBriefSerializer(many=False, read_only=True)
|
||||
sub_part = PartBriefSerializer(many=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = BomItem
|
||||
fields = [
|
||||
'pk',
|
||||
'url',
|
||||
'part',
|
||||
'sub_part',
|
||||
'quantity'
|
||||
]
|
||||
|
||||
|
||||
class SupplierPartSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
part = PartBriefSerializer(many=False, read_only=True)
|
||||
supplier = CompanyBriefSerializer(many=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = SupplierPart
|
||||
fields = [
|
||||
'pk',
|
||||
'url',
|
||||
'part',
|
||||
'supplier',
|
||||
'SKU',
|
||||
'manufacturer',
|
||||
'MPN',
|
||||
]
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
{% block css %}
|
||||
|
||||
<link rel='stylesheet' href="{% static 'css/footable.bootstrap.css' %}">
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block details %}
|
||||
@@ -13,30 +11,7 @@
|
||||
|
||||
<h3>Bill of Materials</h3>
|
||||
|
||||
<table class="table table-striped" id='bom-table' data-filtering='true' data-sorting='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Part</th>
|
||||
<th>Description</th>
|
||||
<th data-type='number'>Quantity</th>
|
||||
<th data-sortable='false'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for bom_item in part.bom_items.all %}
|
||||
{% with sub_part=bom_item.sub_part %}
|
||||
<tr>
|
||||
<td><a href="{% url 'part-detail' sub_part.id %}">{{ sub_part.name }}</a></td>
|
||||
<td>{{ sub_part.description }}</td>
|
||||
<td>{{ bom_item.quantity }}</td>
|
||||
<td>
|
||||
<button type='button' url="{% url 'bom-item-edit' bom_item.id %}" class='btn btn-success edit-row-button'>Edit</button>
|
||||
<button type='button' url="{% url 'bom-item-delete' bom_item.id %}" class='btn btn-danger delete-row-button'>Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<table class='table table-striped table-condensed' id='bom-table'>
|
||||
</table>
|
||||
|
||||
<div class='container-fluid'>
|
||||
@@ -46,27 +21,32 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#bom-table').footable();
|
||||
|
||||
$('#bom-table').on('click', '.delete-row-button', function () {
|
||||
function reloadBom() {
|
||||
$("#bom-table").bootstrapTable('refresh');
|
||||
}
|
||||
|
||||
$('#bom-table').on('click', '.delete-button', function () {
|
||||
var button = $(this);
|
||||
|
||||
launchDeleteForm("#modal-delete",
|
||||
button.attr('url'),
|
||||
{
|
||||
reload: true
|
||||
success: reloadBom
|
||||
});
|
||||
});
|
||||
|
||||
$('#bom-table').on('click', '.edit-row-button', function () {
|
||||
$("#bom-table").on('click', '.edit-button', function () {
|
||||
var button = $(this);
|
||||
|
||||
launchModalForm("#modal-form",
|
||||
button.attr('url'));
|
||||
button.attr('url'),
|
||||
{
|
||||
success: reloadBom
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -80,4 +60,45 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#bom-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
part: {{ part.id }}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'sub_part',
|
||||
title: 'Part',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value.name, value.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'sub_part.description',
|
||||
title: 'Description',
|
||||
},
|
||||
{
|
||||
field: 'quantity',
|
||||
title: 'Quantity',
|
||||
searchable: false,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
formatter: function(value, row, index, field) {
|
||||
return editButton(row.url + 'edit') + ' ' + deleteButton(row.url + 'delete');
|
||||
}
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-bom-list' %}"
|
||||
});
|
||||
{% endblock %}
|
||||
@@ -17,8 +17,8 @@
|
||||
{% endif %}
|
||||
|
||||
{% if category.has_parts %}
|
||||
<h4>Parts</h4>
|
||||
{% include "part/category_parts.html" with parts=category.parts.all %}
|
||||
<table class='table table-striped table-condensed' id='part-table'>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<div class='container-fluid'>
|
||||
@@ -29,6 +29,7 @@
|
||||
<button class="btn btn-success" id='create-part'>New Part</button>
|
||||
<button class="btn btn-danger" id='delete-category'>Delete Category</button>
|
||||
|
||||
<button class='btn btn-primary' id='get-rows'>Do thing</button>
|
||||
</div>
|
||||
|
||||
{% include 'modals.html' %}
|
||||
@@ -36,11 +37,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>``
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#part-list').footable();
|
||||
|
||||
$("#edit-category").click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -84,4 +83,11 @@
|
||||
follow: true
|
||||
});
|
||||
});
|
||||
|
||||
{% include "part/category_parts.html" with category=category %}
|
||||
|
||||
$("#get-rows").click( function() {
|
||||
alert($("#part-table").bootstrapTable('getSelections'));
|
||||
});
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,24 +1,63 @@
|
||||
<table class="table table-striped" data-sorting='true' data-filtering='true' id="part-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Part</th>
|
||||
<th>Description</th>
|
||||
<th>Category</th>
|
||||
<th data-type='number'>Stock</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for part in parts %}
|
||||
<tr>
|
||||
<td><a href="{% url 'part-detail' part.id %}">{{ part.name }}</a></td>
|
||||
<td>{{ part.description }}</td>
|
||||
<td>
|
||||
{% if part.category %}
|
||||
<a href="{% url 'category-detail' part.category.id %}">{{ part.category_path }}</a>
|
||||
$("#part-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
sortName: 'description',
|
||||
idField: 'pk',
|
||||
method: 'get',
|
||||
pagination: true,
|
||||
rememberOrder: true,
|
||||
{% if category %}
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
category: {{ category.id }},
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><a href="{% url 'part-stock' part.id %}">{{ part.total_stock }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
columns: [
|
||||
{
|
||||
checkbox: true,
|
||||
title: 'Select',
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
title: 'Part',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'description',
|
||||
title: 'Description',
|
||||
},
|
||||
{% if category == None %}
|
||||
{
|
||||
sortable: true,
|
||||
field: 'category',
|
||||
title: 'Category',
|
||||
formatter: function(value, row, index, field) {
|
||||
if (row.category) {
|
||||
return renderLink(row.category.name, row.category.url);
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
{
|
||||
field: 'total_stock',
|
||||
title: 'Stock',
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-part-list' %}",
|
||||
});
|
||||
@@ -16,8 +16,7 @@
|
||||
{% include "part/category_subcategories.html" with children=children %}
|
||||
{% endif %}
|
||||
|
||||
<h4>Parts</h4>
|
||||
{% include "part/category_parts.html" with parts=parts %}
|
||||
<table class='table table-striped table-condensed' id='part-table'>
|
||||
|
||||
<div class='container-fluid'>
|
||||
<button type='button' class='btn btn-primary' id='create-cat'>
|
||||
@@ -29,11 +28,9 @@
|
||||
|
||||
{% block js_load %}
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#part-list').footable();
|
||||
|
||||
$("#create-cat").click(function() {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -73,6 +70,8 @@
|
||||
launchModalForm("#modal-form", "{% url 'part-create' %}");
|
||||
});
|
||||
|
||||
{% include "part/category_parts.html" %}
|
||||
|
||||
loadTree();
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,50 +6,8 @@
|
||||
|
||||
<h3>Part Stock</h3>
|
||||
|
||||
<table class="table table-striped" id='stock-table' data-sorting='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sortable='false'>Link</th>
|
||||
{% if part.trackable %}
|
||||
<th>Serial Number</th>
|
||||
{% else %}
|
||||
<th>Quantity</th>
|
||||
{% endif %}
|
||||
<th>Location</th>
|
||||
<th>Supplier part</th>
|
||||
<th>Stocktake</th>
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for stock in part.stock_entries %}
|
||||
<tr>
|
||||
<td><a href="{% url 'stock-item-detail' stock.id %}">Click</a></td>
|
||||
<td>
|
||||
{% if part.trackable %}
|
||||
{{ stock.serial }}
|
||||
{% else %}
|
||||
{{ stock.quantity }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if stock.location %}
|
||||
<a href="{% url 'stock-location-detail' stock.location.id %}">{{ stock.location.name }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if stock.supplier_part %}
|
||||
<a href="{% url 'supplier-part-detail' stock.supplier_part.id %}">
|
||||
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if stock.stocktake_date %}{{ stock.stocktake_date }}{% endif %}</td>
|
||||
<td>{{ stock.notes }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table
|
||||
<table class='table table-striped table-condensed' id='stock-table'>
|
||||
</table>
|
||||
|
||||
<div class='container-fluid'>
|
||||
<button class='btn btn-success' id='add-stock-item'>Add new Stock Item</button>
|
||||
@@ -59,11 +17,9 @@
|
||||
|
||||
{% block js_load %}
|
||||
{{ block.super }}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
$('#stock-table').footable();
|
||||
|
||||
$('#add-stock-item').click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -75,4 +31,41 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#stock-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
part: {{ part.id }},
|
||||
in_stock: true,
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
checkbox: true,
|
||||
},
|
||||
{
|
||||
field: 'location',
|
||||
title: 'Location',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field){
|
||||
return renderLink(value.pathstring, value.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'quantity',
|
||||
title: 'Stock',
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-stock-list' %}"
|
||||
});
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,30 +6,14 @@
|
||||
|
||||
<h3>Part Suppliers</h3>
|
||||
|
||||
<table class="table table-striped" id='supplier-table' data-sorting='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>SKU</th>
|
||||
<th>Supplier</th>
|
||||
<th>MPN</th>
|
||||
<th>URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for spart in part.supplier_parts.all %}
|
||||
<tr>
|
||||
<td><a href="{% url 'supplier-part-detail' spart.id %}">{{ spart.SKU }}</a></td>
|
||||
<td><a href="{% url 'company-detail' spart.supplier.id %}">{{ spart.supplier.name }}</a></td>
|
||||
<td>{{ spart.manufacturer_string }}</td>
|
||||
<td>
|
||||
{% if spart.URL %}
|
||||
<a href="{{ spart.URL }}">{{ spart.URL }}</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
{% if part.supplier_count > 0 %}
|
||||
<p><b>{{ part.name }}</b> is available from {{ part.supplier_count }} suppliers.</p>
|
||||
|
||||
<table class="table table-striped table-condensed" id='supplier-table'>
|
||||
</table>
|
||||
{% else %}
|
||||
<p><b>{{ part.name }}</b> is not available from any suppliers.</p>
|
||||
{% endif %}
|
||||
|
||||
<div class='container-fluid'>
|
||||
<button class="btn btn-success" id='supplier-create'>New Supplier Part</button>
|
||||
@@ -39,11 +23,9 @@
|
||||
|
||||
{% block js_load %}
|
||||
{{ block.super }}
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>``
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
$('#supplier-table').footable();
|
||||
|
||||
$('#supplier-create').click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -53,4 +35,39 @@
|
||||
data: {part: {{ part.id }} }
|
||||
});
|
||||
});
|
||||
|
||||
$("#supplier-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
part: {{ part.id }}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
sortable: true,
|
||||
field: 'supplier',
|
||||
title: 'Supplier',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value.name, value.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'SKU',
|
||||
title: 'SKU',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'manufacturer',
|
||||
title: 'Manufacturer',
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-part-supplier-list' %}"
|
||||
});
|
||||
|
||||
{% endblock %}
|
||||
@@ -6,19 +6,58 @@
|
||||
|
||||
<h3>Used In</h3>
|
||||
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>Part</th>
|
||||
<th>Uses</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
{% for item in part.used_in.all %}
|
||||
<tr>
|
||||
<td><a href="{% url 'part-bom' item.part.id %}">{{ item.part.name }}</a></td>
|
||||
<td>{{ item.quantity }}</td>
|
||||
<td>{{ item.part.description }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if part.used_in_count > 0 %}
|
||||
|
||||
<p>
|
||||
<b>{{ part.name }}</b> is used to make {{ part.used_in_count }} other parts.
|
||||
</p>
|
||||
|
||||
<table class="table table-striped table-condensed" id='used-table'>
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
<p>
|
||||
{{ part.name }} is not used to make any other parts.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
$("#used-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
sub_part: {{ part.id }}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'part',
|
||||
title: 'Part',
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value.name, value.url);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'part.description',
|
||||
title: 'Description',
|
||||
},
|
||||
{
|
||||
field: 'quantity',
|
||||
title: 'Uses',
|
||||
}
|
||||
|
||||
],
|
||||
url: "{% url 'api-bom-list' %}"
|
||||
})
|
||||
|
||||
{% endblock %}
|
||||
+1
@@ -0,0 +1 @@
|
||||
.fixed-table-container .bs-checkbox,.fixed-table-container .no-records-found{text-align:center}.fixed-table-body thead th .th-inner,.table td,.table th{box-sizing:border-box}.bootstrap-table .table{margin-bottom:0!important;border-bottom:1px solid #ddd;border-collapse:collapse!important;border-radius:1px}.bootstrap-table .table:not(.table-condensed),.bootstrap-table .table:not(.table-condensed)>tbody>tr>td,.bootstrap-table .table:not(.table-condensed)>tbody>tr>th,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>td,.bootstrap-table .table:not(.table-condensed)>tfoot>tr>th,.bootstrap-table .table:not(.table-condensed)>thead>tr>td{padding:8px}.bootstrap-table .table.table-no-bordered>tbody>tr>td,.bootstrap-table .table.table-no-bordered>thead>tr>th{border-right:2px solid transparent}.bootstrap-table .table.table-no-bordered>tbody>tr>td:last-child{border-right:none}.fixed-table-container{position:relative;clear:both;border:1px solid #ddd;border-radius:4px;-webkit-border-radius:4px;-moz-border-radius:4px}.fixed-table-container.table-no-bordered{border:1px solid transparent}.fixed-table-footer,.fixed-table-header{overflow:hidden}.fixed-table-footer{border-top:1px solid #ddd}.fixed-table-body{overflow-x:auto;overflow-y:auto;height:100%}.fixed-table-container table{width:100%}.fixed-table-container thead th{height:0;padding:0;margin:0;border-left:1px solid #ddd}.fixed-table-container thead th:focus{outline:transparent solid 0}.fixed-table-container thead th:first-child:not([data-not-first-th]){border-left:none;border-top-left-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px}.fixed-table-container tbody td .th-inner,.fixed-table-container thead th .th-inner{padding:8px;line-height:24px;vertical-align:top;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fixed-table-container thead th .sortable{cursor:pointer;background-position:right;background-repeat:no-repeat;padding-right:30px}.fixed-table-container thead th .both{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC')}.fixed-table-container thead th .asc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==)}.fixed-table-container thead th .desc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII=)}.fixed-table-container th.detail{width:30px}.fixed-table-container tbody td{border-left:1px solid #ddd}.fixed-table-container tbody tr:first-child td{border-top:none}.fixed-table-container tbody td:first-child{border-left:none}.fixed-table-container tbody .selected td{background-color:#f5f5f5}.fixed-table-container input[type=radio],.fixed-table-container input[type=checkbox]{margin:0 auto!important}.fixed-table-pagination .pagination-detail,.fixed-table-pagination div.pagination{margin-top:10px;margin-bottom:10px}.fixed-table-pagination div.pagination .pagination{margin:0}.fixed-table-pagination .pagination a{padding:6px 12px;line-height:1.428571429}.fixed-table-pagination .pagination-info{line-height:34px;margin-right:5px}.fixed-table-pagination .btn-group{position:relative;display:inline-block;vertical-align:middle}.fixed-table-pagination .dropup .dropdown-menu{margin-bottom:0}.fixed-table-pagination .page-list{display:inline-block}.fixed-table-toolbar .columns-left{margin-right:5px}.fixed-table-toolbar .columns-right{margin-left:5px}.fixed-table-toolbar .columns label{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429}.fixed-table-toolbar .bs-bars,.fixed-table-toolbar .columns,.fixed-table-toolbar .search{position:relative;margin-top:10px;margin-bottom:10px;line-height:34px}.fixed-table-pagination li.disabled a{pointer-events:none;cursor:default}.fixed-table-loading{display:none;position:absolute;top:42px;right:0;bottom:0;left:0;z-index:99;background-color:#fff;text-align:center}.fixed-table-body .card-view .title{font-weight:700;display:inline-block;min-width:30%;text-align:left!important}.table td,.table th{vertical-align:middle}.fixed-table-toolbar .dropdown-menu{text-align:left;max-height:300px;overflow:auto}.fixed-table-toolbar .btn-group>.btn-group{display:inline-block;margin-left:-1px!important}.fixed-table-toolbar .btn-group>.btn-group>.btn{border-radius:0}.fixed-table-toolbar .btn-group>.btn-group:first-child>.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.fixed-table-toolbar .btn-group>.btn-group:last-child>.bLine truncated
|
||||
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
|
||||
* @version 3.1.5
|
||||
* @link http://fooplugins.com
|
||||
* @copyright Steven Usher & Brad Vincent 2015
|
||||
* @license Released under the GPLv3 license.
|
||||
*/
|
||||
table.footable,
|
||||
table.footable-details {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.footable-details {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
table.footable-hide-fouc {
|
||||
display: none;
|
||||
}
|
||||
table > tbody > tr > td > span.footable-toggle {
|
||||
margin-right: 8px;
|
||||
opacity: 0.3;
|
||||
}
|
||||
table > tbody > tr > td > span.footable-toggle.last-column {
|
||||
margin-left: 8px;
|
||||
float: right;
|
||||
}
|
||||
table.table-condensed > tbody > tr > td > span.footable-toggle {
|
||||
margin-right: 5px;
|
||||
}
|
||||
table.footable-details > tbody > tr > th:nth-child(1) {
|
||||
min-width: 40px;
|
||||
width: 120px;
|
||||
}
|
||||
table.footable-details > tbody > tr > td:nth-child(2) {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
table.footable-details > thead > tr:first-child > th,
|
||||
table.footable-details > thead > tr:first-child > td,
|
||||
table.footable-details > tbody > tr:first-child > th,
|
||||
table.footable-details > tbody > tr:first-child > td,
|
||||
table.footable-details > tfoot > tr:first-child > th,
|
||||
table.footable-details > tfoot > tr:first-child > td {
|
||||
border-top-width: 0;
|
||||
}
|
||||
table.footable-details.table-bordered > thead > tr:first-child > th,
|
||||
table.footable-details.table-bordered > thead > tr:first-child > td,
|
||||
table.footable-details.table-bordered > tbody > tr:first-child > th,
|
||||
table.footable-details.table-bordered > tbody > tr:first-child > td,
|
||||
table.footable-details.table-bordered > tfoot > tr:first-child > th,
|
||||
table.footable-details.table-bordered > tfoot > tr:first-child > td {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
div.footable-loader {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
height: 300px;
|
||||
position: relative;
|
||||
}
|
||||
div.footable-loader > span.fooicon {
|
||||
display: inline-block;
|
||||
opacity: 0.3;
|
||||
font-size: 30px;
|
||||
line-height: 32px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-top: -16px;
|
||||
margin-left: -16px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-animation: fooicon-spin-r 2s infinite linear;
|
||||
animation: fooicon-spin-r 2s infinite linear;
|
||||
}
|
||||
table.footable > tbody > tr.footable-empty > td {
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
}
|
||||
table.footable > tbody > tr > td,
|
||||
table.footable > tbody > tr > th {
|
||||
display: none;
|
||||
}
|
||||
table.footable > tbody > tr.footable-empty > td,
|
||||
table.footable > tbody > tr.footable-empty > th,
|
||||
table.footable > tbody > tr.footable-detail-row > td,
|
||||
table.footable > tbody > tr.footable-detail-row > th {
|
||||
display: table-cell;
|
||||
}
|
||||
@-webkit-keyframes fooicon-spin-r {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fooicon-spin-r {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
|
||||
.fooicon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
display: inline-block;
|
||||
font-family: 'Glyphicons Halflings' !important;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.fooicon:before,
|
||||
.fooicon:after {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.fooicon-loader:before {
|
||||
content: "\e030";
|
||||
}
|
||||
.fooicon-plus:before {
|
||||
content: "\2b";
|
||||
}
|
||||
.fooicon-minus:before {
|
||||
content: "\2212";
|
||||
}
|
||||
.fooicon-search:before {
|
||||
content: "\e003";
|
||||
}
|
||||
.fooicon-remove:before {
|
||||
content: "\e014";
|
||||
}
|
||||
.fooicon-sort:before {
|
||||
content: "\e150";
|
||||
}
|
||||
.fooicon-sort-asc:before {
|
||||
content: "\e155";
|
||||
}
|
||||
.fooicon-sort-desc:before {
|
||||
content: "\e156";
|
||||
}
|
||||
.fooicon-pencil:before {
|
||||
content: "\270f";
|
||||
}
|
||||
.fooicon-trash:before {
|
||||
content: "\e020";
|
||||
}
|
||||
.fooicon-eye-close:before {
|
||||
content: "\e106";
|
||||
}
|
||||
.fooicon-flash:before {
|
||||
content: "\e162";
|
||||
}
|
||||
.fooicon-cog:before {
|
||||
content: "\e019";
|
||||
}
|
||||
.fooicon-stats:before {
|
||||
content: "\e185";
|
||||
}
|
||||
|
||||
table.footable > thead > tr.footable-filtering > th {
|
||||
border-bottom-width: 1px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-right,
|
||||
table.footable > thead > tr.footable-filtering > th,
|
||||
table.footable.footable-filtering-right > thead > tr.footable-filtering > th {
|
||||
text-align: right;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-left,
|
||||
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
|
||||
text-align: left;
|
||||
}
|
||||
.footable-filtering-external.footable-filtering-center,
|
||||
table.footable.footable-filtering-center > thead > tr.footable-filtering > th {
|
||||
text-align: center;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
|
||||
margin-top: 5px;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
||||
width: 100%;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox,
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
|
||||
margin: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox > label,
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
|
||||
display: block;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox input[type="checkbox"],
|
||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
|
||||
position: absolute;
|
||||
margin-left: -20px;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
||||
width: auto;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
table.footable > thead > tr.footable-filtering > th div.form-group+div.form-group {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
table.footable > thead > tr > td.footable-sortable,
|
||||
table.footable > thead > tr > th.footable-sortable,
|
||||
table.footable > tbody > tr > td.footable-sortable,
|
||||
table.footable > tbody > tr > th.footable-sortable,
|
||||
table.footable > tfoot > tr > td.footable-sortable,
|
||||
table.footable > tfoot > tr > th.footable-sortable {
|
||||
position: relative;
|
||||
padding-right: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
td.footable-sortable > span.fooicon,
|
||||
th.footable-sortable > span.fooicon {
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in;
|
||||
}
|
||||
td.footable-sortable:hover > span.fooicon,
|
||||
th.footable-sortable:hover > span.fooicon {
|
||||
opacity: 1;
|
||||
}
|
||||
td.footable-sortable.footable-asc > span.fooicon,
|
||||
th.footable-sortable.footable-asc > span.fooicon,
|
||||
td.footable-sortable.footable-desc > span.fooicon,
|
||||
th.footable-sortable.footable-desc > span.fooicon {
|
||||
opacity: 1;
|
||||
}
|
||||
/* hides the sort icons when sorting is not allowed */
|
||||
table.footable-sorting-disabled td.footable-sortable.footable-asc > span.fooicon,
|
||||
table.footable-sorting-disabled td.footable-sortable.footable-desc > span.fooicon,
|
||||
table.footable-sorting-disabled td.footable-sortable:hover > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable.footable-asc > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable.footable-desc > span.fooicon,
|
||||
table.footable-sorting-disabled th.footable-sortable:hover > span.fooicon {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
.footable-paging-external ul.pagination,
|
||||
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
.footable-paging-external span.label,
|
||||
table.footable > tfoot > tr.footable-paging > td > span.label {
|
||||
display: inline-block;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.footable-paging-external.footable-paging-center,
|
||||
table.footable > tfoot > tr.footable-paging > td,
|
||||
table.footable-paging-center > tfoot > tr.footable-paging > td {
|
||||
text-align: center;
|
||||
}
|
||||
.footable-paging-external.footable-paging-left,
|
||||
table.footable-paging-left > tfoot > tr.footable-paging > td {
|
||||
text-align: left;
|
||||
}
|
||||
.footable-paging-external.footable-paging-right,
|
||||
table.footable-paging-right > tfoot > tr.footable-paging > td {
|
||||
text-align: right;
|
||||
}
|
||||
ul.pagination > li.footable-page {
|
||||
display: none;
|
||||
}
|
||||
ul.pagination > li.footable-page.visible {
|
||||
display: inline;
|
||||
}
|
||||
td.footable-editing {
|
||||
width: 90px;
|
||||
max-width: 90px;
|
||||
}
|
||||
table.footable-editing-no-edit td.footable-editing,
|
||||
table.footable-editing-no-delete td.footable-editing,
|
||||
table.footable-editing-no-view td.footable-editing {
|
||||
width: 70px;
|
||||
max-width: 70px;
|
||||
}
|
||||
table.footable-editing-no-edit.footable-editing-no-delete td.footable-editing,
|
||||
table.footable-editing-no-edit.footable-editing-no-view td.footable-editing,
|
||||
table.footable-editing-no-delete.footable-editing-no-view td.footable-editing {
|
||||
width: 50px;
|
||||
max-width: 50px;
|
||||
}
|
||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view td.footable-editing,
|
||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view th.footable-editing {
|
||||
width: 0;
|
||||
max-width: 0;
|
||||
display: none !important;
|
||||
}
|
||||
table.footable-editing-right td.footable-editing,
|
||||
table.footable-editing-right tr.footable-editing {
|
||||
text-align: right;
|
||||
}
|
||||
table.footable-editing-left td.footable-editing,
|
||||
table.footable-editing-left tr.footable-editing {
|
||||
text-align: left;
|
||||
}
|
||||
table.footable-editing button.footable-add,
|
||||
table.footable-editing button.footable-hide,
|
||||
table.footable-editing-show button.footable-show,
|
||||
table.footable-editing.footable-editing-always-show button.footable-show,
|
||||
table.footable-editing.footable-editing-always-show button.footable-hide,
|
||||
table.footable-editing.footable-editing-always-show.footable-editing-no-add tr.footable-editing {
|
||||
display: none;
|
||||
}
|
||||
table.footable-editing.footable-editing-show button.footable-add,
|
||||
table.footable-editing.footable-editing-show button.footable-hide,
|
||||
table.footable-editing.footable-editing-always-show button.footable-add {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* bootstrap-table - v1.12.1 - 2018-03-12
|
||||
* https://github.com/wenzhixin/bootstrap-table
|
||||
* Copyright (c) 2018 zhixin wen
|
||||
* Licensed MIT License
|
||||
*/
|
||||
!function(a){"use strict";a.fn.bootstrapTable.locales["en-US"]={formatLoadingMessage:function(){return"Loading, please wait..."},formatRecordsPerPage:function(a){return a+" rows per page"},formatShowingRows:function(a,b,c){return"Showing "+a+" to "+b+" of "+c+" rows"},formatSearch:function(){return"Search"},formatNoMatches:function(){return"No matching records found"},formatPaginationSwitch:function(){return"Hide/Show pagination"},formatRefresh:function(){return"Refresh"},formatToggle:function(){return"Toggle"},formatColumns:function(){return"Columns"},formatAllRows:function(){return"All"},formatExport:function(){return"Export data"},formatClearFilters:function(){return"Clear filters"}},a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales["en-US"])}(jQuery);
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* bootstrap-table - v1.12.1 - 2018-03-12
|
||||
* https://github.com/wenzhixin/bootstrap-table
|
||||
* Copyright (c) 2018 zhixin wen
|
||||
* Licensed MIT License
|
||||
*/
|
||||
!function(a){"use strict";var b=3;try{b=parseInt(a.fn.dropdown.Constructor.VERSION,10)}catch(c){}var d={3:{buttonsClass:"default",iconsPrefix:"glyphicon",icons:{paginationSwitchDown:"glyphicon-collapse-down icon-chevron-down",paginationSwitchUp:"glyphicon-collapse-up icon-chevron-up",refresh:"glyphicon-refresh icon-refresh",toggleOff:"glyphicon-list-alt icon-list-alt",toggleOn:"glyphicon-list-alt icon-list-alt",columns:"glyphicon-th icon-th",detailOpen:"glyphicon-plus icon-plus",detailClose:"glyphicon-minus icon-minus",fullscreen:"glyphicon-fullscreen"},pullClass:"pull",toobarDropdowHtml:['<ul class="dropdown-menu" role="menu">',"</ul>"],toobarDropdowItemHtml:'<li role="menuitem"><label>%s</label></li>',pageDropdownHtml:['<ul class="dropdown-menu" role="menu">',"</ul>"],pageDropdownItemHtml:'<li role="menuitem" class="%s"><a href="#">%s</a></li>'},4:{buttonsClass:"secondary",iconsPrefix:"fa",icons:{paginationSwitchDown:"fa-toggle-down",paginationSwitchUp:"fa-toggle-up",refresh:"fa-refresh",toggleOff:"fa-toggle-off",toggleOn:"fa-toggle-on",columns:"fa-th-list",detailOpen:"fa-plus",detailClose:"fa-minus",fullscreen:"fa-arrows-alt"},pullClass:"float",toobarDropdowHtml:['<div class="dropdown-menu dropdown-menu-right">',"</div>"],toobarDropdowItemHtml:'<label class="dropdown-item">%s</label>',pageDropdownHtml:['<div class="dropdown-menu">',"</div>"],pageDropdownItemHtml:'<a class="dropdown-item %s" href="#">%s</a>'}}[b],e=null,f=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},g=function(b,c,d,e){var f="";return a.each(b,function(a,b){return b[c]===e?(f=b[d],!1):!0}),f},h=function(b){var c,d,e,f=0,g=[];for(c=0;c<b[0].length;c++)f+=b[0][c].colspan||1;for(c=0;c<b.length;c++)for(g[c]=[],d=0;f>d;d++)g[c][d]=!1;for(c=0;c<b.length;c++)for(d=0;d<b[c].length;d++){var h=b[c][d],i=h.rowspan||1,j=h.colspan||1,k=a.inArray(!1,g[c]);for(1===j&&(h.fieldIndex=k,"undefined"==typeof h.field&&(h.field=k)),e=0;i>e;e++)g[c+e][k]=!0;for(e=0;j>e;e++)g[c][k+e]=!0}},i=function(){if(null===e){var b,c,d=a("<p/>").addClass("fixed-table-scroll-inner"),f=a("<div/>").addClass("fixed-table-scroll-outer");f.append(d),a("body").append(f),b=d[0].offsetWidth,f.css("overflow","scroll"),c=d[0].offsetWidth,b===c&&(c=f[0].clientWidth),f.remove(),e=b-c}return e},j=function(b,c,d,e){var g=c;if("string"==typeof c){var h=c.split(".");h.length>1?(g=window,a.each(h,function(a,b){g=g[b]})):g=window[c]}return"object"==typeof g?g:"function"==typeof g?g.apply(b,d||[]):!g&&"string"==typeof c&&f.apply(this,[c].concat(d))?f.apply(this,[c].concat(d)):e},k=function(b,c,d){var e=Object.getOwnPropertyNames||function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c);return b},f=e(b),g=e(c),h="";if(d&&f.length!==g.length)return!1;for(var i=0;i<f.length;i++)if(h=f[i],a.inArray(h,g)>-1&&b[h]!==c[h])return!1;return!0},l=function(a){return"string"==typeof a?a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/`/g,"`"):a},m=function(a){for(var b in a){var c=b.split(/(?=[A-Z])/).join("-").toLowerCase();c!==b&&(a[c]=a[b],delete a[b])}return a},n=function(a,b,c){var d=a;if("string"!=typeof b||a.hasOwnProperty(b))return c?l(a[b]):a[b];var e=b.split(".");for(var f in e)e.hasOwnProperty(f)&&(d=d&&d[e[f]]);return c?l(d):d},o=function(){return!!(navigator.userAgent.indexOf("MSIE ")>0||navigator.userAgent.match(/Trident.*rv\:11\./))},p=function(){Object.keys||(Object.keys=function(){var a=Object.prototype.hasOwnProperty,b=!{toString:null}.propertyIsEnumerable("toString"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],d=c.length;return function(e){if("object"!=typeof e&&("function"!=typeof e||null===e))throw new TypeError("Object.keys called on non-object");var f,g,h=[];for(f in e)a.call(e,f)&&h.push(f);if(b)for(g=0;d>g;g++)a.call(e,c[g])&&h.push(c[g]);return h}}())},q=function(b,c){this.options=c,this.$el=a(b),this.$el_=this.$el.clone(),this.timeoutId_=0,this.timeoutFooter_=0,this.init()};q.DEFAULTS={classes:"table table-hover",sortClass:void 0,locale:void 0,height:void 0,undefinedText:"-",sortName:void 0,sortOrder:"asc",sortStable:!1,rememberOrder:!1,striped:!1,columns:[[]],data:[],totalField:"total",dataField:"rows",method:"get",url:void 0,ajax:void 0,cache:!0,contentType:"application/json",dataType:"json",ajaxOptions:{},queryParams:function(a){return a},queryParamsType:"limit",responseHandler:function(a){return a},pagination:!1,onlyInfoPagination:!1,paginationLoop:!0,sidePagination:"client",totalRows:0,pageNumber:1,pageSize:10,pageList:[10,25,50,100],paginationHAlign:"right",paginationVAlign:"bottom",paginationDetailHAlign:"left",paginationPreText:"‹",paginationNextText:"›",search:!1,searchOnEnterKey:!1,strictSearch:!1,searchAlign:"right",selectItemName:"btSelectItem",showHeader:!0,showFooter:!1,showColumns:!1,showPaginationSwitch:!1,shoLine truncated
|
||||
|
||||
if((!e.fromHtml||"undefined"!=typeof p||z.checkbox||z.radio)&&z.visible&&(!e.options.cardView||z.cardVisible)){if(z.escape&&(p=l(p)),i=f('style="%s"',k.concat(e.header.styles[d]).join("; ")),b["_"+m+"_id"]&&(t=f(' id="%s"',b["_"+m+"_id"])),b["_"+m+"_class"]&&(u=f(' class="%s"',b["_"+m+"_class"])),b["_"+m+"_rowspan"]&&(w=f(' rowspan="%s"',b["_"+m+"_rowspan"])),b["_"+m+"_colspan"]&&(x=f(' colspan="%s"',b["_"+m+"_colspan"])),b["_"+m+"_title"]&&(y=f(' title="%s"',b["_"+m+"_title"])),s=j(e.header,e.header.cellStyles[d],[p,b,c,m],s),s.classes&&(u=f(' class="%s"',s.classes)),s.css){var A=[];for(var B in s.css)A.push(B+": "+s.css[B]);i=f('style="%s"',A.concat(e.header.styles[d]).join("; "))}q=j(z,e.header.formatters[d],[p,b,c,m],p),b["_"+m+"_data"]&&!a.isEmptyObject(b["_"+m+"_data"])&&a.each(b["_"+m+"_data"],function(a,b){"index"!==a&&(v+=f(' data-%s="%s"',a,b))}),z.checkbox||z.radio?(r=z.checkbox?"checkbox":r,r=z.radio?"radio":r,o=[f(e.options.cardView?'<div class="card-view %s">':'<td class="bs-checkbox %s">',z["class"]||""),"<input"+f(' data-index="%s"',c)+f(' name="%s"',e.options.selectItemName)+f(' type="%s"',r)+f(' value="%s"',b[e.options.idField])+f(' checked="%s"',q===!0||p||q&&q.checked?"checked":void 0)+f(' disabled="%s"',!z.checkboxEnabled||q&&q.disabled?"disabled":void 0)+" />",e.header.formatters[d]&&"string"==typeof q?q:"",e.options.cardView?"</div>":"</td>"].join(""),b[e.header.stateField]=q===!0||!!p||q&&q.checked):(q="undefined"==typeof q||null===q?e.options.undefinedText:q,o=e.options.cardView?['<div class="card-view">',e.options.showHeader?f('<span class="title" %s>%s</span>',i,g(e.columns,"field","title",m)):"",f('<span class="value">%s</span>',q),"</div>"].join(""):[f("<td%s %s %s %s %s %s %s>",t,u,i,v,w,x,y),q,"</td>"].join(""),e.options.cardView&&e.options.smartDisplay&&""===q&&(o='<div class="card-view"></div>')),h.push(o)}}),this.options.cardView&&h.push("</div></td>"),h.push("</tr>"),h.join(" ")}},q.prototype.initBody=function(b){var c=this,d=this.getData();this.trigger("pre-body",d),this.$body=this.$el.find(">tbody"),this.$body.length||(this.$body=a("<tbody></tbody>").appendTo(this.$el)),this.options.pagination&&"server"!==this.options.sidePagination||(this.pageFrom=1,this.pageTo=d.length);for(var e,g=a(document.createDocumentFragment()),h=this.pageFrom-1;h<this.pageTo;h++){var i=d[h],k=this.initRow(i,h,d,g);e=e||!!k,k&&k!==!0&&g.append(k)}e||g.append('<tr class="no-records-found">'+f('<td colspan="%s">%s</td>',this.$header.find("th").length,this.options.formatNoMatches())+"</tr>"),this.$body.html(g),b||this.scrollTo(0),this.$body.find("> tr[data-index] > td").off("click dblclick").on("click dblclick",function(b){var d=a(this),e=d.parent(),g=c.data[e.data("index")],h=d[0].cellIndex,i=c.getVisibleFields(),j=i[c.options.detailView&&!c.options.cardView?h-1:h],k=c.columns[c.fieldsColumnsIndex[j]],l=n(g,j,c.options.escape);if(!d.find(".detail-icon").length&&(c.trigger("click"===b.type?"click-cell":"dbl-click-cell",j,l,g,d),c.trigger("click"===b.type?"click-row":"dbl-click-row",g,e,j),"click"===b.type&&c.options.clickToSelect&&k.clickToSelect&&c.options.ignoreClickToSelectOn(b.target))){var m=e.find(f('[name="%s"]',c.options.selectItemName));m.length&&m[0].click()}}),this.$body.find("> tr[data-index] > td > .detail-icon").off("click").on("click",function(b){b.preventDefault();var e=a(this),g=e.parent().parent(),h=g.data("index"),i=d[h];if(g.next().is("tr.detail-view"))e.find("i").attr("class",f("%s %s",c.options.iconsPrefix,c.options.icons.detailOpen)),c.trigger("collapse-row",h,i,g.next()),g.next().remove();else{e.find("i").attr("class",f("%s %s",c.options.iconsPrefix,c.options.icons.detailClose)),g.after(f('<tr class="detail-view"><td colspan="%s"></td></tr>',g.find("td").length));var k=g.next().find("td"),l=j(c.options,c.options.detailFormatter,[h,i,k],"");1===k.length&&k.append(l),c.trigger("expand-row",h,i,k)}return c.resetView(),!1}),this.$selectItem=this.$body.find(f('[name="%s"]',this.options.selectItemName)),this.$selectItem.off("click").on("click",function(b){b.stopImmediatePropagation();var d=a(this),e=d.prop("checked"),f=c.data[d.data("index")];(a(this).is(":radio")||c.options.singleSelect)&&a.each(c.options.data,function(a,b){b[c.header.stateField]=!1}),f[c.header.stateField]=e,c.options.singleSelect&&(c.$selectItem.not(this).each(function(){c.data[a(this).data("index")][c.header.stateField]=!1}),c.$selectItem.filter(":checked").not(this).prop("checked",!1)),c.updateSelected(),c.trigger(e?"check":"uncheck",f,d)}),a.each(this.header.events,function(b,d){if(d){"string"==typeof d&&(d=j(null,d));var e=c.header.fields[b],f=a.inArray(e,c.getVisibleFields());if(-1!==f){c.options.detailView&&!c.options.cardView&&(f+=1);for(var g in d)c.$body.find(">tr:not(.no-records-found)").each(function(){var b=a(this),h=b.find(c.options.cardView?".card-view":"td").eq(f),i=g.indexOf(" "),j=g.substring(0,i),k=g.substring(i+1),l=d[g];h.find(k).off(j).on(j,function(a){var d=b.data("index"),f=c.data[d],g=fLine truncated
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,22 @@
|
||||
function editButton(url, text='Edit') {
|
||||
return "<button class='btn btn-success edit-button' type='button' url='" + url + "'>" + text + "</button>";
|
||||
}
|
||||
|
||||
function deleteButton(url, text='Delete') {
|
||||
return "<button class='btn btn-danger delete-button' type='button' url='" + url + "'>" + text + "</button>";
|
||||
}
|
||||
|
||||
function renderLink(text, url) {
|
||||
if (text && url) {
|
||||
return '<a href="' + url + '">' + text + '</a>';
|
||||
}
|
||||
else if (text) {
|
||||
return text;
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,30 @@ from rest_framework import serializers
|
||||
|
||||
from .models import StockItem, StockLocation
|
||||
|
||||
from part.serializers import PartBriefSerializer
|
||||
|
||||
|
||||
class LocationBriefSerializer(serializers.ModelSerializer):
|
||||
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = StockLocation
|
||||
fields = [
|
||||
'pk',
|
||||
'name',
|
||||
'pathstring',
|
||||
'url',
|
||||
]
|
||||
|
||||
|
||||
class StockItemSerializer(serializers.ModelSerializer):
|
||||
""" Serializer for a StockItem
|
||||
"""
|
||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
||||
|
||||
part = PartBriefSerializer(many=False, read_only=True)
|
||||
location = LocationBriefSerializer(many=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = StockItem
|
||||
@@ -16,17 +36,17 @@ class StockItemSerializer(serializers.ModelSerializer):
|
||||
'supplier_part',
|
||||
'location',
|
||||
'in_stock',
|
||||
'belongs_to',
|
||||
'customer',
|
||||
#'belongs_to',
|
||||
#'customer',
|
||||
'quantity',
|
||||
'serial',
|
||||
'batch',
|
||||
'status',
|
||||
'notes',
|
||||
'updated',
|
||||
'stocktake_date',
|
||||
'stocktake_user',
|
||||
'review_needed',
|
||||
#'updated',
|
||||
#'stocktake_date',
|
||||
#'stocktake_user',
|
||||
#'review_needed',
|
||||
]
|
||||
|
||||
""" These fields are read-only in this context.
|
||||
|
||||
@@ -9,35 +9,7 @@
|
||||
{% include "stock/location_list.html" with locations=locations %}
|
||||
{% endif %}
|
||||
|
||||
<table class="table table-striped" id='stock-table' data-filtering='true' data-sorting='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Part</th>
|
||||
<th>Location</th>
|
||||
<th data-type='number'>Stock</th>
|
||||
<th>Status</th>
|
||||
<th data-type='date'>Stocktake</th>
|
||||
<th data-sortable='false'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items.all %}
|
||||
<tr>
|
||||
<td><a href="{% url 'part-stock' item.part.id %}">{{ item.part.name }}</a></td>
|
||||
<td>
|
||||
{% if item.location %}
|
||||
<a href="{% url 'stock-location-detail' item.location.id %}">
|
||||
{{ item.location.pathstring }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ item.quantity }}</td>
|
||||
<td>{{ item.get_status_display }}</td>
|
||||
<td>{{ item.stocktake_date }}</td>
|
||||
<td><a href="{% url 'stock-item-detail' item.id %}">Click</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<table class="table table-striped" id='stock-table'>
|
||||
</table>
|
||||
|
||||
<div class='container-fluid'>
|
||||
@@ -49,12 +21,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#stock-table').footable();
|
||||
|
||||
$('#location-create').click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -63,4 +32,7 @@
|
||||
follow: true
|
||||
});
|
||||
});
|
||||
|
||||
{% include "stock/stock_table.html" %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -114,8 +114,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
{% include "stock/location_list.html" with locations=location.children %}
|
||||
{% endif %}
|
||||
|
||||
<h4>Stock Items</h4>
|
||||
{% include "stock/stock_table.html" with items=location.items %}
|
||||
{% if location.has_items %}
|
||||
<table class='table table-striped table-condensed' id='stock-table'>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<div class='container-fluid'>
|
||||
<button class='btn btn-success' id='location-create'>New Stock Location</button>
|
||||
@@ -28,12 +30,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block js_load %}
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#stock-table').footable();
|
||||
|
||||
$('#location-create').click(function () {
|
||||
launchModalForm("#modal-form",
|
||||
@@ -72,4 +71,7 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
{% include 'stock/stock_table.html' with location=location %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -1,22 +1,60 @@
|
||||
<table class="table table-striped" id='stock-table' data-filtering='true' data-sorting='true'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Part</th>
|
||||
<th data-type='number'>Stock</th>
|
||||
<th>Status</th>
|
||||
<th>Stocktake</th>
|
||||
<th data-sortable='false'></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items.all %}
|
||||
<tr>
|
||||
<td><a href="{% url 'part-stock' item.part.id %}">{{ item.part.name }}</a></td>
|
||||
<td>{{ item.quantity }}</td>
|
||||
<td>{{ item.get_status_display }}</td>
|
||||
<td>{{ item.stocktake_date }}</td>
|
||||
<td><a href="{% url 'stock-item-detail' item.id %}">Click</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
$("#stock-table").bootstrapTable({
|
||||
sortable: true,
|
||||
search: true,
|
||||
method: 'get',
|
||||
pagination: true,
|
||||
rememberOrder: true,
|
||||
{% if location %}
|
||||
queryParams: function(p) {
|
||||
return {
|
||||
location: {{ location.id }}
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
columns: [
|
||||
{
|
||||
checkbox: true,
|
||||
title: 'Select',
|
||||
searchable: false,
|
||||
},
|
||||
{
|
||||
field: 'pk',
|
||||
title: 'ID',
|
||||
visible: false,
|
||||
},
|
||||
{
|
||||
field: 'part.name',
|
||||
title: 'Part',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
return renderLink(value, row.part.url);
|
||||
}
|
||||
},
|
||||
{% if location == None %}
|
||||
{
|
||||
field: 'location',
|
||||
title: 'Location',
|
||||
sortable: true,
|
||||
formatter: function(value, row, index, field) {
|
||||
if (row.location) {
|
||||
return renderLink(row.location.name, row.location.url);
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{% endif %}
|
||||
{
|
||||
field: 'quantity',
|
||||
title: 'Stock',
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: 'Status',
|
||||
sortable: true,
|
||||
}
|
||||
],
|
||||
url: "{% url 'api-stock-list' %}",
|
||||
});
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap_3.3.7_css_bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/select2.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap-table.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/inventree.css' %}">
|
||||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
@@ -47,6 +48,12 @@ InvenTree
|
||||
<script type="text/javascript" src="{% static 'script/bootstrap.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'script/select2/select2.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/bootstrap-treeview.js' %}"></script>
|
||||
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/bootstrap-table.min.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/bootstrap-table-en-US.min.js' %}"></script>
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/tables.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/trees.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/sidenav.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/notification.js' %}"></script>
|
||||
|
||||
Reference in new issue
Block a user