summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2018-03-08 13:49:08 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2018-03-08 13:49:08 +0100
commit89c07c34691b71f5cf572134244fd7e272631013 (patch)
tree76533d9bc0562b05355eb79b01ee7ad71756f692
parentee4daac3b1d22e3ff3890efee015253f3e4b9e7a (diff)
downloadIshtar-89c07c34691b71f5cf572134244fd7e272631013.tar.bz2
Ishtar-89c07c34691b71f5cf572134244fd7e272631013.zip
Manage autorefresh for import page (refs #3951)
-rw-r--r--ishtar_common/context_processors.py3
-rw-r--r--ishtar_common/models_imports.py33
-rw-r--r--ishtar_common/static/js/ishtar.js48
-rw-r--r--ishtar_common/static/media/styles.css2
-rw-r--r--ishtar_common/templates/base.html7
-rw-r--r--ishtar_common/templates/ishtar/import_list.html71
-rw-r--r--ishtar_common/templates/ishtar/import_table.html81
-rw-r--r--ishtar_common/urls.py4
-rw-r--r--ishtar_common/utils.py13
-rw-r--r--ishtar_common/views.py24
10 files changed, 210 insertions, 76 deletions
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index 90817776f..7619363dc 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -52,7 +52,8 @@ def get_base_context(request):
# messages
dct['MESSAGES'] = []
- if 'messages' in request.session and request.session['messages']:
+ if not request.is_ajax() and 'messages' in request.session and \
+ request.session['messages']:
for message, message_type in request.session['messages']:
dct['MESSAGES'].append((message, message_type))
request.session['messages'] = []
diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py
index e0a144adc..b6b68d5a6 100644
--- a/ishtar_common/models_imports.py
+++ b/ishtar_common/models_imports.py
@@ -39,7 +39,8 @@ from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
from ishtar_common.utils import create_slug, \
- get_all_related_m2m_objects_with_model, put_session_message
+ get_all_related_m2m_objects_with_model, put_session_message, \
+ put_session_var, get_session_var
from ishtar_common.data_importer import Importer, ImportFormater, \
IntegerFormater, FloatFormater, UnicodeFormater, DateFormater, \
TypeFormater, YearFormater, StrToBoolean, FileFormater, InseeFormater
@@ -822,8 +823,8 @@ class Import(models.Model):
help_text=_(u'If set to true, do not overload existing values.'))
creation_date = models.DateTimeField(
_(u"Creation date"), auto_now_add=True, blank=True, null=True)
- end_date = models.DateTimeField(_(u"End date"), blank=True,
- null=True, editable=False)
+ end_date = models.DateTimeField(_(u"End date"), auto_now_add=True,
+ blank=True, null=True, editable=False)
seconds_remaining = models.IntegerField(
_(u"Remaining seconds"), blank=True, null=True, editable=False)
@@ -922,24 +923,29 @@ class Import(models.Model):
def initialize(self, user=None):
self.state = 'AP'
+ self.end_date = datetime.datetime.now()
self.save()
self.get_importer_instance().initialize(self.data_table,
user=user, output='db')
self.state = 'A'
+ self.end_date = datetime.datetime.now()
self.save()
def delayed_importation(self, session_key):
if not settings.USE_BACKGROUND_TASK:
return self.importation(session_key=session_key)
- put_session_message(session_key,
- unicode(_(u"Import added to the queue")),
- "warning")
+ put_session_message(
+ session_key,
+ unicode(_(u"Import {} added to the queue")).format(self.name),
+ "info")
self.state = 'IQ'
+ self.end_date = datetime.datetime.now()
self.save()
return delayed_import(self.pk, session_key)
def importation(self, session_key=None):
self.state = 'IP'
+ self.end_date = datetime.datetime.now()
self.save()
importer = self.get_importer_instance()
try:
@@ -952,6 +958,11 @@ class Import(models.Model):
self.imported_file),
"warning"
)
+ ids = get_session_var(session_key, 'current_import_id')
+ if not ids:
+ ids = []
+ ids.append(self.pk)
+ put_session_var(session_key, 'current_import_id', ids)
self.state = 'FE'
self.save()
return
@@ -970,26 +981,32 @@ class Import(models.Model):
ContentFile(importer.get_csv_errors().encode('utf-8'))
)
msg = unicode(_(u"Import {} finished with errors")).format(
- self.imported_file)
+ self.name)
msg_cls = "warning"
else:
self.state = 'F'
self.error_file = None
msg = unicode(_(u"Import {} finished with no errors")).format(
- self.imported_file)
+ self.name)
msg_cls = "primary"
if session_key:
put_session_message(session_key, msg, msg_cls)
+ ids = self.request.session['current_import_id'] \
+ if 'current_import_id' in self.request.session else []
+ ids.append(self.pk)
+ put_session_var(session_key, 'current_import_id', ids)
if importer.match_table:
match_file = filename + "_match_%s.csv" % now
self.match_file.save(
match_file,
ContentFile(importer.get_csv_matches().encode('utf-8'))
)
+ self.end_date = datetime.datetime.now()
self.save()
def archive(self):
self.state = 'AC'
+ self.end_date = datetime.datetime.now()
self.save()
def get_all_imported(self):
diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js
index fbf1ddc17..126373b94 100644
--- a/ishtar_common/static/js/ishtar.js
+++ b/ishtar_common/static/js/ishtar.js
@@ -188,6 +188,21 @@ function display_info(msg){
}, 5000);
}
+function add_message(message, message_type){
+ if (!message_type) message_type = 'info';
+
+ var html = $("#message_list").html();
+ html += '<div class="alert alert-' + message_type + ' alert-dismissible fade show"';
+ html += ' role="alert">';
+ html += message;
+ html += ' <button type="button" class="close" data-dismiss="alert"';
+ html += ' aria-label="Close">';
+ html += ' <span aria-hidden="true">&times;</span>';
+ html += ' </button>';
+ html += ' </div>';
+ $("#message_list").html(html);
+}
+
function load_opened_shortcut_menu(){
load_shortcut_menu(true);
}
@@ -257,6 +272,39 @@ $(document).on("click", '#to_top_arrow', function(){
$("html, body").animate({ scrollTop: 0}, 1000);
});
+var autorefresh = false;
+var autorefresh_message_start = "";
+var autorefresh_message_end = "";
+
+function startRefresh() {
+ if (!autorefresh) return;
+ autorefresh_link = $('#autorefreshpage').attr("data-link");
+ autorefresh_div_id = $('#autorefreshpage').attr("data-div");
+ $.get(autorefresh_link, function(data) {
+ $('#' + autorefresh_div_id).html(data);
+ });
+ setTimeout(startRefresh, 10000);
+}
+
+$(document).on("click", '#autorefreshpage', function(){
+ autorefresh_div_id = $('#autorefreshpage').attr("data-div");
+ if (!$(this).hasClass('disabled')) {
+ $(this).addClass('disabled');
+ autorefresh = false;
+ display_info(autorefresh_message_end);
+ $("#" + autorefresh_div_id).find('select').prop('disabled', false);
+ $("#" + autorefresh_div_id).find('input').prop('disabled', false);
+ } else {
+ $(this).removeClass('disabled');
+ autorefresh = true;
+ setTimeout(startRefresh, 10000);
+ display_info(autorefresh_message_start);
+ $("#" + autorefresh_div_id).find('select').prop('disabled', true);
+ $("#" + autorefresh_div_id).find('input').prop('disabled', true);
+
+ }
+});
+
$(document).on("click", '.check-all', function(){
$(this).closest('table'
).find('input:checkbox'
diff --git a/ishtar_common/static/media/styles.css b/ishtar_common/static/media/styles.css
index 37170a801..4ab36afe2 100644
--- a/ishtar_common/static/media/styles.css
+++ b/ishtar_common/static/media/styles.css
@@ -69,7 +69,7 @@ div.nav-button:hover{
opacity: 0.2;
}
-#to_bottom_arrow{
+#to_top_arrow{
bottom:84px;
}
diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html
index c11ae524e..bbf030409 100644
--- a/ishtar_common/templates/base.html
+++ b/ishtar_common/templates/base.html
@@ -40,6 +40,8 @@
var activate_own_search_msg = "{% trans 'Searches in the shortcut menu deal with only your items.' %}";
var YES = "{% trans 'yes' %}";
var NO = "{% trans 'no' %}";
+ var autorefresh_message_start = "{% trans 'Autorefresh start. The form is disabled.' %}";
+ var autorefresh_message_end = "{% trans 'Autorefresh end. The form is re-enabled.' %}";
</script>
{% endcompress %}
{% compress css %}
@@ -67,9 +69,6 @@
<p><strong class='lbl'>{{lbl}}{% trans ":"%}</strong> <span class='value'>{{value}}</span></p>
{% endfor %}
</div> {%endif%}
- <button class="nav-button btn btn-sm btn-secondary" id="to_bottom_arrow">
- <i class="fa fa-arrow-down" aria-hidden="true"></i>
- </button>
<button class="nav-button btn btn-sm btn-secondary" id="to_top_arrow">
<i class="fa fa-arrow-up" aria-hidden="true"></i>
</button>
@@ -97,6 +96,7 @@
<div id="window_wrapper">
<div id="window" role="tablist"></div>
</div>
+ <div id="message_list">
{% if MESSAGES %}{% for message, message_type in MESSAGES %}
<div class="alert alert-{{message_type}} alert-dismissible fade show"
role="alert">
@@ -107,6 +107,7 @@
</button>
</div>
{% endfor %}{% endif %}
+ </div>
{% if warnings %}{% for warning in warnings %}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
{{warning}}<button type="button" class="close" data-dismiss="alert" aria-label="Close">
diff --git a/ishtar_common/templates/ishtar/import_list.html b/ishtar_common/templates/ishtar/import_list.html
index 4ac8a79be..a5fa34660 100644
--- a/ishtar_common/templates/ishtar/import_list.html
+++ b/ishtar_common/templates/ishtar/import_list.html
@@ -2,71 +2,20 @@
{% load i18n inline_formset %}
{% block pre_container %}
+<button id="autorefreshpage"
+ class="nav-button btn btn-sm btn-secondary disabled"
+ data-link="{% url 'current_imports_table' %}"
+ data-div="import-container"
+ title="{% trans 'Autorefresh the table (useful when waiting for an import result)' %}">
+ <i class="fa fa-refresh" aria-hidden="true"></i>
+</button>
+
<form action="." method="post">{% csrf_token %}
{% endblock %}
{% block content %}
-<h2>{{page_name}}</h2>
-<div class='form'>
-{% if not object_list %}
-<p>{% trans "No pending imports." %}</p>
-{% else %}
-<table class="table table-striped">
-<tr>
- <th>{% trans "Name" %}</th>
- <th>{% trans "Type" %}</th>
- <th>{% trans "File" context "file" %}</th>
- <th>{% trans "Creation" %}</th>
- <th>{% trans "Status" %}</th>
- <th>{% trans "Action" %}</th>
- <th>{% trans "Unmatched items" %}</th>
- <th>{% trans "Error" %}</th>
- <th>{% trans "Control" %}</th>
- <th>{% trans "Match" %}</th>
-</tr>
-{% for import in object_list %}
-<tr>
- <td>
- {{import.name|default:"-"}}
- </td>
- <td>
- {{import.importer_type}}
- </td>
- <td>
- <a href='{{import.imported_file.url}}'>{% trans "Source file" %}</a>
- </td>
- <td>
- {{import.creation_date}} ({{import.user}})
- </td>
- <td>
- {{import.status}}
- </td>
- <td>
- <select name='import-action-{{import.pk}}'>
- <option value=''>--------</option>
- {% for action, lbl in import.get_actions %}
- <option value='{{action}}'>{{lbl}}</option>
- {% endfor%}
- </select>
- </td>
- <td>
- {% if import.need_matching %}
- <a href='{% url "import_link_unmatched" import.pk %}'>{% trans "Match"%}</a>
- {% endif %}
- </td>
- <td style="white-space: nowrap;">{% if import.error_file %}
- <i class="text-danger fa fa-exclamation-triangle" aria-hidden="true"></i> <a href='{{import.error_file.url}}'>{% trans "File" context "not a directory" %}</a>
- {% endif %}</td>
- <td>{% if import.result_file %}
- <a href='{{import.result_file.url}}'>{% trans "File" context "not a directory" %}</a>
- {% endif %}</td>
- <td>{% if import.match_file %}
- <a href='{{import.match_file.url}}'>{% trans "File" context "not a directory" %}</a>
- {% endif %}</td>
-</tr>
-{% endfor %}
-</table>
-{% endif %}
+<div id="import-container">
+ {% include "ishtar/import_table.html" %}
</div>
{% endblock %}
diff --git a/ishtar_common/templates/ishtar/import_table.html b/ishtar_common/templates/ishtar/import_table.html
new file mode 100644
index 000000000..95940a4ab
--- /dev/null
+++ b/ishtar_common/templates/ishtar/import_table.html
@@ -0,0 +1,81 @@
+{% load i18n inline_formset %}
+<script type="text/javascript">
+var html = $("#message_list").html();
+{% if MESSAGES and AJAX %}{% for message, message_type in MESSAGES %}
+html += '<div class="alert alert-{{message_type}} alert-dismissible fade show"';
+html += ' role="alert">';
+html += ' {{message}}';
+html += ' <button type="button" class="close" data-dismiss="alert"';
+html += ' aria-label="Close">';
+html += ' <span aria-hidden="true">&times;</span>';
+html += ' </button>';
+html += ' </div>';
+{% endfor %}{% endif %}
+$("#message_list").html(html);
+
+$("#import-list").find('select').prop('disabled', true);
+$("#import-list").find('input').prop('disabled', true);
+
+</script>
+<h2>{{page_name}}</h2>
+<div class='form' id="import-list">
+ {% if not object_list %}
+ <p>{% trans "No pending imports." %}</p>
+ {% else %}
+ <table class="table table-striped">
+ <tr>
+ <th>{% trans "Name" %}</th>
+ <th>{% trans "Type" %}</th>
+ <th>{% trans "File" context "file" %}</th>
+ <th>{% trans "Creation" %}</th>
+ <th>{% trans "Status" %}</th>
+ <th>{% trans "Action" %}</th>
+ <th>{% trans "Unmatched items" %}</th>
+ <th>{% trans "Error" %}</th>
+ <th>{% trans "Control" %}</th>
+ <th>{% trans "Match" %}</th>
+ </tr>
+ {% for import in object_list %}
+ <tr{% if import.pk in refreshed_pks %} class='bg-info'{% endif %}>
+ <td>
+ {{import.name|default:"-"}}
+ </td>
+ <td>
+ {{import.importer_type}}
+ </td>
+ <td>
+ <a href='{{import.imported_file.url}}'>{% trans "Source file" %}</a>
+ </td>
+ <td>
+ {{import.creation_date}} ({{import.user}})
+ </td>
+ <td>
+ {{import.status}}
+ </td>
+ <td>
+ <select name='import-action-{{import.pk}}'>
+ <option value=''>--------</option>
+ {% for action, lbl in import.get_actions %}
+ <option value='{{action}}'>{{lbl}}</option>
+ {% endfor%}
+ </select>
+ </td>
+ <td>
+ {% if import.need_matching %}
+ <a href='{% url "import_link_unmatched" import.pk %}'>{% trans "Match"%}</a>
+ {% endif %}
+ </td>
+ <td style="white-space: nowrap;">{% if import.error_file %}
+ <i class="text-danger fa fa-exclamation-triangle" aria-hidden="true"></i> <a href='{{import.error_file.url}}'>{% trans "File" context "not a directory" %}</a>
+ {% endif %}</td>
+ <td>{% if import.result_file %}
+ <a href='{{import.result_file.url}}'>{% trans "File" context "not a directory" %}</a>
+ {% endif %}</td>
+ <td>{% if import.match_file %}
+ <a href='{{import.match_file.url}}'>{% trans "File" context "not a directory" %}</a>
+ {% endif %}</td>
+ </tr>
+ {% endfor %}
+ </table>
+ {% endif %}
+</div>
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index ce3386363..5aa3bb409 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -105,6 +105,10 @@ urlpatterns = [
check_rights(['change_import'])(
views.ImportListView.as_view()),
name='current_imports'),
+ url(r'^import-list-table/$',
+ check_rights(['change_import'])(
+ views.ImportListTableView.as_view()),
+ name='current_imports_table'),
url(r'^import-list-old/$',
check_rights(['change_import'])(
views.ImportOldListView.as_view()),
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index 675b840ca..948604c16 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -383,3 +383,16 @@ def put_session_message(session_key, message, message_type):
messages.append((message, message_type))
session['messages'] = messages
session.save()
+
+
+def put_session_var(session_key, key, value):
+ session = SessionStore(session_key=session_key)
+ session[key] = value
+ session.save()
+
+
+def get_session_var(session_key, key):
+ session = SessionStore(session_key=session_key)
+ if key not in session:
+ return
+ return session[key]
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 66642090f..c2b292ed4 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -1789,9 +1789,9 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
def get_queryset(self):
q = self.model.objects.exclude(state='AC')
if self.request.user.is_superuser:
- return q.order_by('-creation_date')
+ return q.order_by('-creation_date').order_by('-end_date')
user = models.IshtarUser.objects.get(pk=self.request.user.pk)
- return q.filter(user=user).order_by('-creation_date')
+ return q.filter(user=user).order_by('-end_date')
def post(self, request, *args, **kwargs):
for field in request.POST:
@@ -1824,6 +1824,26 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
return HttpResponseRedirect(reverse(self.current_url))
+class ImportListTableView(ImportListView):
+ template_name = 'ishtar/import_table.html'
+ current_url = 'current_imports_table'
+
+ def get_context_data(self, **kwargs):
+ dct = super(ImportListTableView, self).get_context_data(**kwargs)
+ dct['AJAX'] = True
+ dct['MESSAGES'] = []
+ request = self.request
+ if 'messages' in request.session and \
+ request.session['messages']:
+ for message, message_type in request.session['messages']:
+ dct['MESSAGES'].append((message, message_type))
+ request.session['messages'] = []
+ if 'current_import_id' in request.session and \
+ request.session['current_import_id']:
+ dct['refreshed_pks'] = request.session.pop('current_import_id')
+ return dct
+
+
class ImportOldListView(ImportListView):
page_name = _(u"Old imports")
current_url = 'old_imports'