mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Functional checkpoint: add/delete related parts from template
This commit is contained in:
parent
8579abb9c2
commit
34e4409e7f
@ -1254,25 +1254,32 @@ class Part(MPTTModel):
|
||||
|
||||
return self.get_descendants(include_self=False)
|
||||
|
||||
def fetch_related_parts(self):
|
||||
""" Return all related parts """
|
||||
def get_related_parts(self):
|
||||
""" Return list of tuples for all related parts:
|
||||
- first value is PartRelated object
|
||||
- second value is matching Part object
|
||||
"""
|
||||
|
||||
related_parts = []
|
||||
|
||||
parts_1 = self.related_parts_1.filter(part_1__id=self.pk)
|
||||
related_parts_1 = self.related_parts_1.filter(part_1__id=self.pk)
|
||||
|
||||
parts_2 = self.related_parts_2.filter(part_2__id=self.pk)
|
||||
related_parts_2 = self.related_parts_2.filter(part_2__id=self.pk)
|
||||
|
||||
for part in parts_1:
|
||||
# Append
|
||||
related_parts.append(part.part_2)
|
||||
for related_part in related_parts_1:
|
||||
# Add to related parts list
|
||||
related_parts.append((related_part, related_part.part_2))
|
||||
|
||||
for part in parts_2:
|
||||
# Append
|
||||
related_parts.append(part.part_1)
|
||||
for related_part in related_parts_2:
|
||||
# Add to related parts list
|
||||
related_parts.append((related_part, related_part.part_1))
|
||||
|
||||
return related_parts
|
||||
|
||||
@property
|
||||
def related_count(self):
|
||||
return len(self.get_related_parts())
|
||||
|
||||
|
||||
def attach_file(instance, filename):
|
||||
""" Function for storing a file for a PartAttachment
|
||||
@ -1783,7 +1790,8 @@ class PartRelated(models.Model):
|
||||
|
||||
@classmethod
|
||||
def create(cls, part_1, part_2):
|
||||
''' Create PartRelated object '''
|
||||
''' Create PartRelated object and relationship between two parts '''
|
||||
|
||||
related_part = cls()
|
||||
related_part.create_relationship(part_1, part_2)
|
||||
return related_part
|
||||
|
@ -18,7 +18,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class='table table-striped table-condensed related-table' id='table-related-part' data-toolbar='#button-bar'>
|
||||
<table id='table-related-part' class='table table-condensed table-striped' data-toolbar='#button-toolbar'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-field='part' data-serachable='true'>{% trans "Part" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in part.get_related_parts %}
|
||||
{% with part_related=item.0 part=item.1 %}
|
||||
<tr>
|
||||
<td>
|
||||
<a class='hover-icon'>
|
||||
<img class='hover-img-thumb' src='{{ part.get_thumbnail_url }}'>
|
||||
<img class='hover-img-large' src='{{ part.get_thumbnail_url }}'>
|
||||
</a>
|
||||
<a href='/part/{{ part.id }}/'>{{ part }}</a>
|
||||
<div class='btn-group' style='float: right;'>
|
||||
{% if roles.part.change %}
|
||||
<button title='{% trans "Delete" %}' class='btn btn-default btn-glyph delete-related-part' url="{% url 'part-related-delete' part_related.id %}" type='button'><span class='fas fa-trash-alt icon-red'/></button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
@ -27,20 +52,24 @@
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
loadPartRelatedTable($("#table-related-part"), {
|
||||
url: "{% url 'api-part-list' %}",
|
||||
params: {
|
||||
part: {{ part.id }},
|
||||
},
|
||||
});
|
||||
$('#table-related-part').inventreeTable({
|
||||
});
|
||||
|
||||
$("#add-related-part").click(function() {
|
||||
$("#add-related-part").click(function() {
|
||||
launchModalForm("{% url 'part-related-create' %}", {
|
||||
data: {
|
||||
part: {{ part.id }},
|
||||
},
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('.delete-related-part').click(function() {
|
||||
var button = $(this);
|
||||
|
||||
launchModalForm(button.attr('url'), {
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
|
||||
{% endblock %}
|
@ -64,7 +64,7 @@
|
||||
</li>
|
||||
{% endif %}
|
||||
<li{% ifequal tab 'related-parts' %} class="active"{% endifequal %}>
|
||||
<a href="{% url 'part-related' part.id %}">{% trans "Related Parts" %} {% if part.related_count > 0 %}<span class="badge">{{ part.related_count }}</span>{% endif %}</a>
|
||||
<a href="{% url 'part-related' part.id %}">{% trans "Related" %} {% if part.related_count > 0 %}<span class="badge">{{ part.related_count }}</span>{% endif %}</a>
|
||||
</li>
|
||||
<li{% ifequal tab 'attachments' %} class="active"{% endifequal %}>
|
||||
<a href="{% url 'part-attachments' part.id %}">{% trans "Attachments" %} {% if part.attachment_count > 0 %}<span class="badge">{{ part.attachment_count }}</span>{% endif %}</a>
|
||||
|
@ -81,10 +81,8 @@ class PartRelatedCreate(AjaxCreateView):
|
||||
ajax_template_name = "modal_form.html"
|
||||
role_required = 'part.change'
|
||||
|
||||
# TODO: QuerySet should not show parts already related to object
|
||||
|
||||
def get_initial(self):
|
||||
""" Point part_1 to parent part """
|
||||
""" Set parent part as part_1 field """
|
||||
|
||||
initials = {}
|
||||
|
||||
@ -102,12 +100,30 @@ class PartRelatedCreate(AjaxCreateView):
|
||||
""" Create a form to upload a new PartRelated
|
||||
|
||||
- Hide the 'part_1' field (parent part)
|
||||
- Display parts which are not yet related
|
||||
"""
|
||||
|
||||
form = super(AjaxCreateView, self).get_form()
|
||||
|
||||
form.fields['part_1'].widget = HiddenInput()
|
||||
|
||||
try:
|
||||
# Get parent part
|
||||
parent_part = self.get_initial()['part_1']
|
||||
# Get existing related parts
|
||||
related_parts = [related_part[1].pk for related_part in parent_part.get_related_parts()]
|
||||
|
||||
# Build updated choice list excluding parts already related to parent part
|
||||
updated_choices = []
|
||||
for choice in form.fields["part_2"].choices:
|
||||
if choice[0] not in related_parts:
|
||||
updated_choices.append(choice)
|
||||
|
||||
# Update choices for related part
|
||||
form.fields['part_2'].choices = updated_choices
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return form
|
||||
|
||||
def post_save(self):
|
||||
@ -116,14 +132,9 @@ class PartRelatedCreate(AjaxCreateView):
|
||||
form = self.get_form()
|
||||
|
||||
if form.is_valid():
|
||||
print('form is valid!')
|
||||
|
||||
part_1 = form.cleaned_data['part_1']
|
||||
part_2 = form.cleaned_data['part_2']
|
||||
|
||||
print(f'{part_1=}')
|
||||
print(f'{part_2=}')
|
||||
|
||||
PartRelated.create(part_1, part_2)
|
||||
|
||||
|
||||
@ -132,7 +143,6 @@ class PartRelatedDelete(AjaxDeleteView):
|
||||
|
||||
model = PartRelated
|
||||
ajax_form_title = _("Delete Related Part")
|
||||
ajax_template_name = "related_delete.html"
|
||||
context_object_name = "related"
|
||||
role_required = 'part.change'
|
||||
|
||||
|
@ -163,41 +163,6 @@ function loadSimplePartTable(table, url, options={}) {
|
||||
}
|
||||
|
||||
|
||||
function loadPartRelatedTable(table, options={}) {
|
||||
/* Load related parts table */
|
||||
|
||||
var columns = [
|
||||
{
|
||||
field: options.params['part'],
|
||||
title: '{% trans 'Part' %}',
|
||||
sortable: true,
|
||||
sortName: 'name',
|
||||
formatter: function(value, row, index, field) {
|
||||
|
||||
var name = '';
|
||||
|
||||
if (row.IPN) {
|
||||
name += row.IPN + ' | ' + row.name;
|
||||
} else {
|
||||
name += row.name;
|
||||
}
|
||||
|
||||
return renderLink(name, '/part/' + row.pk + '/');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$(table).inventreeTable({
|
||||
sortName: 'part',
|
||||
groupBy: false,
|
||||
name: options.name || 'related_parts',
|
||||
formatNoMatches: function() { return "{% trans "No parts found" %}"; },
|
||||
columns: columns,
|
||||
showColumns: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function loadParametricPartTable(table, options={}) {
|
||||
/* Load parametric table for part parameters
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user