A good start on web interface

- Added details for "part" app
- Added BOM page for each part
- Added Stock page for each part
- Bootstrap! CSS!
This commit is contained in:
Oliver 2018-04-14 00:08:30 +10:00
parent bd46f66d6b
commit eec725d90f
14 changed files with 197 additions and 38 deletions

View File

@ -9,6 +9,9 @@ from bom.urls import bom_urls
from stock.urls import stock_urls, stock_loc_urls
from supplier.urls import cust_urls, manu_urls, supplier_part_urls, price_break_urls, supplier_urls
from django.conf import settings
from django.conf.urls.static import static
#from project.urls import prj_urls, prj_part_urls, prj_cat_urls, prj_run_urls
#from track.urls import unique_urls, part_track_urls
@ -65,4 +68,4 @@ urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
]
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -0,0 +1,23 @@
body {
padding-left: 15px;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
th {
text-align: left;
}
table tr:nth-child(even) {
background-color: #eee;
}
table tr:nth-child(odd) {
background-color: #fff;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -1,30 +0,0 @@
<h1>Part details for {{ part.name }}</h1>
{% include "cat_link.html" with category=part.category %}
<br>
Part name: {{ part.name }}
<br>
Description: {{ part.description }}
<br>
IPN: {% if part.IPN %}{{ part.IPN }}{% else %}N/A{% endif %}
<br>
Stock: {{ part.stock }}
<br><br>
BOM items: {{ part.bomItemCount }}<br>
Used in {{ part.usedInCount }} other parts.<br>
<h2>BOM</h2>
<ul>
{% for bom in part.bom_items.all %}
<li><a href="{% url 'detail' bom.sub_part.id %}">{{ bom.sub_part.name }}</a> ({{ bom.quantity }})</li>
{% endfor %}
</ul>
<h2>Used to make</h2>
<ul>
{% for p in part.used_in.all %}
<li><a href="{% url 'detail' p.part.id %}">{{ p.part.name }}</a></li>
{% endfor %}
</ul>

View File

@ -0,0 +1,29 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'css/part.css' %}">
<title>
{% block title %}
InvenTree
{% endblock %}
</title>
</head>
<body>
{% include "part/navbar.html" %}
{% block content %}
<!-- Each view fills in here.. -->
{% endblock %}
</body>
</html>

View File

@ -0,0 +1,22 @@
{% extends "part/part_base.html" %}
{% block details %}
<table>
<tr>
<th>Part</th>
<th>Description</th>
<th>Quantity</th>
</tr>
{% for bom_item in part.bom_items.all %}
{% with sub_part=bom_item.sub_part %}
<tr>
<td><a href="{% url 'detail' sub_part.id %}">{{ sub_part.name }}</a></td>
<td>{{ sub_part.description }}</td>
<td>{{ bom_item.quantity }}</td>
</tr>
{% endwith %}
{% endfor %}
</table>
{% endblock %}

View File

@ -1,4 +1,4 @@
<div id="category-path" background="#99F">
<div class="container">
<a href="/part/list/">All</a> >
{% for path_item in category.parentpath %}
<a href="/part/list/?category={{ path_item.id }}">{{ path_item.name }}</a> >

View File

@ -0,0 +1,12 @@
{% extends "part/part_base.html" %}
{% block details %}
<br>
<a href="{% url 'bom' part.id %}">There are <b>{{ part.bomItemCount }}</b> BOM items for this part.</a>
<br>
Used in {{ part.usedInCount }} other parts.<br>
<a href="{% url 'stock' part.id %}">There are {{ part.stock }} units in stock.</a>
{% endblock %}

View File

@ -1,7 +1,11 @@
{% extends "part/base.html" %}
{% block content %}
<h1>Parts page!</h1>
{% if category %}
{% include "cat_link.html" with category=category %}
{% include "part/cat_link.html" with category=category %}
<h3>Child categories</h3>
<ul>
{% for child in category.children.all %}
@ -25,3 +29,5 @@ No category!
{% endfor %}
</table>
{% endblock %}

View File

@ -0,0 +1,22 @@
{% load static %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">
<img src="{% static 'img/inventree.png' %}" width="30" height="30"/>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Parts<span class="sr-only">(current)</span></a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>

View File

@ -0,0 +1,21 @@
{% extends "part/base.html" %}
{% block content %}
{% include "part/cat_link.html" with category=part.category %}
<a href="{% url 'detail' part.id %}">{{ part.name }}</a>
<br>
{{ part.description }}
<br>
IPN: {% if part.IPN %}{{ part.IPN }}{% else %}N/A{% endif %}
<br>
{% block details %}
<!-- Specific part details go here... -->
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends "part/part_base.html" %}
{% block details %}
<br>
Total in stock: {{ part.stock }}
<br>
<table>
<tr>
<th>Quantity</th>
<th>Location</th>
<th>Supplier part</th>
<th>Stocktake</th>
<th>Notes</th>
</tr>
{% for stock in part.locations.all %}
<tr>
<td>{{ stock.quantity }}</td>
<td>{{ stock.location.name }}</td>
<td>
{% if stock.supplier_part %}
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
{% endif %}
</td>
<td>{% if stock.stocktake_date %}{{ stock.stocktake_date }}{% endif %}</td>
<td>{{ stock.notes }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,4 +1,4 @@
from django.conf.urls import url
from django.conf.urls import url, include
from django.views.generic.base import RedirectView
from . import views
@ -28,11 +28,18 @@ part_api_urls = [
url(r'^$', views.PartList.as_view()),
]
part_detail_urls = [
url(r'^bom/?', views.bom, name='bom'),
url(r'^stock/?', views.stock, name='stock'),
url('', views.detail, name='detail'),
]
# URL list for part web interface
part_urls = [
# Individual
url(r'^(?P<pk>\d+)/$', views.detail, name='detail'),
# ex: /part/
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),
url('list', views.index, name='index'),
# ex: /part/5/

View File

@ -31,7 +31,7 @@ class IndexView(generic.ListView):
"""
def index(request):
template = loader.get_template('index.html')
template = loader.get_template('part/index.html')
parts = Part.objects.all()
@ -59,10 +59,22 @@ def detail(request, pk):
part = get_object_or_404(Part, pk=pk)
return render(request, 'detail.html', {'part' : part})
return render(request, 'part/detail.html', {'part' : part})
#return HttpResponse("You're looking at part %s." % pk)
def bom(request, pk):
part = get_object_or_404(Part, pk=pk)
return render(request, 'part/bom.html', {'part': part})
def stock(request, pk):
part = get_object_or_404(Part, pk=pk)
return render(request, 'part/stock.html', {'part': part})
#def results(request, question_id):
# response = "You're looking at the results of question %s."
# return HttpResponse(response % question_id)