mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Implemented tree view
Using library bootstrap-treeview - part category tree - stock location tree - Currenly is functional but looks terrible
This commit is contained in:
parent
095492203f
commit
8d0789c37c
@ -12,6 +12,7 @@ from build.urls import build_urls
|
||||
|
||||
from part.api import part_api_urls
|
||||
from company.api import company_api_urls
|
||||
from stock.api import stock_api_urls
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
@ -25,6 +26,7 @@ admin.site.site_header = "InvenTree Admin"
|
||||
apipatterns = [
|
||||
url(r'^part/', include(part_api_urls)),
|
||||
url(r'^company/', include(company_api_urls)),
|
||||
url(r'^stock/', include(stock_api_urls)),
|
||||
|
||||
# User URLs
|
||||
url(r'^user/', include(user_urls)),
|
||||
|
@ -5,6 +5,48 @@ from django.template.loader import render_to_string
|
||||
from django.http import JsonResponse
|
||||
|
||||
from django.views.generic import UpdateView, CreateView, DeleteView
|
||||
from rest_framework import views
|
||||
from django.http import JsonResponse
|
||||
|
||||
|
||||
class TreeSerializer(views.APIView):
|
||||
|
||||
def itemToJson(self, item):
|
||||
|
||||
data = {
|
||||
'text': item.name,
|
||||
'href': item.get_absolute_url(),
|
||||
}
|
||||
|
||||
if item.has_children:
|
||||
nodes = []
|
||||
|
||||
for child in item.children.all().order_by('name'):
|
||||
nodes.append(self.itemToJson(child))
|
||||
|
||||
data['nodes'] = nodes
|
||||
|
||||
return data
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
top_items = self.model.objects.filter(parent=None).order_by('name')
|
||||
|
||||
nodes = []
|
||||
|
||||
for item in top_items:
|
||||
nodes.append(self.itemToJson(item))
|
||||
|
||||
top = {
|
||||
'text': self.title,
|
||||
'nodes': nodes,
|
||||
}
|
||||
|
||||
response = {
|
||||
'tree': [top]
|
||||
}
|
||||
|
||||
return JsonResponse(response, safe=False)
|
||||
|
||||
|
||||
class AjaxView(object):
|
||||
|
@ -7,9 +7,17 @@ from rest_framework import generics, permissions
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .models import Part
|
||||
from .models import Part, PartCategory
|
||||
from .serializers import PartSerializer
|
||||
|
||||
from InvenTree.views import TreeSerializer
|
||||
|
||||
|
||||
class PartCategoryTree(TreeSerializer):
|
||||
|
||||
title = "Parts"
|
||||
model = PartCategory
|
||||
|
||||
|
||||
class PartList(generics.ListCreateAPIView):
|
||||
|
||||
@ -44,5 +52,7 @@ class PartList(generics.ListCreateAPIView):
|
||||
|
||||
part_api_urls = [
|
||||
|
||||
url(r'^tree/?', PartCategoryTree.as_view(), name='api-part-tree'),
|
||||
|
||||
url(r'^.*$', PartList.as_view(), name='api-part-list'),
|
||||
]
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
<script type='text/javascript' src="{% static 'script/footable.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/modal_form.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/bootstrap-treeview.js' %}"></script>
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
$('#part-list').footable();
|
||||
@ -44,7 +43,36 @@
|
||||
});
|
||||
});
|
||||
|
||||
function loadTree() {
|
||||
var requestData = {};
|
||||
|
||||
{% if category %}
|
||||
requestData.category = {{ category.id }};
|
||||
{% endif %}
|
||||
|
||||
$.ajax({
|
||||
url: "{% url 'api-part-tree' %}",
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
data: requestData,
|
||||
success: function (response) {
|
||||
if (response.tree) {
|
||||
$("#part-tree").treeview({
|
||||
data: response.tree,
|
||||
enableLinks: true
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
alert('Error retrieving part tree:\n' + thrownError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#create-part").click(function() {
|
||||
launchModalForm("#modal-form", "{% url 'part-create' %}");
|
||||
});
|
||||
|
||||
loadTree();
|
||||
|
||||
{% endblock %}
|
||||
|
37
InvenTree/static/css/bootstrap-treeview.css
vendored
Normal file
37
InvenTree/static/css/bootstrap-treeview.css
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/* =========================================================
|
||||
* bootstrap-treeview.css v1.2.0
|
||||
* =========================================================
|
||||
* Copyright 2013 Jonathan Miles
|
||||
* Project URL : http://www.jondmiles.com/bootstrap-treeview
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ========================================================= */
|
||||
|
||||
.treeview .list-group-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.treeview span.indent {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.treeview span.icon {
|
||||
width: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.treeview .node-disabled {
|
||||
color: silver;
|
||||
cursor: not-allowed;
|
||||
}
|
@ -41,8 +41,17 @@
|
||||
}
|
||||
|
||||
.inventree-content {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
padding-top: 15px;
|
||||
margin-right: 50px;
|
||||
margin-left: 50px;
|
||||
width: 100%;
|
||||
transition: 0.5s;
|
||||
}
|
||||
|
||||
.body {
|
||||
padding-top: 70px;
|
||||
}
|
||||
|
||||
.modal {
|
||||
@ -61,4 +70,19 @@
|
||||
max-height: calc(100vh - 200px) !important;
|
||||
overflow-y: scroll;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* The side navigation menu */
|
||||
.sidenav {
|
||||
height: 100%; /* 100% Full-height */
|
||||
width: 0px; /* 0 width - change this with JavaScript */
|
||||
position: fixed; /* Stay in place */
|
||||
background-color: #fff; /* Black*/
|
||||
overflow-x: hidden; /* Disable horizontal scroll */
|
||||
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
align-items: stretch;
|
||||
display: flex;
|
||||
}
|
1249
InvenTree/static/script/bootstrap-treeview.js
vendored
Normal file
1249
InvenTree/static/script/bootstrap-treeview.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
InvenTree/static/script/sidenav.js
Normal file
9
InvenTree/static/script/sidenav.js
Normal file
@ -0,0 +1,9 @@
|
||||
function openSideNav() {
|
||||
document.getElementById("sidenav").style.width = "250px";
|
||||
document.getElementById("inventree-content").style.marginLeft = "270px";
|
||||
}
|
||||
|
||||
function closeSideNav() {
|
||||
document.getElementById("sidenav").style.width = "0";
|
||||
document.getElementById("inventree-content").style.marginLeft = "0";
|
||||
}
|
20
InvenTree/static/script/trees.js
Normal file
20
InvenTree/static/script/trees.js
Normal file
@ -0,0 +1,20 @@
|
||||
function loadTree(url, tree, data) {
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'get',
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: function (response) {
|
||||
if (response.tree) {
|
||||
$(tree).treeview({
|
||||
data: response.tree,
|
||||
enableLinks: true
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
//TODO
|
||||
}
|
||||
});
|
||||
}
|
@ -3,11 +3,20 @@ from django_filters import NumberFilter
|
||||
|
||||
from rest_framework import generics, permissions, response
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
# from InvenTree.models import FilterChildren
|
||||
from .models import StockLocation, StockItem
|
||||
from .serializers import StockItemSerializer, StockQuantitySerializer
|
||||
from .serializers import LocationSerializer
|
||||
|
||||
from InvenTree.views import TreeSerializer
|
||||
|
||||
|
||||
class StockCategoryTree(TreeSerializer):
|
||||
title = 'Stock'
|
||||
model = StockLocation
|
||||
|
||||
|
||||
class StockDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
@ -127,3 +136,8 @@ class LocationList(generics.ListCreateAPIView):
|
||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||
filter_backends = (DjangoFilterBackend,)
|
||||
filter_class = StockLocationFilter
|
||||
|
||||
|
||||
stock_api_urls = [
|
||||
url(r'^tree/?', StockCategoryTree.as_view(), name='api-stock-tree'),
|
||||
]
|
@ -15,9 +15,7 @@
|
||||
|
||||
{% block css %}
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
<title>
|
||||
@ -31,22 +29,42 @@ InvenTree
|
||||
|
||||
{% include "navbar.html" %}
|
||||
|
||||
<div class="container container-fluid inventree-content">
|
||||
<div class='main body wrapper'>
|
||||
|
||||
{% include "sidebar.html" %}
|
||||
|
||||
<div class="container container-fluid inventree-content" id='inventree-content'>
|
||||
{% block content %}
|
||||
<!-- Each view fills in here.. -->
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script type="text/javascript" src="{% static 'script/jquery_3.3.1_jquery.min.js' %}"></script>
|
||||
<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/trees.js' %}"></script>
|
||||
<script type='text/javascript' src="{% static 'script/sidenav.js' %}"></script>
|
||||
|
||||
{% block js_load %}
|
||||
{% endblock %}
|
||||
|
||||
<script type='text/javascript'>
|
||||
$(document).ready(function () {
|
||||
|
||||
loadTree("{% url 'api-part-tree' %}",
|
||||
"#part-tree");
|
||||
|
||||
loadTree("{% url 'api-stock-tree' %}",
|
||||
"#stock-tree");
|
||||
|
||||
$('#logo').click(function() {
|
||||
openSideNav();
|
||||
});
|
||||
|
||||
{% block js_ready %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -1,9 +1,9 @@
|
||||
{% load static %}
|
||||
|
||||
<nav class="navbar navbar-default">
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/"><img src="{% static 'img/inventree.png' %}" width="40" height="40"/></a>
|
||||
<a class="navbar-brand" id='logo'><img src="{% static 'img/inventree.png' %}" width="40" height="40"/></a>
|
||||
</div>
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="{% url 'part-index' %}">Parts</a></li>
|
||||
|
9
InvenTree/templates/sidebar.html
Normal file
9
InvenTree/templates/sidebar.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div class='sidenav' id='sidenav'>
|
||||
|
||||
<div id='part-tree'></div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div id='stock-tree'></div>
|
||||
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user