- {% if roles.part.add %}
-
- {% endif %}
+
+
+
+
+
{% trans "Parameters" %}
+
+
+
+
+
+
+
+
{% trans "Attachments" %}
+
+
+ {% include "attachment_table.html" %}
-
@@ -269,6 +309,18 @@
{% block js_ready %}
{{ block.super }}
+ $('#edit-notes').click(function() {
+ constructForm('{% url "api-part-detail" part.pk %}', {
+ fields: {
+ notes: {
+ multiline: true,
+ }
+ },
+ title: '{% trans "Edit Part Notes" %}',
+ reload: true,
+ });
+ });
+
$(".slidey").change(function() {
var field = $(this).attr('fieldname');
@@ -337,4 +389,68 @@
});
});
+ loadAttachmentTable(
+ '{% url "api-part-attachment-list" %}',
+ {
+ filters: {
+ part: {{ part.pk }},
+ },
+ onEdit: function(pk) {
+ var url = `/api/part/attachment/${pk}/`;
+
+ constructForm(url, {
+ fields: {
+ comment: {},
+ },
+ title: '{% trans "Edit Attachment" %}',
+ onSuccess: reloadAttachmentTable,
+ });
+ },
+ onDelete: function(pk) {
+ var url = `/api/part/attachment/${pk}/`;
+
+ constructForm(url, {
+ method: 'DELETE',
+ confirmMessage: '{% trans "Confirm Delete Operation" %}',
+ title: '{% trans "Delete Attachment" %}',
+ onSuccess: reloadAttachmentTable,
+ });
+ }
+ }
+ );
+
+ enableDragAndDrop(
+ '#attachment-dropzone',
+ '{% url "api-part-attachment-list" %}',
+ {
+ data: {
+ part: {{ part.id }},
+ },
+ label: 'attachment',
+ success: function(data, status, xhr) {
+ reloadAttachmentTable();
+ }
+ }
+ );
+
+ $("#new-attachment").click(function() {
+
+ constructForm(
+ '{% url "api-part-attachment-list" %}',
+ {
+ method: 'POST',
+ fields: {
+ attachment: {},
+ comment: {},
+ part: {
+ value: {{ part.pk }},
+ hidden: true,
+ }
+ },
+ onSuccess: reloadAttachmentTable,
+ title: '{% trans "Add Attachment" %}',
+ }
+ )
+ });
+
{% endblock %}
diff --git a/InvenTree/part/templates/part/navbar.html b/InvenTree/part/templates/part/navbar.html
index afe4fee374..e8617dc677 100644
--- a/InvenTree/part/templates/part/navbar.html
+++ b/InvenTree/part/templates/part/navbar.html
@@ -109,16 +109,4 @@
{% endif %}
-
-
-
- {% trans "Attachments" %}
-
-
-
-
-
- {% trans "Notes" %}
-
-
diff --git a/InvenTree/part/templates/part/notes.html b/InvenTree/part/templates/part/notes.html
deleted file mode 100644
index 63e0190d48..0000000000
--- a/InvenTree/part/templates/part/notes.html
+++ /dev/null
@@ -1,57 +0,0 @@
-{% extends "part/part_base.html" %}
-{% load static %}
-{% load crispy_forms_tags %}
-{% load i18n %}
-{% load markdownify %}
-
-{% block menubar %}
-{% include 'part/navbar.html' with tab='notes' %}
-{% endblock %}
-
-{% block heading %}
-{% trans "Part Notes" %}
-{% if roles.part.change and not editing %}
-
-{% endif %}
-{% endblock %}
-
-{% block details %}
-
-{% if editing %}
-
-
-{{ form.media }}
-
-{% else %}
-
-
- {% if part.notes %}
-
- {{ part.notes | markdownify }}
-
- {% endif %}
-
-
-{% endif %}
-
-{% endblock %}
-
-{% block js_ready %}
-{{ block.super }}
-
-{% if editing %}
-{% else %}
-$("#edit-notes").click(function() {
- location.href = "{% url 'part-notes' part.id %}?edit=1";
-});
-{% endif %}
-
-{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py
index 8843a839a1..1fa7227f5e 100644
--- a/InvenTree/part/urls.py
+++ b/InvenTree/part/urls.py
@@ -61,8 +61,6 @@ part_detail_urls = [
url(r'^tests/', views.PartDetail.as_view(template_name='part/part_tests.html'), name='part-test-templates'),
url(r'^track/?', views.PartDetail.as_view(template_name='part/track.html'), name='part-track'),
url(r'^related-parts/?', views.PartDetail.as_view(template_name='part/related.html'), name='part-related'),
- url(r'^attachments/?', views.PartDetail.as_view(template_name='part/attachments.html'), name='part-attachments'),
- url(r'^notes/?', views.PartNotes.as_view(), name='part-notes'),
url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),
diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py
index 561b9be0fb..4acf5fcdb6 100644
--- a/InvenTree/part/views.py
+++ b/InvenTree/part/views.py
@@ -13,7 +13,7 @@ from django.shortcuts import get_object_or_404
from django.shortcuts import HttpResponseRedirect
from django.utils.translation import gettext_lazy as _
from django.urls import reverse, reverse_lazy
-from django.views.generic import DetailView, ListView, UpdateView
+from django.views.generic import DetailView, ListView
from django.forms.models import model_to_dict
from django.forms import HiddenInput, CheckboxInput
from django.conf import settings
@@ -747,40 +747,6 @@ class PartImportAjax(FileManagementAjaxView, PartImport):
return PartImport.validate(self, self.steps.current, form, **kwargs)
-class PartNotes(UpdateView):
- """ View for editing the 'notes' field of a Part object.
- Presents a live markdown editor.
- """
-
- context_object_name = 'part'
- # form_class = part_forms.EditNotesForm
- template_name = 'part/notes.html'
- model = Part
-
- role_required = 'part.change'
-
- fields = ['notes']
-
- def get_success_url(self):
- """ Return the success URL for this form """
-
- return reverse('part-notes', kwargs={'pk': self.get_object().id})
-
- def get_context_data(self, **kwargs):
-
- part = self.get_object()
-
- context = super().get_context_data(**kwargs)
-
- context['editing'] = str2bool(self.request.GET.get('edit', ''))
-
- ctx = part.get_context_data(self.request)
-
- context.update(ctx)
-
- return context
-
-
class PartDetail(InvenTreeRoleMixin, DetailView):
""" Detail view for Part object
"""
diff --git a/InvenTree/templates/js/forms.js b/InvenTree/templates/js/forms.js
index b71551747c..6dd7dbd968 100644
--- a/InvenTree/templates/js/forms.js
+++ b/InvenTree/templates/js/forms.js
@@ -353,12 +353,16 @@ function constructFormBody(fields, options) {
// Override existing query filters (if provided!)
fields[field].filters = Object.assign(fields[field].filters || {}, field_options.filters);
+ // TODO: Refactor the following code with Object.assign (see above)
+
// Secondary modal options
fields[field].secondary = field_options.secondary;
// Edit callback
fields[field].onEdit = field_options.onEdit;
+ fields[field].multiline = field_options.multiline;
+
// Custom help_text
if (field_options.help_text) {
fields[field].help_text = field_options.help_text;
@@ -1483,7 +1487,11 @@ function constructInputOptions(name, classes, type, parameters) {
opts.push(`placeholder='${parameters.placeholder}'`);
}
- return `
`;
+ if (parameters.multiline) {
+ return `
`;
+ } else {
+ return `
`;
+ }
}