mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge pull request #1808 from SchrodingersGat/part-page-refactor
Move "attachments" and "notes" to "Part Detail" page
This commit is contained in:
commit
2295008944
@ -837,6 +837,12 @@ input[type="submit"] {
|
|||||||
pointer-events: none; /* Prevent this div from blocking links underneath */
|
pointer-events: none; /* Prevent this div from blocking links underneath */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notes {
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
display: none;
|
display: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
@ -853,6 +859,11 @@ input[type="submit"] {
|
|||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-small {
|
||||||
|
padding: 3px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-remove {
|
.btn-remove {
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
{% extends "part/part_base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block menubar %}
|
|
||||||
{% include 'part/navbar.html' with tab='attachments' %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block heading %}
|
|
||||||
{% trans "Part Attachments" %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block details %}
|
|
||||||
|
|
||||||
{% include "attachment_table.html" with attachments=part.part_attachments %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block js_ready %}
|
|
||||||
{{ block.super }}
|
|
||||||
|
|
||||||
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 %}
|
|
@ -1,6 +1,7 @@
|
|||||||
{% extends "part/part_base.html" %}
|
{% extends "part/part_base.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load markdownify %}
|
||||||
|
|
||||||
|
|
||||||
{% block menubar %}
|
{% block menubar %}
|
||||||
@ -135,11 +136,38 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.responsible %}
|
{% if part.responsible %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-user'>d</span></td>
|
<td><span class='fas fa-user'></span></td>
|
||||||
<td><strong>{% trans "Responsible User" %}</strong></td>
|
<td><strong>{% trans "Responsible User" %}</strong></td>
|
||||||
<td>{{ part.responsible }}</td>
|
<td>{{ part.responsible }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<tr><td colspan="3"></td></tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><span class='fas fa-sticky-note'></span></td>
|
||||||
|
<td>
|
||||||
|
<strong>{% trans "Notes" %}</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class='btn-group float-right'>
|
||||||
|
<button type='button' id='edit-notes' title='{% trans "Edit Notes" %}' class='btn btn-small btn-default'>
|
||||||
|
<span class='fas fa-edit'>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan='3'>
|
||||||
|
{% if part.notes %}
|
||||||
|
<div class='notes'>
|
||||||
|
{{ part.notes | markdownify }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class='col-sm-6'>
|
<div class='col-sm-6'>
|
||||||
@ -240,11 +268,11 @@
|
|||||||
|
|
||||||
{% block post_content_panel %}
|
{% block post_content_panel %}
|
||||||
|
|
||||||
|
<div class='row'>
|
||||||
|
<div class='col-sm-6'>
|
||||||
<div class='panel panel-default panel-inventree'>
|
<div class='panel panel-default panel-inventree'>
|
||||||
<div class='panel-heading'>
|
<div class='panel-heading'>
|
||||||
<h4>
|
<h4>{% trans "Parameters" %}</h4>
|
||||||
{% trans "Part Parameters" %}
|
|
||||||
</h4>
|
|
||||||
</div>
|
</div>
|
||||||
<div class='panel-content'>
|
<div class='panel-content'>
|
||||||
<div id='param-button-toolbar'>
|
<div id='param-button-toolbar'>
|
||||||
@ -259,6 +287,18 @@
|
|||||||
<table id='parameter-table' class='table table-condensed table-striped' data-toolbar="#param-button-toolbar"></table>
|
<table id='parameter-table' class='table table-condensed table-striped' data-toolbar="#param-button-toolbar"></table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='col-sm-6'>
|
||||||
|
<div class='panel panel-default panel-inventree'>
|
||||||
|
<div class='panel-heading'>
|
||||||
|
<h4>{% trans "Attachments" %}</h4>
|
||||||
|
</div>
|
||||||
|
<div class='panel-content'>
|
||||||
|
{% include "attachment_table.html" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -269,6 +309,18 @@
|
|||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{{ block.super }}
|
{{ 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() {
|
$(".slidey").change(function() {
|
||||||
var field = $(this).attr('fieldname');
|
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 %}
|
{% endblock %}
|
||||||
|
@ -109,16 +109,4 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class='list-group-item {% if tab == "attachments" %}active{% endif %}' title='{% trans "Attachments" %}'>
|
|
||||||
<a href='{% url "part-attachments" part.id %}'>
|
|
||||||
<span class='menu-tab-icon fas fa-paperclip sidebar-icon'></span>
|
|
||||||
{% trans "Attachments" %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class='list-group-item {% if tab == "notes" %}active{% endif %}' title='{% trans "Part Notes" %}'>
|
|
||||||
<a href='{% url "part-notes" part.id %}'>
|
|
||||||
<span class='menu-tab-icon fas fa-clipboard sidebar-icon'></span>
|
|
||||||
{% trans "Notes" %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -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 %}
|
|
||||||
<button title='{% trans "Edit notes" %}' class='btn btn-default' id='edit-notes'><span class='fas fa-edit'></span></button>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block details %}
|
|
||||||
|
|
||||||
{% if editing %}
|
|
||||||
<form method='POST'>
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
{{ form }}
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<button type="submit" class='btn btn-default'>{% trans "Save" %}</button>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{{ form.media }}
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
|
|
||||||
<div class='panel panel-default'>
|
|
||||||
{% if part.notes %}
|
|
||||||
<div class='panel-content'>
|
|
||||||
{{ part.notes | markdownify }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% 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 %}
|
|
@ -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'^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'^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'^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'),
|
url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from django.shortcuts import get_object_or_404
|
|||||||
from django.shortcuts import HttpResponseRedirect
|
from django.shortcuts import HttpResponseRedirect
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.urls import reverse, reverse_lazy
|
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.models import model_to_dict
|
||||||
from django.forms import HiddenInput, CheckboxInput
|
from django.forms import HiddenInput, CheckboxInput
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -747,40 +747,6 @@ class PartImportAjax(FileManagementAjaxView, PartImport):
|
|||||||
return PartImport.validate(self, self.steps.current, form, **kwargs)
|
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):
|
class PartDetail(InvenTreeRoleMixin, DetailView):
|
||||||
""" Detail view for Part object
|
""" Detail view for Part object
|
||||||
"""
|
"""
|
||||||
|
@ -353,12 +353,16 @@ function constructFormBody(fields, options) {
|
|||||||
// Override existing query filters (if provided!)
|
// Override existing query filters (if provided!)
|
||||||
fields[field].filters = Object.assign(fields[field].filters || {}, field_options.filters);
|
fields[field].filters = Object.assign(fields[field].filters || {}, field_options.filters);
|
||||||
|
|
||||||
|
// TODO: Refactor the following code with Object.assign (see above)
|
||||||
|
|
||||||
// Secondary modal options
|
// Secondary modal options
|
||||||
fields[field].secondary = field_options.secondary;
|
fields[field].secondary = field_options.secondary;
|
||||||
|
|
||||||
// Edit callback
|
// Edit callback
|
||||||
fields[field].onEdit = field_options.onEdit;
|
fields[field].onEdit = field_options.onEdit;
|
||||||
|
|
||||||
|
fields[field].multiline = field_options.multiline;
|
||||||
|
|
||||||
// Custom help_text
|
// Custom help_text
|
||||||
if (field_options.help_text) {
|
if (field_options.help_text) {
|
||||||
fields[field].help_text = field_options.help_text;
|
fields[field].help_text = field_options.help_text;
|
||||||
@ -1483,8 +1487,12 @@ function constructInputOptions(name, classes, type, parameters) {
|
|||||||
opts.push(`placeholder='${parameters.placeholder}'`);
|
opts.push(`placeholder='${parameters.placeholder}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parameters.multiline) {
|
||||||
|
return `<textarea ${opts.join(' ')}></textarea>`;
|
||||||
|
} else {
|
||||||
return `<input ${opts.join(' ')}>`;
|
return `<input ${opts.join(' ')}>`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Construct a "hidden" input
|
// Construct a "hidden" input
|
||||||
|
Loading…
Reference in New Issue
Block a user