Implemented tree view

Using library bootstrap-treeview
- part category tree
- stock location tree
- Currenly is functional but looks terrible
This commit is contained in:
Oliver 2018-04-28 23:22:12 +10:00
parent 095492203f
commit 8d0789c37c
13 changed files with 1471 additions and 9 deletions

View File

@ -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)),

View File

@ -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):

View File

@ -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'),
]

View File

@ -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 %}

View 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;
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View 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";
}

View 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
}
});
}

View File

@ -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'),
]

View File

@ -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 %}

View File

@ -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>

View File

@ -0,0 +1,9 @@
<div class='sidenav' id='sidenav'>
<div id='part-tree'></div>
<hr>
<div id='stock-tree'></div>
</div>