Fixed templates, not sure why can't keep FileManager across forms... and also need to save form data

This commit is contained in:
eeintech 2021-05-04 17:35:27 -04:00
parent 64fb492b97
commit b4342d6203
6 changed files with 275 additions and 120 deletions

View File

@ -143,7 +143,7 @@ class MultiStepFormView(SessionWizardView):
try: try:
# Get template # Get template
template = self.form_steps_template[int(self.steps.current)] template = self.form_steps_template[self.steps.index]
except IndexError: except IndexError:
return self.template_name return self.template_name
@ -157,7 +157,7 @@ class MultiStepFormView(SessionWizardView):
# Get form description # Get form description
try: try:
description = self.form_steps_description[int(self.steps.current)] description = self.form_steps_description[self.steps.index]
except IndexError: except IndexError:
description = '' description = ''
# Add description to form steps # Add description to form steps

View File

@ -295,16 +295,14 @@ class UploadFile(forms.Form):
help_text=_('Select order file to upload'), help_text=_('Select order file to upload'),
) )
file_manager = None
def clean_file(self): def clean_file(self):
file = self.cleaned_data['file'] file = self.cleaned_data['file']
# Create a FileManager object - will perform initial data validation # Create a FileManager object - will perform initial data validation
# (and raise a ValidationError if there is something wrong with the file) # (and raise a ValidationError if there is something wrong with the file)
self.file_manager = FileManager(file=file, name='order') file_manager = FileManager(file=file, name='order')
return file return file_manager
class MatchField(forms.Form): class MatchField(forms.Form):

View File

@ -3,8 +3,7 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block form %} {% block form_alert %}
{% if missing_columns and missing_columns|length > 0 %} {% if missing_columns and missing_columns|length > 0 %}
<div class='alert alert-danger alert-block' role='alert'> <div class='alert alert-danger alert-block' role='alert'>
{% trans "Missing selections for the following required columns" %}: {% trans "Missing selections for the following required columns" %}:
@ -16,18 +15,17 @@
</ul> </ul>
</div> </div>
{% endif %} {% endif %}
{% endblock form_alert %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> {% block form_buttons_top %}
{% csrf_token %}
{% load crispy_forms_tags %}
{{ wizard.management_form }}
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button> <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
{% endif %} {% endif %}
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button> <button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
{% endblock form_buttons_top %}
<table class='table table-striped' style='margin-top: 12px'> {% block form_content %}
{{ wizard.form }}
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
@ -82,8 +80,7 @@
{% endwith %} {% endwith %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> {% endblock form_content %}
</form> {% block form_buttons_bottom %}
{% endblock form_buttons_bottom %}
{% endblock %}

View File

@ -3,26 +3,22 @@
{% load i18n %} {% load i18n %}
{% load static %} {% load static %}
{% block form %} {% block form_alert %}
{% if form_errors %} {% if form_errors %}
<div class='alert alert-danger alert-block' role='alert'> <div class='alert alert-danger alert-block' role='alert'>
{% trans "Errors exist in the submitted data" %} {% trans "Errors exist in the submitted data" %}
</div> </div>
{% endif %} {% endif %}
{% endblock form_alert %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> {% block form_buttons_top %}
{% csrf_token %}
{% load crispy_forms_tags %}
{{ wizard.management_form }}
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button> <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
{% endif %} {% endif %}
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button> <button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
{% csrf_token %} {% endblock form_buttons_top %}
<table class='table table-striped'> {% block form_content %}
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
@ -95,11 +91,10 @@
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> {% endblock form_content %}
</form> {% block form_buttons_bottom %}
{% endblock form_buttons_bottom %}
{% endblock %}
{% block js_ready %} {% block js_ready %}
{{ block.super }} {{ block.super }}

View File

@ -17,30 +17,31 @@
<p>{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }} <p>{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }}
{% if description %}- {{ description }}{% endif %}</p> {% if description %}- {{ description }}{% endif %}</p>
{% block form %} {% block form_alert %}
{% endblock form_alert %}
<form action="" method="post" enctype="multipart/form-data"> <form action="" method="post" class='js-modal-form' enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
<table>
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% crispy form %}
{% endfor %}
{% else %}
{% crispy wizard.form %}
{% endif %}
{% block form_buttons_top %}
{% endblock form_buttons_top %}
<table class='table table-striped' style='margin-top: 12px; margin-bottom: 0px'>
{{ wizard.management_form }}
{% block form_content %}
{% crispy wizard.form %}
{% endblock form_content %}
</table>
{% block form_buttons_bottom %}
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button> <button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
{% endif %} {% endif %}
<button type="submit" class="save btn btn-default">{% trans "Upload File" %}</button> <button type="submit" class="save btn btn-default">{% trans "Upload File" %}</button>
</form> </form>
</table> {% endblock form_buttons_bottom %}
{% endblock form %}
{% endblock details %} {% endblock details %}
{% block js_ready %} {% block js_ready %}

View File

@ -570,9 +570,9 @@ class PurchaseOrderUpload(MultiStepFormView):
''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) ''' ''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) '''
form_list = [ form_list = [
order_forms.UploadFile, ('upload', order_forms.UploadFile),
order_forms.MatchField, ('fields', order_forms.MatchField),
order_forms.MatchPart, ('parts', order_forms.MatchPart),
] ]
form_steps_template = [ form_steps_template = [
'order/order_wizard/po_upload.html', 'order/order_wizard/po_upload.html',
@ -608,26 +608,152 @@ class PurchaseOrderUpload(MultiStepFormView):
context.update({'rows': self.rows}) context.update({'rows': self.rows})
# print(f'{self.rows}') # print(f'{self.rows}')
print(f'{context=}')
return context return context
def process_step(self, form): def getTableDataFromForm(self, form_data):
print(f'{self.steps.current=} | {form.data}') """ Extract table cell data from form data.
return self.get_form_step_data(form) These data are used to maintain state between sessions.
# def get_all_cleaned_data(self): Table data keys are as follows:
# cleaned_data = super().get_all_cleaned_data()
# print(f'{self.steps.current=} | {cleaned_data}')
# return cleaned_data
# def get_form_step_data(self, form): col_name_<idx> - Column name at idx as provided in the uploaded file
# print(f'{self.steps.current=} | {form.data}') col_guess_<idx> - Column guess at idx as selected
# return form.data row_<x>_col<y> - Cell data as provided in the uploaded file
"""
if not self.file_manager:
print('Lost file manager...')
return
# Map the columns
self.column_names = {}
self.column_selections = {}
self.row_data = {}
for item in form_data:
value = form_data[item]
# Column names as passed as col_name_<idx> where idx is an integer
# Extract the column names
if item.startswith('col_name_'):
try:
col_id = int(item.replace('col_name_', ''))
except ValueError:
continue
col_name = value
self.column_names[col_id] = col_name
# Extract the column selections (in the 'select fields' view)
if item.startswith('col_guess_'):
try:
col_id = int(item.replace('col_guess_', ''))
except ValueError:
continue
col_name = value
self.column_selections[col_id] = value
# Extract the row data
if item.startswith('row_'):
# Item should be of the format row_<r>_col_<c>
s = item.split('_')
if len(s) < 4:
continue
# Ignore row/col IDs which are not correct numeric values
try:
row_id = int(s[1])
col_id = int(s[3])
except ValueError:
continue
if row_id not in self.row_data:
self.row_data[row_id] = {}
self.row_data[row_id][col_id] = value
self.col_ids = sorted(self.column_names.keys())
# Re-construct the data table
self.rows = []
for row_idx in sorted(self.row_data.keys()):
row = self.row_data[row_idx]
items = []
for col_idx in sorted(row.keys()):
value = row[col_idx]
items.append(value)
self.rows.append({
'index': row_idx,
'data': items,
'errors': {},
})
# Construct the column data
self.columns = []
# Track any duplicate column selections
self.duplicates = False
for col in self.col_ids:
if col in self.column_selections:
guess = self.column_selections[col]
else:
guess = None
header = ({
'name': self.column_names[col],
'guess': guess
})
if guess:
n = list(self.column_selections.values()).count(self.column_selections[col])
if n > 1:
header['duplicate'] = True
self.duplicates = True
self.columns.append(header)
# Are there any missing columns?
self.missing_columns = []
# Check that all required fields are present
for col in self.file_manager.REQUIRED_HEADERS:
if col not in self.column_selections.values():
self.missing_columns.append(col)
# Check that at least one of the part match field is present
part_match_found = False
for col in self.file_manager.PART_MATCH_HEADERS:
if col in self.column_selections.values():
part_match_found = True
break
# If not, notify user
if not part_match_found:
for col in self.file_manager.PART_MATCH_HEADERS:
self.missing_columns.append(col)
def handleFileUpload(self, form):
""" Process file upload and setup fields form """
def get_form_step_files(self, form):
# Check if user completed file upload # Check if user completed file upload
if self.steps.current == '0': if self.steps.current == 'upload':
# Retrieve FileManager instance from form # Copy FileManager instance from form
self.file_manager = form.file_manager self.file_manager = form.cleaned_data['file']
print(f'{self.file_manager=}')
# Setup FileManager for order upload # Setup FileManager for order upload
setup_valid = self.file_manager.setup() setup_valid = self.file_manager.setup()
if setup_valid: if setup_valid:
@ -637,13 +763,51 @@ class PurchaseOrderUpload(MultiStepFormView):
self.columns = self.file_manager.columns() self.columns = self.file_manager.columns()
self.rows = self.file_manager.rows() self.rows = self.file_manager.rows()
return form.files # Save FileManager
# self.storage.set_step_data('file', self.file_manager)
def post(self, request, *args, **kwargs): def handleFieldSelection(self, form_data):
""" Perform the various 'POST' requests required. """ Process field matching """
"""
print('Posting!') # Extract form data
return super().post(*args, **kwargs) self.getTableDataFromForm(form_data)
valid = len(self.missing_columns) == 0 and not self.duplicates
if not valid:
raise ValidationError('Invalid data')
def handlePartSelection(self, form_data):
pass
# print(f'{form_data=}')
# def process_step(self, form):
# print(f'{self.steps.current=} | {form.data}')
# return self.get_form_step_data(form)
def get_form_step_data(self, form):
print(f'{self.steps.current=}\n{form.data=}')
print(f'{self.file_manager=}')
# Process steps
if self.steps.current == 'upload':
self.handleFileUpload(form)
if self.steps.current == 'fields':
self.handleFieldSelection(form.data)
elif self.steps.current == 'parts':
self.handlePartSelection(form.data)
return form.data
# def get_all_cleaned_data(self):
# cleaned_data = super().get_all_cleaned_data()
# print(f'{self.steps.current=} | {cleaned_data}')
# return cleaned_data
# def post(self, request, *args, **kwargs):
# """ Perform the various 'POST' requests required.
# """
# print('Posting!')
# return super().post(*args, **kwargs)
def done(self, form_list, **kwargs): def done(self, form_list, **kwargs):
return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']})) return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']}))