Attachment functionality for BuildOrder

This commit is contained in:
Oliver Walters 2020-10-26 17:00:31 +11:00
parent 664dd0000c
commit 7525bc2ead
6 changed files with 200 additions and 8 deletions

View File

@ -322,9 +322,14 @@ class AjaxCreateView(AjaxMixin, CreateView):
""" """
pass pass
def post_save(self, new_object, request, **kwargs): def post_save(self, **kwargs):
""" """
Hook for doing something with the created object after it is saved Hook for doing something with the created object after it is saved
kwargs:
request - The request object
new_object - The newly created object
""" """
pass pass
@ -356,7 +361,7 @@ class AjaxCreateView(AjaxMixin, CreateView):
self.pre_save(self.form, request) self.pre_save(self.form, request)
self.object = self.form.save() self.object = self.form.save()
self.post_save(self.object, request) self.post_save(new_object=self.object, request=request)
# Return the PK of the newly-created object # Return the PK of the newly-created object
data['pk'] = self.object.pk data['pk'] = self.object.pk
@ -411,7 +416,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
# Include context data about the updated object # Include context data about the updated object
data['pk'] = obj.id data['pk'] = obj.id
self.post_save(obj) self.post_save(new_object=obj, request=request)
try: try:
data['url'] = obj.get_absolute_url() data['url'] = obj.get_absolute_url()
@ -420,7 +425,7 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
return self.renderJsonResponse(request, form, data) return self.renderJsonResponse(request, form, data)
def post_save(self, obj, *args, **kwargs): def post_save(self, **kwargs):
""" """
Hook called after the form data is saved. Hook called after the form data is saved.
(Optional) (Optional)

View File

@ -11,7 +11,7 @@ from InvenTree.forms import HelperForm
from InvenTree.fields import RoundingDecimalFormField from InvenTree.fields import RoundingDecimalFormField
from django import forms from django import forms
from .models import Build, BuildItem from .models import Build, BuildItem, BuildOrderAttachment
from stock.models import StockLocation from stock.models import StockLocation
@ -164,3 +164,17 @@ class EditBuildItemForm(HelperForm):
'quantity', 'quantity',
'install_into', 'install_into',
] ]
class EditBuildAttachmentForm(HelperForm):
"""
Form for creating / editing a BuildAttachment object
"""
class Meta:
model = BuildOrderAttachment
fields = [
'build',
'attachment',
'comment'
]

View File

@ -0,0 +1,78 @@
{% extends "build/build_base.html" %}
{% load static %}
{% load i18n %}
{% load markdownify %}
{% block details %}
{% include "build/tabs.html" with tab='attachments' %}
<h4>{% trans "Attachments" %}</h4>
<hr>
{% include "attachment_table.html" with attachments=build.attachments.all %}
{% endblock %}
{% block js_ready %}
{{ block.super }}
enableDragAndDrop(
'#attachment-dropzone',
'{% url "build-attachment-create" %}',
{
data: {
build: {{ build.id }},
},
label: 'attachment',
success: function(data, status, xhr) {
location.reload();
}
}
);
// Callback for creating a new attachment
$('#new-attachment').click(function() {
launchModalForm(
'{% url "build-attachment-create" %}',
{
reload: true,
data: {
build: {{ build.pk }},
}
}
);
});
// Callback for editing an attachment
$("#attachment-table").on('click', '.attachment-edit-button', function() {
var pk = $(this).attr('pk');
var url = `/build/attachment/${pk}/edit/`;
launchModalForm(
url,
{
reload: true,
}
);
});
// Callback for deleting an attachment
$("#attachment-table").on('click', '.attachment-delete-button', function() {
var pk = $(this).attr('pk');
var url = `/build/attachment/${pk}/delete/`;
launchModalForm(
url,
{
reload: true,
}
);
});
$("#attachment-table").inventreeTable({});
{% endblock %}

View File

@ -13,4 +13,7 @@
<li{% if tab == 'notes' %} class='active'{% endif %}> <li{% if tab == 'notes' %} class='active'{% endif %}>
<a href="{% url 'build-notes' build.id %}">{% trans "Notes" %}{% if build.notes %} <span class='fas fa-info-circle'></span>{% endif %}</a> <a href="{% url 'build-notes' build.id %}">{% trans "Notes" %}{% if build.notes %} <span class='fas fa-info-circle'></span>{% endif %}</a>
</li> </li>
<li {% if tab == 'attachments' %} class='active'{% endif %}>
<a href='{% url "build-attachments" build.id %}'>{% trans "Attachments" %}</a>
</li>
</ul> </ul>

View File

@ -18,6 +18,7 @@ build_detail_urls = [
url(r'^notes/', views.BuildNotes.as_view(), name='build-notes'), url(r'^notes/', views.BuildNotes.as_view(), name='build-notes'),
url(r'^attachments/', views.BuildDetail.as_view(template_name='build/attachments.html'), name='build-attachments'),
url(r'^output/', views.BuildDetail.as_view(template_name='build/build_output.html'), name='build-output'), url(r'^output/', views.BuildDetail.as_view(template_name='build/build_output.html'), name='build-output'),
url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'), url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
@ -32,6 +33,12 @@ build_urls = [
url('^new/', views.BuildItemCreate.as_view(), name='build-item-create'), url('^new/', views.BuildItemCreate.as_view(), name='build-item-create'),
])), ])),
url('^attachment/', include([
url('^new/', views.BuildAttachmentCreate.as_view(), name='build-attachment-create'),
url(r'^(?P<pk>\d+)/edit/', views.BuildAttachmentEdit.as_view(), name='build-attachment-edit'),
url(r'^(?P<pk>\d+)/delete/', views.BuildAttachmentDelete.as_view(), name='build-attachment-delete'),
])),
url(r'new/', views.BuildCreate.as_view(), name='build-create'), url(r'new/', views.BuildCreate.as_view(), name='build-create'),
url(r'^(?P<pk>\d+)/', include(build_detail_urls)), url(r'^(?P<pk>\d+)/', include(build_detail_urls)),

View File

@ -12,7 +12,7 @@ from django.forms import HiddenInput
from django.urls import reverse from django.urls import reverse
from part.models import Part from part.models import Part
from .models import Build, BuildItem from .models import Build, BuildItem, BuildOrderAttachment
from . import forms from . import forms
from stock.models import StockLocation, StockItem from stock.models import StockLocation, StockItem
@ -527,12 +527,14 @@ class BuildCreate(AjaxCreateView):
'success': _('Created new build'), 'success': _('Created new build'),
} }
def post_save(self, new_object, request, **kwargs): def post_save(self, **kwargs):
""" """
Called immediately after a new Build object is created. Called immediately after a new Build object is created.
""" """
build = new_object build = kwargs['new_object']
request = kwargs['request']
build.createInitialStockItem(request.user) build.createInitialStockItem(request.user)
@ -795,3 +797,86 @@ class BuildItemEdit(AjaxUpdateView):
form.fields[field].widget = HiddenInput() form.fields[field].widget = HiddenInput()
return form return form
class BuildAttachmentCreate(AjaxCreateView):
"""
View for creating a BuildAttachment
"""
model = BuildOrderAttachment
form_class = forms.EditBuildAttachmentForm
ajax_form_title = _('Add Build Order Attachment')
role_required = 'build.add'
def post_save(self, **kwargs):
self.object.user = self.request.user
self.object.save()
def get_data(self):
return {
'success': _('Added attachment')
}
def get_initial(self):
"""
Get initial data for creating an attachment
"""
initials = super().get_initial()
try:
initials['build'] = Build.objects.get(pk=self.request.GET.get('build', -1))
except (ValueError, Build.DoesNotExist):
pass
return initials
def get_form(self):
"""
Hide the 'build' field if specified
"""
form = super().get_form()
form.fields['build'].widget = HiddenInput()
return form
class BuildAttachmentEdit(AjaxUpdateView):
"""
View for editing a BuildAttachment object
"""
model = BuildOrderAttachment
form_class = forms.EditBuildAttachmentForm
ajax_form_title = _('Edit Attachment')
role_required = 'build.change'
def get_form(self):
form = super().get_form()
form.fields['build'].widget = HiddenInput()
return form
def get_data(self):
return {
'success': _('Attachment updated')
}
class BuildAttachmentDelete(AjaxDeleteView):
"""
View for deleting a BuildAttachment
"""
model = BuildOrderAttachment
ajax_form_title = _('Delete Attachment')
context_object_name = 'attachment'
role_required = 'build.delete'
def get_data(self):
return {
'danger': _('Deleted attachment')
}