Allow for customization of workflow
This commit is contained in:
parent
444aeb37e6
commit
326de9444d
34 changed files with 315 additions and 129 deletions
|
@ -4,4 +4,5 @@ from .layout import LayoutAdmin
|
|||
from .item import ItemAdmin
|
||||
from .manufacturer import ManufacturerAdmin
|
||||
from .form_factor import FormFactorAdmin
|
||||
from .tag import TagAdmin
|
||||
from .tag import TagAdmin
|
||||
from .settings import SettingsAdmin
|
21
inventory/admin/settings.py
Normal file
21
inventory/admin/settings.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from typing import Optional, TypeVar
|
||||
from django.db.models import Model
|
||||
from django.http.request import HttpRequest
|
||||
from django.contrib import admin
|
||||
|
||||
from inventory.models import Settings
|
||||
|
||||
|
||||
_ModelT = TypeVar("_ModelT", bound=Model)
|
||||
|
||||
|
||||
class SettingsAdmin(admin.ModelAdmin):
|
||||
|
||||
def has_add_permission(self, request: HttpRequest) -> bool:
|
||||
return False
|
||||
|
||||
def has_delete_permission(self, request: HttpRequest, obj: Optional[_ModelT] = None) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
admin.site.register(Settings, SettingsAdmin)
|
28
inventory/migrations/0004_auto_20201222_1858.py
Normal file
28
inventory/migrations/0004_auto_20201222_1858.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.1.4 on 2020-12-22 18:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0003_item_size'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='area',
|
||||
name='show_sub_area',
|
||||
field=models.BooleanField(default=True, help_text='Allow sub-areas to be defined in this area'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workshop',
|
||||
name='show_boxes',
|
||||
field=models.BooleanField(default=True, help_text='Allow boxes to be defined directly in this workshop'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='size',
|
||||
field=models.PositiveIntegerField(default=1, help_text='Number of sub-compartments this item takes up'),
|
||||
),
|
||||
]
|
27
inventory/migrations/0005_settings.py
Normal file
27
inventory/migrations/0005_settings.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 3.1.4 on 2020-12-22 19:29
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
def create_settings(apps, schema_editor):
|
||||
Settings = apps.get_model('inventory', 'Settings')
|
||||
Settings.objects.create(default_container=None)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0004_auto_20201222_1858'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Settings',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('default_container', models.ForeignKey(blank=True, default=None, help_text='Default container to display when calling the index page', null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.container')),
|
||||
],
|
||||
),
|
||||
migrations.RunPython(create_settings)
|
||||
]
|
|
@ -9,3 +9,4 @@ from .manufacturer import Manufacturer
|
|||
from .tag import Tag
|
||||
from .workshop import Workshop
|
||||
from .container import Container, CanBeContained
|
||||
from .settings import Settings
|
|
@ -6,6 +6,7 @@ from .container import Container, CanBeContained
|
|||
class Area(CanBeContained, Container):
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
description = models.CharField(max_length=4096)
|
||||
show_sub_area = models.BooleanField(default=True, help_text="Allow sub-areas to be defined in this area")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
changed_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.urls import reverse
|
||||
from django.db import models
|
||||
from django.apps import apps
|
||||
|
||||
|
@ -30,6 +29,9 @@ class Container(models.Model):
|
|||
|
||||
@property
|
||||
def url(self):
|
||||
_, obj = self.subclass
|
||||
if obj is not None:
|
||||
return obj.url
|
||||
return None
|
||||
|
||||
|
||||
|
@ -48,4 +50,4 @@ class CanBeContained(models.Model):
|
|||
@property
|
||||
def container_url(self):
|
||||
_, obj = self.container.subclass
|
||||
return obj.url
|
||||
return obj.url
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from django.db import models
|
||||
from django.contrib.postgres.fields import JSONField, ArrayField
|
||||
|
||||
from .container import CanBeContained
|
||||
|
||||
|
@ -23,4 +22,4 @@ class Item(CanBeContained):
|
|||
tags = models.ManyToManyField('inventory.Tag', blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
|
|
@ -11,4 +11,4 @@ class Manufacturer(models.Model):
|
|||
icon = models.ImageField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
return self.name
|
||||
|
|
18
inventory/models/settings.py
Normal file
18
inventory/models/settings.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class Settings(models.Model):
|
||||
default_container = models.ForeignKey(
|
||||
'inventory.Container',
|
||||
on_delete=models.SET_NULL,
|
||||
default=None,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text='Default container to display when calling the index page'
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return 'Settings'
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = 'Settings'
|
|
@ -6,6 +6,7 @@ from .container import Container
|
|||
class Workshop(Container):
|
||||
name = models.CharField(max_length=255, unique=True)
|
||||
description = models.CharField(max_length=4096)
|
||||
show_boxes = models.BooleanField(default=True, help_text="Allow boxes to be defined directly in this workshop")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
changed_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
|
|
|
@ -10,12 +10,15 @@ tr {
|
|||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
min-width: 100px;
|
||||
min-height: 75px;
|
||||
}
|
||||
|
||||
.cell {
|
||||
flex-grow: 1;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.cell:nth-child(2n) {
|
||||
|
|
|
@ -54,11 +54,11 @@ table.box th {
|
|||
|
||||
nav {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
background-color: #292981;
|
||||
color: #ffffff;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
nav form {
|
||||
|
@ -73,6 +73,12 @@ nav button {
|
|||
padding: 8px 10px 8px 10px;
|
||||
}
|
||||
|
||||
nav .icon-only-button {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
@ -103,29 +109,29 @@ nav .icon {
|
|||
filter: invert();
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
nav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@media (min-width: 1025px) {
|
||||
h1, h2 {
|
||||
width: 80%;
|
||||
}
|
||||
nav ul li {
|
||||
display: inline-block;
|
||||
text-indent: 0;
|
||||
margin: 0;
|
||||
padding: 0 10px 0 0;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 80%;
|
||||
}
|
||||
nav .spacer {
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
h1, h2 {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -144,4 +150,24 @@ h2 .icon {
|
|||
width: 25px;
|
||||
height: 25px;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.nav-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
height: 100%;
|
||||
width: 30%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.nav-list li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border: 1px solid black;
|
||||
margin-bottom: -1px;
|
||||
padding: 10px;
|
||||
text-indent: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
|
1
inventory/static/inventory/img/star-filled.svg
Normal file
1
inventory/static/inventory/img/star-filled.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"/></svg>
|
After Width: | Height: | Size: 516 B |
1
inventory/static/inventory/img/star-outline.svg
Normal file
1
inventory/static/inventory/img/star-outline.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z"/></svg>
|
After Width: | Height: | Size: 628 B |
|
@ -13,6 +13,15 @@
|
|||
{% block header_bar %}
|
||||
{% endblock %}
|
||||
</h2>
|
||||
|
||||
<div class="spacer">
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{% block header_icons %}
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<form method="POST" action="{% url "logout" %}">
|
||||
{% csrf_token %}
|
||||
|
|
|
@ -9,28 +9,34 @@
|
|||
<span class="small">{{ area.description}}</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block header_icons %}
|
||||
{% include 'inventory/set_index.html' with item=area is_index=is_index %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h3>Areas</h3>
|
||||
<ul>
|
||||
{% for a in area.area_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'area-detail' a.id %}" title="{{ a.description }}">{{ a.name }}</a>
|
||||
{% if user.is_staff %}
|
||||
<a class="edit" href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No areas defined</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if area.show_sub_area %}
|
||||
<h3>Areas</h3>
|
||||
<ul class="nav-list">
|
||||
{% for a in area.area_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'area-detail' a.id %}" title="{{ a.description }}">{{ a.name }}</a>
|
||||
{% if user.is_staff %}
|
||||
<a class="edit" href="{% url "admin:inventory_area_change" object_id=area.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No areas defined</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% if user.is_staff %}
|
||||
<p><a href="{% url "admin:inventory_area_add" %}?container={{ area.id }}&index=0">Create new area...</a></p>
|
||||
{% if user.is_staff %}
|
||||
<p><a href="{% url "admin:inventory_area_add" %}?container={{ area.id }}&index=0">Create new area...</a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<h3>Boxes</h3>
|
||||
<ul>
|
||||
<h3>Containers</h3>
|
||||
<ul class="nav-list">
|
||||
{% for box in area.box_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'box-detail' box.id %}" title="{{ box.description }}">{{ box.name }} ({{ box.layout.name }})</a>
|
||||
|
@ -39,7 +45,7 @@
|
|||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No boxes defined</li>
|
||||
<li>No containers defined</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
|
18
inventory/templates/inventory/box-detail.html
Normal file
18
inventory/templates/inventory/box-detail.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ object.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ object.name }}
|
||||
<span class="small">{{ object.description}}</span></h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block header_icons %}
|
||||
{% include 'inventory/set_index.html' with item=object is_index=is_index %}
|
||||
{% endblock %}
|
|
@ -1,12 +1,4 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ box.container.display_name }} - {{ box.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ box.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ box.container.display_name }} - {{ box.name }}
|
||||
<span class="small">{{ box.description}}</span>
|
||||
{% endblock %}
|
||||
{% extends "inventory/box-detail.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "inventory/box-detail.html" %}
|
||||
{% load static %}
|
||||
{% load admin_urls %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ object.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ object.name }}
|
||||
<span class="small">{{ object.description}}</span>{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<table class="box">
|
||||
<tbody>
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "inventory/box-detail.html" %}
|
||||
{% load static %}
|
||||
{% load admin_urls %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ object.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ object.name }}
|
||||
<span class="small">{{ object.description}}</span></h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<table class="box">
|
||||
<tbody>
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "inventory/box-detail.html" %}
|
||||
{% load static %}
|
||||
{% load admin_urls %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ object.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ object.name }}
|
||||
<span class="small">{{ object.description}}</span></h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<table class="box">
|
||||
<tbody>
|
||||
|
|
|
@ -1,19 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{% extends "inventory/box-detail.html" %}
|
||||
{% load static %}
|
||||
{% load admin_urls %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static "inventory/css/cell.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{{ object.name }}{% endblock %}
|
||||
|
||||
{% block header_bar %}
|
||||
<a href="{{ object.container_url }}"><img class="icon" src="{% static "inventory/img/back.svg" %}"></a>
|
||||
{{ object.name }}
|
||||
<span class="small">{{ object.description}}</span></h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% for part in layouted %}
|
||||
<table class="box">
|
||||
|
|
15
inventory/templates/inventory/set_index.html
Normal file
15
inventory/templates/inventory/set_index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% load static %}
|
||||
|
||||
<li>
|
||||
<form method="POST" action="{% url "index" %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="index_id" value='{{ item.id }}'>
|
||||
<button class="icon-only-button">
|
||||
{% if is_index %}
|
||||
<img class="icon" src="{% static "inventory/img/star-filled.svg" %}">
|
||||
{% else %}
|
||||
<img class="icon" src="{% static "inventory/img/star-outline.svg" %}">
|
||||
{% endif %}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
|
@ -9,9 +9,13 @@
|
|||
<span class="small">{{ workshop.description}}</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block header_icons %}
|
||||
{% include 'inventory/set_index.html' with item=workshop is_index=is_index %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>Areas</h3>
|
||||
<ul>
|
||||
<ul class="nav-list">
|
||||
{% for area in workshop.area_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'area-detail' area.id %}" title="{{ area.description }}">{{ area.name }}</a>
|
||||
|
@ -29,22 +33,24 @@
|
|||
<p><a href="{% url "admin:inventory_area_add" %}?container={{ workshop.id }}&index=0">Create new area...</a></p>
|
||||
{% endif %}
|
||||
|
||||
<h3>Boxes</h3>
|
||||
<ul>
|
||||
{% for box in workshop.box_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'box-detail' box.id %}" title="{{ box.description }}">{{ box.name }} ({{ box.layout.name }})</a>
|
||||
({{ box.description }})
|
||||
{% if user.is_staff %}
|
||||
<a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No boxes defined</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if workshop.show_boxes %}
|
||||
<h3>Containers</h3>
|
||||
<ul class="nav-list">
|
||||
{% for box in workshop.box_related.all %}
|
||||
<li>
|
||||
<a href="{% url 'box-detail' box.id %}" title="{{ box.description }}">{{ box.name }} ({{ box.layout.name }})</a>
|
||||
({{ box.description }})
|
||||
{% if user.is_staff %}
|
||||
<a class="edit" href="{% url "admin:inventory_box_change" object_id=box.pk %}"><img class="icon" src="{% static "inventory/img/edit.svg" %}"></a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No containers defined</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% if user.is_staff %}
|
||||
<p><a href="{% url "admin:inventory_box_add" %}?container={{ workshop.id }}&index=0">Create new box...</a></p>
|
||||
{% if user.is_staff %}
|
||||
<p><a href="{% url "admin:inventory_box_add" %}?container={{ workshop.id }}&index=0">Create new container...</a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -8,7 +8,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<ul>
|
||||
<ul class="nav-list">
|
||||
{% for workshop in object_list %}
|
||||
<li>
|
||||
<a href="{% url 'workshop-detail' workshop.id %}" title="{{ workshop.description }}">{{ workshop.name }}</a>
|
||||
|
@ -23,4 +23,5 @@
|
|||
<p><a href="{% url "admin:inventory_workshop_add" %}?layout=1">Create new workshop...</a></p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -17,7 +17,7 @@ Including another URLconf
|
|||
from django.urls import path
|
||||
|
||||
from .views import WorkshopListView, AreaListView, BoxListView, ItemListView, ManufacturerListView, DistributorListView
|
||||
from .views import WorkshopView, AreaView, BoxView, ItemView, DistributorView, ManufacturerView
|
||||
from .views import WorkshopView, AreaView, BoxView, ItemView, DistributorView, ManufacturerView, IndexView
|
||||
|
||||
urlpatterns = [
|
||||
path('workshops', WorkshopListView.as_view(), name='workshop-list'),
|
||||
|
@ -33,4 +33,5 @@ urlpatterns = [
|
|||
path('manufacturer/<int:pk>', ManufacturerView.as_view(), name='manufacturer-detail'),
|
||||
path('distributors', DistributorListView.as_view(), name='distributor-list'),
|
||||
path('distributor/<int:pk>', DistributorView.as_view(), name='distributor-detail'),
|
||||
path('', IndexView.as_view(), name='index')
|
||||
]
|
||||
|
|
|
@ -4,3 +4,14 @@ from .distributor import DistributorView, DistributorListView
|
|||
from .item import ItemView, ItemListView
|
||||
from .manufacturer import ManufacturerView, ManufacturerListView
|
||||
from .workshop import WorkshopView, WorkshopListView
|
||||
from .index import IndexView
|
||||
|
||||
__all__ = [
|
||||
AreaView, AreaListView,
|
||||
BoxView, BoxListView,
|
||||
DistributorView, DistributorListView,
|
||||
ItemView, ItemListView,
|
||||
ManufacturerView, ManufacturerListView,
|
||||
WorkshopView, WorkshopListView,
|
||||
IndexView
|
||||
]
|
|
@ -4,9 +4,11 @@ from django.views.generic import ListView, DetailView
|
|||
|
||||
from inventory.models import Area
|
||||
|
||||
from .utils import CanBeIndexMixin
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class AreaView(DetailView):
|
||||
class AreaView(CanBeIndexMixin, DetailView):
|
||||
context_object_name = 'area'
|
||||
queryset = Area.objects.all().select_related(
|
||||
'container',
|
||||
|
|
|
@ -6,9 +6,11 @@ from django.db.models import QuerySet
|
|||
|
||||
from inventory.models import Box
|
||||
|
||||
from .utils import CanBeIndexMixin
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class BoxView(DetailView):
|
||||
class BoxView(CanBeIndexMixin, DetailView):
|
||||
context_object_name = 'box'
|
||||
template_name_field = 'template_name'
|
||||
queryset = Box.objects.all().select_related(
|
||||
|
|
30
inventory/views/index.py
Normal file
30
inventory/views/index.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from django.urls import reverse
|
||||
from django.shortcuts import redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.generic import View
|
||||
|
||||
from inventory.models import Settings
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class IndexView(View):
|
||||
|
||||
def get(self, request):
|
||||
settings = Settings.objects.first()
|
||||
if settings.default_container is not None:
|
||||
print(settings.default_container.url)
|
||||
return redirect(settings.default_container.url)
|
||||
else:
|
||||
return redirect(reverse('workshop-list'))
|
||||
|
||||
def post(self, request):
|
||||
if 'index_id' in request.POST:
|
||||
settings = Settings.objects.first()
|
||||
new_container_id = int(request.POST['index_id'])
|
||||
if settings.default_container_id == new_container_id:
|
||||
settings.default_container = None
|
||||
else:
|
||||
settings.default_container_id = new_container_id
|
||||
settings.save()
|
||||
return redirect(request.META['HTTP_REFERER'])
|
11
inventory/views/utils.py
Normal file
11
inventory/views/utils.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from typing import Any, Dict
|
||||
|
||||
from inventory.models import Settings
|
||||
|
||||
|
||||
class CanBeIndexMixin:
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['is_index'] = Settings.objects.first().default_container_id == self.object.id
|
||||
print(context)
|
||||
return context
|
|
@ -1,12 +1,14 @@
|
|||
from typing import Any, Dict
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.generic import ListView, DetailView
|
||||
|
||||
from inventory.models import Workshop
|
||||
from inventory.models import Workshop, Settings
|
||||
from .utils import CanBeIndexMixin
|
||||
|
||||
|
||||
@method_decorator(login_required, name='dispatch')
|
||||
class WorkshopView(DetailView):
|
||||
class WorkshopView(CanBeIndexMixin, DetailView):
|
||||
context_object_name = 'workshop'
|
||||
queryset = Workshop.objects.all().prefetch_related('area_related', 'box_related')
|
||||
|
||||
|
@ -14,4 +16,3 @@ class WorkshopView(DetailView):
|
|||
@method_decorator(login_required, name='dispatch')
|
||||
class WorkshopListView(ListView):
|
||||
model = Workshop
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ from django.views.generic import RedirectView
|
|||
|
||||
urlpatterns = [
|
||||
path('', include('inventory.urls')),
|
||||
path('', RedirectView.as_view(pattern_name='workshop-list', permanent=False)),
|
||||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
path('admin/', admin.site.urls),
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue