diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 041603f7fb..9d5e1a2dc4 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -245,6 +245,7 @@ class AjaxCreateView(AjaxMixin, CreateView): # Return the PK of the newly-created object data['pk'] = obj.pk + data['text'] = str(obj) try: data['url'] = obj.get_absolute_url() diff --git a/InvenTree/build/templates/build/allocate.html b/InvenTree/build/templates/build/allocate.html index 9a0f045c68..5b66ef6b57 100644 --- a/InvenTree/build/templates/build/allocate.html +++ b/InvenTree/build/templates/build/allocate.html @@ -34,7 +34,6 @@ InvenTree | Allocate Parts {% block js_load %} {{ block.super }} - {% endblock %} diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 3aeb94700a..d255a319f3 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -670,6 +670,7 @@ class BomItem(models.Model): # A link to the parent part # Each part will get a reverse lookup field 'bom_items' part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='bom_items', + help_text='Select parent part', limit_choices_to={ 'buildable': True, 'active': True, @@ -678,16 +679,17 @@ class BomItem(models.Model): # A link to the child item (sub-part) # Each part will get a reverse lookup field 'used_in' sub_part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='used_in', + help_text='Select part to be used in BOM', limit_choices_to={ 'consumable': True, 'active': True }) # Quantity required - quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)]) + quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)], help_text='BOM quantity for this BOM item') # Note attached to this BOM line item - note = models.CharField(max_length=100, blank=True, help_text='Item notes') + note = models.CharField(max_length=100, blank=True, help_text='BOM item notes') def clean(self): """ Check validity of the BomItem model. @@ -767,7 +769,7 @@ class SupplierPart(models.Model): MPN = models.CharField(max_length=100, blank=True, help_text='Manufacturer part number') - URL = models.URLField(blank=True) + URL = models.URLField(blank=True, help_text='URL for external supplier part link') description = models.CharField(max_length=250, blank=True, help_text='Supplier part description') diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index 295fed23d6..3990bfab6c 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -56,8 +56,6 @@ {% block js_load %} {{ block.super }} - - {% endblock %} @@ -83,7 +81,15 @@ { success: function() { $("#bom-table").bootstrapTable('refresh'); - } + }, + secondary: [ + { + field: 'sub_part', + label: 'New Part', + title: 'Create New Part', + url: "{% url 'part-create' %}", + }, + ] } ); }); diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 286b5fc418..3abef26af9 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -61,8 +61,6 @@ {% endblock %} {% block js_load %} {{ block.super }} - - {% endblock %} {% block js_ready %} {{ block.super }} @@ -82,15 +80,30 @@ $("#part-create").click(function() { launchModalForm( - "{% url 'part-create' %}", - { - follow: true, - data: { - {% if category %} - category: {{ category.id }} - {% endif %} - } - }); + "{% url 'part-create' %}", + { + follow: true, + data: { + {% if category %} + category: {{ category.id }} + {% endif %} + }, + secondary: [ + { + field: 'category', + label: 'New Category', + title: 'Create new Part Category', + url: "{% url 'category-create' %}", + }, + { + field: 'default_location', + label: 'New Location', + title: 'Create new Stock Location', + url: "{% url 'stock-location-create' %}", + } + ] + } + ); }); {% if category %} diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index a7bad6cae4..787e071036 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -20,6 +20,7 @@
This part is used in BOMs for {{ part.used_in_count }} other parts. If you delete this part, the BOMs for the following parts will be updated:
There are {{ part.locations.all|length }} stock entries defined for this part. If you delete this part, the following stock entries will also be deleted:
There are {{ part.supplier_parts.all|length }} suppliers defined for this part. If you delete this part, the following supplier parts will also be deleted.
There are {{ part.serials.all|length }} unique parts tracked for '{{ part.full_name }}'. Deleting this part will permanently remove this tracking information.
-{% endif %} \ No newline at end of file +{% endif %} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/stock.html b/InvenTree/part/templates/part/stock.html index a329a25249..3311dafb8d 100644 --- a/InvenTree/part/templates/part/stock.html +++ b/InvenTree/part/templates/part/stock.html @@ -37,8 +37,6 @@ {% block js_load %} {{ block.super }} - - {% endblock %} {% block js_ready %} {{ block.super }} diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index fef88197f7..55482d3284 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -202,6 +202,7 @@ class PartDuplicate(AjaxCreateView): part = form.save() data['pk'] = part.pk + data['text'] = str(part) deep_copy = str2bool(request.POST.get('deep_copy', False)) @@ -321,6 +322,7 @@ class PartCreate(AjaxCreateView): part = form.save() data['pk'] = part.pk + data['text'] = str(part) try: data['url'] = part.get_absolute_url() diff --git a/InvenTree/static/css/inventree.css b/InvenTree/static/css/inventree.css index e096a94994..bca4560edf 100644 --- a/InvenTree/static/css/inventree.css +++ b/InvenTree/static/css/inventree.css @@ -51,7 +51,7 @@ background: #eee; display: none; position: absolute; - z-index: 999; + z-index: 400; border: 1px solid #555; max-width: 250px; } @@ -159,7 +159,15 @@ .modal { overflow: hidden; - z-index: 99999999; + z-index: 9999; +} + +.modal-primary { + z-index: 10000; +} + +.modal-secondary { + z-index: 11000; } .js-modal-form .checkbox { @@ -170,6 +178,11 @@ width: 45%; } +.modal-secondary .modal-dialog { + width: 40%; + padding-top: 15px; +} + .modal-content h3 { margin-top: 3px; margin-bottom: 3px; @@ -192,6 +205,16 @@ width: 100%; } +/* Force a control-label div to be 100% width */ +.modal .control-label { + width: 100%; +} + +.modal .control-label .btn { + padding-top: 3px; + padding-bottom: 3px; +} + /* The side navigation menu */ .sidenav { height: 100%; /* 100% Full-height */ @@ -217,7 +240,7 @@ margin-top: 20px; width: 100%; padding: 20px; - z-index: 999999; + z-index: 5000; pointer-events: none; // Prevent this div from blocking links underneath } diff --git a/InvenTree/static/script/inventree/modals.js b/InvenTree/static/script/inventree/modals.js index 67d4497674..afb14ace9f 100644 --- a/InvenTree/static/script/inventree/modals.js +++ b/InvenTree/static/script/inventree/modals.js @@ -102,7 +102,7 @@ function afterForm(response, options) { // Was a callback provided? if (options.success) { - options.success(); + options.success(response); } else if (options.follow && response.url) { window.location.href = response.url; @@ -354,6 +354,81 @@ function injectModalForm(modal, form_html) { } +function insertNewItemButton(modal, options) { + /* Insert a button into a modal form, after a field label. + * Looks for a