Skip to content

Commit

Permalink
Merge pull request #71 from saritasa-nest/feature/improve-admin-progr…
Browse files Browse the repository at this point in the history
…ess-bar

Improve html templates for admin pages
  • Loading branch information
Eg0ra authored Nov 29, 2024
2 parents 78cb390 + 596658b commit f04c990
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 147 deletions.
12 changes: 12 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
=======
History
=======
UNRELEASED
------------------
* Fix progress bar on changeview for ImportJob and ExportJob
* Improve celery-import-result page

* Add displaying resources for import form
* Fix autofill `Format` by file extension
* Add `Totals` section
* Remove extra loop if errors in input file (https://github.com/saritasa-nest/django-import-export-extensions/issues/74)

* Fixed display of progress bar when task is waiting to run (https://github.com/saritasa-nest/django-import-export-extensions/issues/68)
* Improve progress bar style (https://github.com/saritasa-nest/django-import-export-extensions/issues/72)

1.0.1 (2024-11-08)
------------------
Expand Down
47 changes: 34 additions & 13 deletions import_export_extensions/admin/mixins/import_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from import_export import admin as import_export_admin
from import_export import mixins as import_export_mixins
from import_export import resources as import_export_resources

from ... import models
from ..forms import ForceImportForm
Expand Down Expand Up @@ -170,24 +171,16 @@ def celery_import_action(
)

# GET: display Import Form
resources = [
resource_class(**resource_kwargs)
for resource_class in resource_classes
]

context.update(self.admin_site.each_context(request))

context["title"] = _("Import")
context["form"] = form
context["opts"] = self.model_info.meta
context["media"] = self.media + form.media
context["fields_list"] = [
(
resource.get_display_name(),
[f.column_name for f in resource.get_user_visible_fields()],
)
for resource in resources
]
context["fields_list"] = self._get_fields_list_for_resources(
resource_classes=resource_classes,
resource_kwargs=resource_kwargs,
)

request.current_app = self.admin_site.name
return TemplateResponse(
Expand Down Expand Up @@ -282,9 +275,16 @@ def celery_import_job_results_view(
context["confirm_form"] = Form()
else:
# display import form
resource_classes = self.get_import_resource_classes(request)
resource_kwargs = self.get_import_resource_kwargs(request)

context["import_form"] = ForceImportForm(
formats=self.get_import_formats(),
resources=self.get_import_resource_classes(request),
resources=resource_classes,
)
context["fields_list"] = self._get_fields_list_for_resources(
resource_classes=resource_classes,
resource_kwargs=resource_kwargs,
)

context.update(self.admin_site.each_context(request))
Expand Down Expand Up @@ -376,6 +376,27 @@ def _redirect_to_results_page(

return HttpResponseRedirect(redirect_to=url)

def _get_fields_list_for_resources(
self,
resource_classes: list[type[import_export_resources.ModelResource]],
resource_kwargs,
) -> list[tuple[str, list[str]]]:
"""Get fields list for resource classes."""
resources = [
resource_class(**resource_kwargs)
for resource_class in resource_classes
]
return [
(
resource.get_display_name(),
[
field.column_name
for field in resource.get_user_visible_fields()
],
)
for resource in resources
]

def changelist_view(
self,
request: WSGIRequest,
Expand Down
14 changes: 4 additions & 10 deletions import_export_extensions/admin/widgets.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

from django import forms
from django.template.loader import render_to_string


class ProgressBarWidget(forms.Widget):
Expand All @@ -9,6 +10,8 @@ class ProgressBarWidget(forms.Widget):
"""

template_name = "admin/import_export_extensions/progress_bar.html"

def __init__(self, *args, **kwargs):
"""Get ``ImportJob`` or ``ExportJob`` instance from kwargs.
Expand All @@ -28,16 +31,7 @@ def render(self, *args, **kwargs) -> str:
to send GET requests.
"""
progress_bar = f"""
<progress
value="0"
max="100"
id="progress-bar"
data-url="{self.url}">
</progress>
"""

return progress_bar
return render_to_string(self.template_name, {"job_url": self.url})

class Media:
"""Class with custom assets for widget."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ progress {
width: 100%;
-webkit-appearance: none;
border: none;
position:relative;
position: relative;
}
progress:before {
content: attr(data-label);
Expand All @@ -24,8 +24,13 @@ progress::-webkit-progress-bar {
background-color: var(--breadcrumbs-fg);
}
progress::-webkit-progress-value {
background-color: var(--breadcrumbs-bg);
background-color: var(--primary);
}
progress::-moz-progress-bar {
background-color: var(--breadcrumbs-bg);
}

html[data-theme="dark"]
progress::-webkit-progress-bar {
background-color: var(--darkened-bg);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
{% endblock %}

{% block breadcrumbs_last %}
<a href="{% url opts|admin_urlname:'export' %}?{{request.GET.urlencode}}">
<a href="{% url opts|admin_urlname:'export' %}?{{ request.GET.urlencode }}">
{% trans "Export" %}
</a>
&rsaquo; {% trans "Export results" %}
Expand All @@ -40,7 +40,7 @@ <h2>
<h2>
{% trans "You can download exported data with following link" %}
</h2>
<a href="{{ export_job.data_file.url }}" id="data_file">Download export data</a>
<a href="{{ export_job.data_file.url }}" id="data_file">{% trans "Download export data" %}</a>
{% endif %}
{% endblock %}
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

{% comment %}
Template to show status of export job.
Similar to job's admin page.

{% endcomment %}

{% block extrastyle %}
Expand All @@ -24,7 +22,7 @@


{% block breadcrumbs_last %}
<a href="{% url opts|admin_urlname:'export' %}?{{request.GET.urlencode}}">
<a href="{% url opts|admin_urlname:'export' %}?{{ request.GET.urlencode }}">
{% trans "Export" %}
</a>
&rsaquo;
Expand All @@ -35,37 +33,14 @@
<div>
<fieldset class="module aligned collapse">
<div class="form-row">
<label>Status</label><p id="current-job-status">{{ export_job.export_status|title }}</p>
<label>{% trans "Status" %}</label>
<p id="current-job-status">{{ export_job.export_status|title }}</p>
</div>

{% if export_job.export_status not in export_job.export_finished_statuses %}
<div class="form-row">
<label>Progress</label>
<p id="progress_bar_html">
<progress max="100" id="progress-bar" data-url="{{ export_job_url }}"></progress>
</p>
</div>
{% endif %}

{% if export_job.export_status == export_job.ExportStatus.EXPORTED %}
<div class="form-row">
<label>Totals</label>
<p>
{% for total, stat in export_job.result.totals.items %}
{{ total.title }}:&nbsp; <b>{{ stat }}</b><br>
{% endfor %}
</p>
</div>
{% endif %}

{% if export_job.export_status == export_job.ExportStatus.EXPORT_ERROR %}
<div class="form-row">
<label>Error</label>
<p><b>{{ export_job.error_message }}</b></p>
</div>
<div class="form-row">
<label>Traceback</label>
{{ export_job.traceback | linebreaks }}
<label>{% trans "Progress" %}</label>
{% include "admin/import_export_extensions/progress_bar.html" with job_url=export_job_url %}
</div>
{% endif %}
</fieldset>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}"></script>
<script type="text/javascript" src="{% static 'import_export_extensions/js/admin/admin.js' %}"></script>
<link rel="stylesheet" type="text/css" href="{% static "import_export_extensions/css/admin/import_result_diff.css" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "import_export/import.css"" %}"/>
<link rel="stylesheet" type="text/css" href="{% static "import_export/import.css" %}"/>
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{% if confirm_form %}
{{ confirm_form.media }}
{% else %}
{{ import_form.media }}
{% endif %}
{% endblock %}


{% block breadcrumbs_last %}
<a href="{% url opts|admin_urlname:'import' %}?{{request.GET.urlencode}}">
<a href="{% url opts|admin_urlname:'import' %}?{{ request.GET.urlencode }}">
{% trans "Import" %}
</a>
&rsaquo; {% trans "Import results" %}
Expand Down Expand Up @@ -50,6 +56,8 @@
<form action="{% url opts|admin_urlname:"import" %}?{{ request.GET.urlencode }}" method="post" enctype="multipart/form-data">
{% csrf_token %}

{% include "admin/import_export/resource_fields_list.html" with import_or_export="import" %}

<fieldset class="module aligned">
{% for field in import_form %}
<div class="form-row">
Expand Down Expand Up @@ -99,62 +107,66 @@ <h2>{% trans "Errors" %}</h2>
</li>
{% endfor %}
{% endfor %}
{% for invalid_row in result.invalid_rows %}
<h2>{% trans "Some rows failed to validate" %}</h2>
<h2>{% trans "Some rows failed to validate" %}</h2>

<p>{% trans "Please correct these errors in your data where possible, then reupload it using the form above." %}</p>
<table class="import-preview">
<thead>
<p>{% trans "Please correct these errors in your data where possible, then reupload it using the form above." %}</p>
<table class="import-preview">
<thead>
<tr>
<th>{% trans "Row" %}</th>
<th>{% trans "Errors" %}</th>
{% for field in result.diff_headers %}
<th>{{ field }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in result.invalid_rows %}
<tr>
<th>{% trans "Row" %}</th>
<th>{% trans "Errors" %}</th>
{% for field in result.diff_headers %}
<th>{{ field }}</th>
<td>{{ row.number }} </td>
<td class="errors">
<span class="validation-error-count">{{ row.error_count }}</span>
<div class="validation-error-container">
<ul class="validation-error-list">
{% for field_name, error_list in row.field_specific_errors.items %}
<li>
<span class="validation-error-field-label">{{ field_name }}</span>
<ul>
{% for error in error_list %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
{% if row.non_field_specific_errors %}
<li>
<span class="validation-error-field-label">{% trans "Non field specific" %}</span>
<ul>
{% for error in row.non_field_specific_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
</div>
</td>
{% for field in row.values %}
<td>{{ field }}</td>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in result.invalid_rows %}
<tr>
<td>{{ row.number }} </td>
<td class="errors">
<span class="validation-error-count">{{ row.error_count }}</span>
<div class="validation-error-container">
<ul class="validation-error-list">
{% for field_name, error_list in row.field_specific_errors.items %}
<li>
<span class="validation-error-field-label">{{ field_name }}</span>
<ul>
{% for error in error_list %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
{% if row.non_field_specific_errors %}
<li>
<span class="validation-error-field-label">{% trans "Non field specific" %}</span>
<ul>
{% for error in row.non_field_specific_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
</div>
</td>
{% for field in row.values %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endfor %}
</tbody>
</table>
</ul>
{% endif %}
{% if import_job.import_status in import_job.success_statuses %}
<h2>{% trans "Totals" %}</h2>
<div>
{% for total, stat in import_job.result.totals.items %}
{{ total.title }}: <b>{{ stat }}</b><br>
{% endfor %}
</div>
<h2>
{% if import_job.import_status == "PARSED" %}
{% trans "These elements will be imported successfully" %}
Expand Down
Loading

0 comments on commit f04c990

Please sign in to comment.