mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
templates and FileManagement config
This commit is contained in:
parent
307a097ab4
commit
8effdffe6f
@ -109,6 +109,27 @@ class FileManager:
|
|||||||
# Update headers
|
# Update headers
|
||||||
self.update_headers()
|
self.update_headers()
|
||||||
|
|
||||||
|
if self.name == 'part':
|
||||||
|
self.REQUIRED_HEADERS = [
|
||||||
|
'Name',
|
||||||
|
'Description',
|
||||||
|
]
|
||||||
|
|
||||||
|
self.OPTIONAL_HEADERS = [
|
||||||
|
'Keywords',
|
||||||
|
'IPN',
|
||||||
|
'Revision',
|
||||||
|
'Link',
|
||||||
|
'default_expiry',
|
||||||
|
'minimum_stock',
|
||||||
|
'Units',
|
||||||
|
'Notes',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Update headers
|
||||||
|
self.update_headers()
|
||||||
|
|
||||||
|
|
||||||
def guess_header(self, header, threshold=80):
|
def guess_header(self, header, threshold=80):
|
||||||
""" Try to match a header (from the file) to a list of known headers
|
""" Try to match a header (from the file) to a list of known headers
|
||||||
|
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
{% extends "part/import_wizard/part_upload.html" %}
|
||||||
|
{% load inventree_extras %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block form_alert %}
|
||||||
|
{% if missing_columns and missing_columns|length > 0 %}
|
||||||
|
<div class='alert alert-danger alert-block' role='alert'>
|
||||||
|
{% trans "Missing selections for the following required columns" %}:
|
||||||
|
<br>
|
||||||
|
<ul>
|
||||||
|
{% for col in missing_columns %}
|
||||||
|
<li>{{ col }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if duplicates and duplicates|length > 0 %}
|
||||||
|
<div class='alert alert-danger alert-block' role='alert'>
|
||||||
|
{% trans "Duplicate selections found, see below. Fix them then retry submitting." %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock form_alert %}
|
||||||
|
|
||||||
|
{% block form_buttons_top %}
|
||||||
|
{% if wizard.steps.prev %}
|
||||||
|
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
|
||||||
|
{% endblock form_buttons_top %}
|
||||||
|
|
||||||
|
{% block form_content %}
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "File Fields" %}</th>
|
||||||
|
<th></th>
|
||||||
|
{% for col in form %}
|
||||||
|
<th>
|
||||||
|
<div>
|
||||||
|
<input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
|
||||||
|
{{ col.name }}
|
||||||
|
<button class='btn btn-default btn-remove' onClick='removeColFromBomWizard()' id='del_col_{{ forloop.counter0 }}' style='display: inline; float: right;' title='{% trans "Remove column" %}'>
|
||||||
|
<span col_id='{{ forloop.counter0 }}' class='fas fa-trash-alt icon-red'></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{% trans "Match Fields" %}</td>
|
||||||
|
<td></td>
|
||||||
|
{% for col in form %}
|
||||||
|
<td>
|
||||||
|
{{ col }}
|
||||||
|
{% for duplicate in duplicates %}
|
||||||
|
{% if duplicate == col.name %}
|
||||||
|
<div class='alert alert-danger alert-block text-center' role='alert' style='padding:2px; margin-top:6px; margin-bottom:2px'>
|
||||||
|
<b>{% trans "Duplicate selection" %}</b>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% for row in rows %}
|
||||||
|
{% with forloop.counter as row_index %}
|
||||||
|
<tr>
|
||||||
|
<td style='width: 32px;'>
|
||||||
|
<button class='btn btn-default btn-remove' onClick='removeRowFromBomWizard()' id='del_row_{{ row_index }}' style='display: inline; float: left;' title='{% trans "Remove row" %}'>
|
||||||
|
<span row_id='{{ row_index }}' class='fas fa-trash-alt icon-red'></span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td style='text-align: left;'>{{ row_index }}</td>
|
||||||
|
{% for item in row.data %}
|
||||||
|
<td>
|
||||||
|
<input type='hidden' name='row_{{ row_index }}_col_{{ forloop.counter0 }}' value='{{ item }}'/>
|
||||||
|
{{ item }}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endwith %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
{% endblock form_content %}
|
||||||
|
|
||||||
|
{% block form_buttons_bottom %}
|
||||||
|
{% endblock form_buttons_bottom %}
|
||||||
|
|
||||||
|
{% block js_ready %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
$('.fieldselect').select2({
|
||||||
|
width: '100%',
|
||||||
|
matcher: partialMatcher,
|
||||||
|
});
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -0,0 +1,90 @@
|
|||||||
|
{% extends "part/import_wizard/part_upload.html" %}
|
||||||
|
{% load inventree_extras %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block form_alert %}
|
||||||
|
{% if form.errors %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form_errors %}
|
||||||
|
<div class='alert alert-danger alert-block' role='alert'>
|
||||||
|
{% trans "Errors exist in the submitted data" %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock form_alert %}
|
||||||
|
|
||||||
|
{% block form_buttons_top %}
|
||||||
|
{% if wizard.steps.prev %}
|
||||||
|
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
|
||||||
|
{% endblock form_buttons_top %}
|
||||||
|
|
||||||
|
{% block form_content %}
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>{% trans "Row" %}</th>
|
||||||
|
{% for col in columns %}
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
|
||||||
|
<input type='hidden' name='col_guess_{{ forloop.counter0 }}' value='{{ col.guess }}'/>
|
||||||
|
{% if col.guess %}
|
||||||
|
{{ col.guess }}
|
||||||
|
{% else %}
|
||||||
|
{{ col.name }}
|
||||||
|
{% endif %}
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr></tr> {% comment %} Dummy row for javascript del_row method {% endcomment %}
|
||||||
|
{% for row in rows %}
|
||||||
|
<tr {% if row.errors %} style='background: #ffeaea;'{% endif %} part-select='#select_part_{{ row.index }}'>
|
||||||
|
<td>
|
||||||
|
<button class='btn btn-default btn-remove' onClick='removeRowFromBomWizard()' id='del_row_{{ row.index }}' style='display: inline; float: right;' title='{% trans "Remove row" %}'>
|
||||||
|
<span row_id='{{ row.index }}' class='fas fa-trash-alt icon-red'></span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% add row.index 1 %}
|
||||||
|
</td>
|
||||||
|
{% for item in row.data %}
|
||||||
|
<td>
|
||||||
|
{% if item.column.guess %}
|
||||||
|
{% with row_name=item.column.guess|lower %}
|
||||||
|
{% for field in form.visible_fields %}
|
||||||
|
{% if field.name == row|keyvalue:row_name %}
|
||||||
|
{{ field }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
{% else %}
|
||||||
|
{{ item.cell }}
|
||||||
|
{% endif %}
|
||||||
|
<input type='hidden' name='row_{{ row.index }}_col_{{ forloop.counter0 }}' value='{{ item.cell }}'/>
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
{% endblock form_content %}
|
||||||
|
|
||||||
|
{% block form_buttons_bottom %}
|
||||||
|
{% endblock form_buttons_bottom %}
|
||||||
|
|
||||||
|
{% block js_ready %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
$('.bomselect').select2({
|
||||||
|
dropdownAutoWidth: true,
|
||||||
|
matcher: partialMatcher,
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.currencyselect').select2({
|
||||||
|
dropdownAutoWidth: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
{% endblock %}
|
61
InvenTree/part/templates/part/import_wizard/part_upload.html
Normal file
61
InvenTree/part/templates/part/import_wizard/part_upload.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{% extends "part/category.html" %}
|
||||||
|
{% load inventree_extras %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block menubar %}
|
||||||
|
{% include 'part/category_navbar.html' with tab='import' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block category_content %}
|
||||||
|
<div class='panel panel-default panel-inventree'>
|
||||||
|
<div class='panel-heading'>
|
||||||
|
<h4>
|
||||||
|
{% trans "Import Parts from File" %}
|
||||||
|
{{ wizard.form.media }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class='panel-content'>
|
||||||
|
{% if roles.part.change %}
|
||||||
|
|
||||||
|
<p>{% blocktrans with step=wizard.steps.step1 count=wizard.steps.count %}Step {{step}} of {{count}}{% endblocktrans %}
|
||||||
|
{% if description %}- {{ description }}{% endif %}</p>
|
||||||
|
|
||||||
|
{% block form_alert %}
|
||||||
|
{% endblock form_alert %}
|
||||||
|
|
||||||
|
<form action="" method="post" class='js-modal-form' enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% 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 %}
|
||||||
|
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" class="save btn btn-default">{% trans "Upload File" %}</button>
|
||||||
|
</form>
|
||||||
|
{% endblock form_buttons_bottom %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<div class='alert alert-danger alert-block' role='alert'>
|
||||||
|
{% trans "Unsuffitient privileges." %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js_ready %}
|
||||||
|
{{ block.super }}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -722,6 +722,31 @@ class PartCreate(AjaxCreateView):
|
|||||||
class PartImport(FileManagementFormView):
|
class PartImport(FileManagementFormView):
|
||||||
''' Part: Upload file, match to fields and import parts(using multi-Step form) '''
|
''' Part: Upload file, match to fields and import parts(using multi-Step form) '''
|
||||||
|
|
||||||
|
name = 'part'
|
||||||
|
form_steps_template = [
|
||||||
|
'part/import_wizard/part_upload.html',
|
||||||
|
'part/import_wizard/match_fields.html',
|
||||||
|
'part/import_wizard/match_references.html',
|
||||||
|
]
|
||||||
|
form_steps_description = [
|
||||||
|
_("Upload File"),
|
||||||
|
_("Match Fields"),
|
||||||
|
_("Match References"),
|
||||||
|
]
|
||||||
|
|
||||||
|
form_field_map = {
|
||||||
|
'name': 'name',
|
||||||
|
'description': 'description',
|
||||||
|
'keywords': 'keywords',
|
||||||
|
'IPN': 'IPN',
|
||||||
|
'revision': 'revision',
|
||||||
|
'link': 'link',
|
||||||
|
'default_expiry': 'default_expiry',
|
||||||
|
'minimum_stock': 'minimum_stock',
|
||||||
|
'units': 'units',
|
||||||
|
'notes': 'notes',
|
||||||
|
}
|
||||||
|
|
||||||
class PartNotes(UpdateView):
|
class PartNotes(UpdateView):
|
||||||
""" View for editing the 'notes' field of a Part object.
|
""" View for editing the 'notes' field of a Part object.
|
||||||
Presents a live markdown editor.
|
Presents a live markdown editor.
|
||||||
|
Loading…
Reference in New Issue
Block a user