From 293b5d4c071041dd849691fd2203e88af548584f Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 30 Jun 2021 00:13:53 +1000 Subject: [PATCH] Allow file and image fields - Use FormData class - Replace existing Company image upload form --- .../templates/company/company_base.html | 18 +++++- InvenTree/company/urls.py | 1 - InvenTree/company/views.py | 14 ----- InvenTree/templates/js/company.js | 33 ----------- InvenTree/templates/js/forms.js | 58 ++++++++++++++++--- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/InvenTree/company/templates/company/company_base.html b/InvenTree/company/templates/company/company_base.html index 197ddbf75e..52d5abf3e6 100644 --- a/InvenTree/company/templates/company/company_base.html +++ b/InvenTree/company/templates/company/company_base.html @@ -157,10 +157,22 @@ {% endif %} $("#company-image-upload").click(function() { - launchModalForm( - "{% url 'company-image' company.id %}", + + constructForm( + '{% url "api-company-detail" company.pk %}', { - reload: true + method: 'PATCH', + fields: { + image: {}, + }, + title: '{% trans "Upload Image" %}', + onSuccess: function(data) { + if (data.image) { + $('#company-image').attr('src', data.image); + } else { + location.reload(); + } + } } ); }); diff --git a/InvenTree/company/urls.py b/InvenTree/company/urls.py index 0aa4d39364..51685215b6 100644 --- a/InvenTree/company/urls.py +++ b/InvenTree/company/urls.py @@ -20,7 +20,6 @@ company_detail_urls = [ url(r'^sales-orders/', views.CompanyDetail.as_view(template_name='company/sales_orders.html'), name='company-detail-sales-orders'), url(r'^notes/', views.CompanyNotes.as_view(), name='company-notes'), - url(r'^thumbnail/', views.CompanyImage.as_view(), name='company-image'), url(r'^thumb-download/', views.CompanyImageDownloadFromURL.as_view(), name='company-image-download'), # Any other URL diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index 5a887d9d38..8416ce2e3f 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -232,20 +232,6 @@ class CompanyImageDownloadFromURL(AjaxUpdateView): ) -class CompanyImage(AjaxUpdateView): - """ View for uploading an image for the Company """ - model = Company - ajax_template_name = 'modal_form.html' - ajax_form_title = _('Update Company Image') - form_class = CompanyImageForm - permission_required = 'company.change_company' - - def get_data(self): - return { - 'success': _('Updated company image'), - } - - class CompanyDelete(AjaxDeleteView): """ View for deleting a Company object """ diff --git a/InvenTree/templates/js/company.js b/InvenTree/templates/js/company.js index b069901ce1..96beb0a041 100644 --- a/InvenTree/templates/js/company.js +++ b/InvenTree/templates/js/company.js @@ -69,39 +69,6 @@ function createCompany(options={}) { } -// Launch form to create a new manufacturer part -function createManufacturerPart(options={}) { - - var fields = { - 'part': { - secondary: { - label: '{% trans "New Part" %}', - } - }, - 'manufacturer': { - secondary: { - label: '{% trans "New Manufacturer" %}', - } - }, - 'MPN': {}, - 'description': {}, - 'link': {}, - }; - - fields = Object.assign(fields, options.fields || {}); - - constructForm( - '{% url "api-manufacturer-part-list" %}', - { - fields: fields, - method: 'POST', - follow: true, - title: '{% trans "Add new Manufacturer Part" %}', - } - ); -} - - function loadCompanyTable(table, url, options={}) { /* * Load company listing data into specified table. diff --git a/InvenTree/templates/js/forms.js b/InvenTree/templates/js/forms.js index e96f9dee2a..535391d2e1 100644 --- a/InvenTree/templates/js/forms.js +++ b/InvenTree/templates/js/forms.js @@ -350,8 +350,8 @@ function constructFormBody(fields, options) { // Set the form title and button labels modalSetTitle(modal, options.title || '{% trans "Form Title" %}'); - modalSetSubmitText(options.submitText || '{% trans "Submit" %}'); - modalSetCloseText(options.cancelText || '{% trans "Cancel" %}'); + modalSetSubmitText(modal, options.submitText || '{% trans "Submit" %}'); + modalSetCloseText(modal, options.cancelText || '{% trans "Cancel" %}'); // Insert generated form content $(modal).find('.modal-form-content').html(html); @@ -387,8 +387,8 @@ function constructFormBody(fields, options) { */ function submitFormData(fields, options) { - // Data to be sent to the server - var data = {}; + // Form data to be uploaded to the server + var form_data = new FormData(); // Extract values for each field options.field_names.forEach(function(name) { @@ -399,16 +399,32 @@ function submitFormData(fields, options) { var value = getFormFieldValue(name, field, options); - data[name] = value; + // Handle file inputs + if (field.type == 'image upload' || field.type == 'file upload') { + + var field_el = $(options.modal).find(`#id_${name}`)[0]; + + var field_files = field_el.files; + + if (field_files.length > 0) { + // One file per field, please! + var file = field_files[0]; + + form_data.append(name, file); + } + } else { + // Normal field (not a file or image) + form_data.append(name, value); + } } else { console.log(`WARNING: Could not find field matching '${name}'`); } }); // Submit data - inventreePut( + inventreeFormDataUpload( options.url, - data, + form_data, { method: options.method, success: function(response, status) { @@ -464,6 +480,9 @@ function updateFieldValues(fields, options) { case 'related field': // TODO? break; + case 'file upload': + case 'image upload': + break; default: el.val(value); break; @@ -1017,6 +1036,10 @@ function constructInput(name, parameters, options) { case 'related field': func = constructRelatedFieldInput; break; + case 'image upload': + case 'file upload': + func = constructFileUploadInput; + break; default: // Unsupported field type! break; @@ -1101,7 +1124,6 @@ function constructCheckboxInput(name, parameters, options) { 'checkbox', parameters ); - } @@ -1193,6 +1215,26 @@ function constructRelatedFieldInput(name, parameters, options) { } +/* + * Construct a field for file upload + */ +function constructFileUploadInput(name, parameters, options) { + + var cls = 'clearablefileinput'; + + if (parameters.required) { + cls = 'fileinput'; + } + + return constructInputOptions( + name, + cls, + 'file', + parameters + ); +} + + /* * Construct a 'help text' div based on the field parameters *