Implement package-detail view
This commit is contained in:
		@@ -292,3 +292,8 @@ class DistributorNumberFormSet(forms.BaseModelFormSet):
 | 
				
			|||||||
            if commit:
 | 
					            if commit:
 | 
				
			||||||
                instance.save()
 | 
					                instance.save()
 | 
				
			||||||
        return instances
 | 
					        return instances
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PackageForm(forms.ModelForm):
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = parts_models.Package
 | 
				
			||||||
 | 
					        fields = '__all__'
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					# Generated by Django 3.2 on 2021-11-14 15:24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					import django.db.models.deletion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ('parts', '0005_auto_20211113_1912'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='component',
 | 
				
			||||||
 | 
					            name='manufacturer',
 | 
				
			||||||
 | 
					            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parts.manufacturer'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='component',
 | 
				
			||||||
 | 
					            name='package',
 | 
				
			||||||
 | 
					            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parts.package'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        migrations.AlterField(
 | 
				
			||||||
 | 
					            model_name='component',
 | 
				
			||||||
 | 
					            name='pref_distri',
 | 
				
			||||||
 | 
					            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parts.distributor'),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
@@ -157,12 +157,12 @@ class Component(models.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
 | 
						id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
 | 
				
			||||||
	name = models.CharField(max_length=100)
 | 
						name = models.CharField(max_length=100)
 | 
				
			||||||
	manufacturer = models.ForeignKey(Manufacturer, on_delete=models.SET_NULL, blank=True, null=True)
 | 
						manufacturer = models.ForeignKey(Manufacturer, on_delete=models.PROTECT, blank=True, null=True)
 | 
				
			||||||
	component_type = models.ForeignKey(ComponentType, on_delete=models.SET_NULL, blank=True, null=True)
 | 
						component_type = models.ForeignKey(ComponentType, on_delete=models.SET_NULL, blank=True, null=True)
 | 
				
			||||||
	pref_distri = models.ForeignKey(Distributor, on_delete=models.SET_NULL, blank=True, null=True)
 | 
						pref_distri = models.ForeignKey(Distributor, on_delete=models.PROTECT, blank=True, null=True)
 | 
				
			||||||
	description = models.TextField(null=True, blank=True)
 | 
						description = models.TextField(null=True, blank=True)
 | 
				
			||||||
	datasheet_link = models.CharField(max_length=300, null=True, blank=True)
 | 
						datasheet_link = models.CharField(max_length=300, null=True, blank=True)
 | 
				
			||||||
	package = models.ForeignKey(Package, on_delete=models.SET_NULL, blank=True, null=True)
 | 
						package = models.ForeignKey(Package, on_delete=models.PROTECT, blank=True, null=True)
 | 
				
			||||||
	image = models.ImageField(upload_to=RandomFileName.RandomFileName('component-images'), blank=True, null=True)
 | 
						image = models.ImageField(upload_to=RandomFileName.RandomFileName('component-images'), blank=True, null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	def __str__(self):
 | 
						def __str__(self):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,8 @@ from .qr_parser import QrCodeValidator
 | 
				
			|||||||
from django.core.paginator import Paginator
 | 
					from django.core.paginator import Paginator
 | 
				
			||||||
from django.core.exceptions import ValidationError
 | 
					from django.core.exceptions import ValidationError
 | 
				
			||||||
from django.db import IntegrityError
 | 
					from django.db import IntegrityError
 | 
				
			||||||
from .forms import MyTestForm, AddSubStorageForm, DeleteStockForm, EditWatermarkForm, EditStockAmountForm, AddStockForm, EditComponentForm, EditComponentParameterForm, DistributorNumberForm, DistributorNumberFormSet
 | 
					from django.db.models import ProtectedError
 | 
				
			||||||
 | 
					from .forms import *
 | 
				
			||||||
from django.db.models import Q
 | 
					from django.db.models import Q
 | 
				
			||||||
from django.db.models.functions import Lower
 | 
					from django.db.models.functions import Lower
 | 
				
			||||||
import uuid
 | 
					import uuid
 | 
				
			||||||
@@ -527,5 +528,48 @@ class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
 | 
				
			|||||||
        self.base_title = 'Package / '+self.object.name
 | 
					        self.base_title = 'Package / '+self.object.name
 | 
				
			||||||
        context = super().get_context_data(**kwargs)
 | 
					        context = super().get_context_data(**kwargs)
 | 
				
			||||||
        context['package'] = self.object
 | 
					        context['package'] = self.object
 | 
				
			||||||
 | 
					        context['edit_form'] = PackageForm(instance=self.object)
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
        return context
 | 
					        return context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_delete_package(self, request):
 | 
				
			||||||
 | 
					        delete_error = None
 | 
				
			||||||
 | 
					        protected_objects = None
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Try to delete this instance
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            self.object.delete()
 | 
				
			||||||
 | 
					        except ProtectedError as pe:
 | 
				
			||||||
 | 
					            delete_error = 'Cannot delete this package. It is referenced by a component.'
 | 
				
			||||||
 | 
					            protected_objects = pe.protected_objects
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            delete_error = 'Cannot delete this package. Unknown error'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if delete_error:
 | 
				
			||||||
 | 
					            context = self.get_context_data()
 | 
				
			||||||
 | 
					            context['delete_error'] = delete_error
 | 
				
			||||||
 | 
					            context['protected_components'] = protected_objects
 | 
				
			||||||
 | 
					            return self.render_to_response(context)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return redirect('parts-main')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def edit_package(self, request):
 | 
				
			||||||
 | 
					        edit_form = PackageForm(data=request.POST, files=request.FILES, instance=self.object)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if edit_form.is_valid():
 | 
				
			||||||
 | 
					            edit_form.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        context = self.get_context_data()
 | 
				
			||||||
 | 
					        if not edit_form.is_valid():
 | 
				
			||||||
 | 
					            context['edit_form'] = edit_form
 | 
				
			||||||
 | 
					        return self.render_to_response(context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def post(self, request, *args, **kwargs):
 | 
				
			||||||
 | 
					        self.object = self.get_object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'submit-pkg-delete' in request.POST:
 | 
				
			||||||
 | 
					            return self.handle_delete_package(request)
 | 
				
			||||||
 | 
					        elif 'submit-pkg-edit' in request.POST:
 | 
				
			||||||
 | 
					            return self.edit_package(request)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return super().post(request, *args, **kwargs)
 | 
				
			||||||
@@ -1,8 +1,94 @@
 | 
				
			|||||||
{% extends 'base.html' %}
 | 
					{% extends 'base.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% load static %}
 | 
				
			||||||
 | 
					{% load crispy_forms_tags %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% block content %}
 | 
					{% block content %}
 | 
				
			||||||
<div class="container">
 | 
					<div class="container">
 | 
				
			||||||
    Meow<br>
 | 
					    <div class="row">
 | 
				
			||||||
    {{package}}
 | 
					        <div class="col-md-3">
 | 
				
			||||||
 | 
					            <div class="row justify-content-center">
 | 
				
			||||||
 | 
					                {% if package.image %}
 | 
				
			||||||
 | 
					                    <img src="{{package.image.url}}" alt="{{package.name}}" class="component-img-big btn" data-bs-toggle="modal" data-bs-target="#pkg-img-modal">
 | 
				
			||||||
 | 
					                {% else %}
 | 
				
			||||||
 | 
					                    <img src="{% static 'css/icons/card-image.svg' %}" alt="{{package.name}}" class="component-img-def-big">
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="row">
 | 
				
			||||||
 | 
					                <button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#pkg-delete-modal"><i class="bi bi-file-x"></i> Delete {{package.name}}</button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="col m-1">
 | 
				
			||||||
 | 
					        <h2>Package {{package.name}}</h2>
 | 
				
			||||||
 | 
					        <form action="" method="post" enctype="multipart/form-data">
 | 
				
			||||||
 | 
					            {% csrf_token %}
 | 
				
			||||||
 | 
					            {{edit_form|crispy}}
 | 
				
			||||||
 | 
					            <input type="submit" class="btn btn-primary" value="Save" name="submit-pkg-edit">
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if package.image %}
 | 
				
			||||||
 | 
					<div class="modal fade" id="pkg-img-modal" tabindex="-1">
 | 
				
			||||||
 | 
					    <div class="modal-dialog modal-lg modal-fullscreen-lg-down">
 | 
				
			||||||
 | 
					        <div class="modal-content">
 | 
				
			||||||
 | 
					            <div class="modal-header">
 | 
				
			||||||
 | 
					                <h5>{{package.name}}</h5>
 | 
				
			||||||
 | 
					                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="modal-body">
 | 
				
			||||||
 | 
					                <div class="text-center">
 | 
				
			||||||
 | 
					                    <img class="component-img-huge" src="{{package.image.url}}">
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- Delete modal -->
 | 
				
			||||||
 | 
					<div class="modal fade" id="pkg-delete-modal" tabindex="-1">
 | 
				
			||||||
 | 
					    <div class="modal-dialog modal-lg modal-fullscreen-lg-down">
 | 
				
			||||||
 | 
					        <div class="modal-content">
 | 
				
			||||||
 | 
					            <div class="modal-header">
 | 
				
			||||||
 | 
					                <h5>{{package.name}}</h5>
 | 
				
			||||||
 | 
					                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="modal-body">
 | 
				
			||||||
 | 
					                <h4>Delete this package?</h4>
 | 
				
			||||||
 | 
					                {% if delete_error %}
 | 
				
			||||||
 | 
					                <div class="alert alert-danger">
 | 
				
			||||||
 | 
					                    {{delete_error}}
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                {% if protected_components %}
 | 
				
			||||||
 | 
					                <h4>Following components prevent the deletion:</h4>
 | 
				
			||||||
 | 
					                <ul>
 | 
				
			||||||
 | 
					                    {% for comp in protected_components %}
 | 
				
			||||||
 | 
					                    <li><a class="text-decoration-none text-primary" href="{% url 'parts-components-detail' uuid=comp.id %}">{{comp}}</a></li>
 | 
				
			||||||
 | 
					                    {% endfor %}
 | 
				
			||||||
 | 
					                </ul>
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					                {% endif %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="modal-footer">
 | 
				
			||||||
 | 
					                <form action="" method="post">
 | 
				
			||||||
 | 
					                    {% csrf_token %}
 | 
				
			||||||
 | 
					                    <button type="submit" class="btn btn-danger" name="submit-pkg-delete"><i class="bi bi-file-x"></i> Delete {{package.name}}</button>
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% endblock content %}
 | 
					{% endblock content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block custom_scripts %}
 | 
				
			||||||
 | 
					<script type="text/javascript">
 | 
				
			||||||
 | 
					{% if delete_error %}
 | 
				
			||||||
 | 
					bootstrap.Modal.getOrCreateInstance(document.getElementById('pkg-delete-modal')).show();
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock custom_scripts %}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user