Skip to content
Snippets Groups Projects
Commit b13bd90e authored by HeJ's avatar HeJ
Browse files

Merge branch 'fix/schedule_import_backend' into 'develop'

minor fixes for schedule import backend

See merge request hub/hub!963
parents b337e38e a6380ea0
No related branches found
No related tags found
No related merge requests found
...@@ -21,22 +21,57 @@ ...@@ -21,22 +21,57 @@
{% if object.errors %} {% if object.errors %}
<div class="card mb-3 border-warning"> <div class="card mb-3 border-warning">
<div class="card-header bg-warning text-white"> <div class="card-header text-bg-warning">
Errors Errors
</div> </div>
<div class="card-body"> <table class="card-body table table-sm table-hover">
<code><pre>{{ object.errors|json_indent }}</pre></code> <thead>
</div> <tr><th>Type</th><th>Action</th><th>Source ID</th><th>Local ID</th><th>Message</th></tr>
</thead>
<tbody>
{% for error in object.errors %}
<tr>
<td>{{ error.type|default:"???" }}</td>
<td>{{ error.action|default:"???" }}</td>
<td>{{ error.source_id|default:"-/-" }}</td>
<td>{{ error.local_id|default:"-/-" }}</td>
<td>{{ error.message }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
{%endif%} {%endif%}
<div class="card mb-3{% if object.data %} border-primary{% endif %}"> {% if activity %}
<div class="card-header{% if object.data %} bg-primary text-white{% endif %}"> <div class="card mb-3 border-primary">
Data <div class="card-header text-bg-primary">
Activity
</div> </div>
<div class="card-body"> <table class="card-body table table-sm table-hover">
<code><pre>{{ object.data|json_indent }}</pre></code> <thead>
<tr><th>Type</th><th>Action</th><th>Source ID</th><th>Local ID</th></tr>
</thead>
<tbody>
{% for item in activity %}
<tr{% if item.action != "seen" %} class="fw-bold"{% endif %}>
<td class="{% if item.action == "seen" %}text-muted{% elif item.action == "error" %}text-danger{% endif %}">{{ item.type|default:"???" }}</td>
<td class="{% if item.action == "seen" %}text-muted{% elif item.action == "error" %}text-danger{% endif %}">{{ item.action|default:"???" }}</td>
<td class="{% if item.action == "seen" %}text-muted{% elif item.action == "error" %}text-danger{% endif %}">{{ item.source_id|default:"-/-" }}</td>
<td class="{% if item.action == "seen" %}text-muted{% elif item.action == "error" %}text-danger{% endif %}">{{ item.local_id|default:"-/-" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
{% endif %}
{% if object.data %}
<div class="text-center">
<a href="{% url 'backoffice:schedulesourceimport-detail-data' pk=object.pk %}" class="btn btn-outline-primary">
data as JSON
</a>
</div> </div>
{% endif %}
{% endblock %} {% endblock %}
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
{% for source in sources %} {% for source in sources %}
{% with source.latest_import as latest %} {% with source.latest_import as latest %}
<div class="col"> <div class="col">
<div class="card{% if source.has_running_import %} border-primary{% elif source.is_due %} border-warning{% endif %}"> <div class="card{% if source.has_running_import %} border-primary{% elif source.is_due %} border-warning{% elif latest.state == 'finished' %} border-success{% endif %}">
<div class="card-header{% if source.has_running_import %} text-bg-primary{% elif source.is_due %} text-bg-warning{% endif %}"> <div class="card-header{% if source.has_running_import %} text-bg-primary{% elif source.is_due %} text-bg-warning{% elif latest.state == 'finished' %} text-bg-success{% endif %}">
<a href="{% url 'backoffice:schedulesource-detail' pk=source.pk %}" class="float-end ms-3">Details</a> <a href="{% url 'backoffice:schedulesource-detail' pk=source.pk %}" class="float-end ms-3">Details</a>
{% if source.assembly %} {% if source.assembly %}
<abbr title="{% trans "Assembly" %}: {{ source.assembly.name }}">{{ source.assembly.slug }}</abbr> <abbr title="{% trans "Assembly" %}: {{ source.assembly.name }}">{{ source.assembly.slug }}</abbr>
...@@ -51,9 +51,10 @@ ...@@ -51,9 +51,10 @@
</p> </p>
{% endif %} {% endif %}
</div> </div>
{% if latest %}
<div class="card-footer"> <div class="card-footer">
<p> <p>
<span class="text-muted small fw-bold">{% trans "ScheduleSource__latest_import" %}</span><br> <a class="text-muted small fw-bold" href="{% url 'backoffice:schedulesourceimport-detail' pk=latest.pk %}">{% trans "ScheduleSource__latest_import" %}</a><br>
<span class="text-muted small">{% trans "start" %}:</span> <span class="text-muted small">{% trans "start" %}:</span>
<abbr title="{{ latest.start }}">{{ latest.start|naturaltime|default:"-/-" }}</abbr><br> <abbr title="{{ latest.start }}">{{ latest.start|naturaltime|default:"-/-" }}</abbr><br>
<span class="text-muted small">{% trans "end" %}:</span> <span class="text-muted small">{% trans "end" %}:</span>
...@@ -62,6 +63,7 @@ ...@@ -62,6 +63,7 @@
{{ latest.get_state_display }}<br> {{ latest.get_state_display }}<br>
</p> </p>
</div> </div>
{% endif %}
</div> </div>
</div> </div>
{% endwith %} {% endwith %}
......
...@@ -124,6 +124,7 @@ urlpatterns = [ ...@@ -124,6 +124,7 @@ urlpatterns = [
path('schedule/source/<uuid:pk>/import', schedules.ScheduleSourcesDoImportView.as_view(), name='schedulesource-import'), path('schedule/source/<uuid:pk>/import', schedules.ScheduleSourcesDoImportView.as_view(), name='schedulesource-import'),
path('schedule/source/<uuid:pk>/update', schedules.ScheduleSourcesUpdateView.as_view(), name='schedulesource-edit'), path('schedule/source/<uuid:pk>/update', schedules.ScheduleSourcesUpdateView.as_view(), name='schedulesource-edit'),
path('schedule/import/<int:pk>', schedules.ScheduleSourceImportDetailView.as_view(), name='schedulesourceimport-detail'), path('schedule/import/<int:pk>', schedules.ScheduleSourceImportDetailView.as_view(), name='schedulesourceimport-detail'),
path('schedule/import/<int:pk>.json', schedules.ScheduleSourceImportDataView.as_view(), name='schedulesourceimport-detail-data'),
path('sos/', RedirectView.as_view(pattern_name='backoffice:sos', permanent=True)), path('sos/', RedirectView.as_view(pattern_name='backoffice:sos', permanent=True)),
path('self-organized/', events.SoSIndexView.as_view(), name='sos'), path('self-organized/', events.SoSIndexView.as_view(), name='sos'),
path('self-organized/projects/create', projects.CreateProjectView.as_view(), name='so-create-project'), path('self-organized/projects/create', projects.CreateProjectView.as_view(), name='so-create-project'),
......
from django.contrib import messages from django.contrib import messages
from django.http import JsonResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse from django.urls import reverse
from django.views import View from django.views import View
...@@ -26,7 +27,7 @@ class SchedulesIndexView(ScheduleAdminMixin, TemplateView): ...@@ -26,7 +27,7 @@ class SchedulesIndexView(ScheduleAdminMixin, TemplateView):
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
ctx = super().get_context_data(*args, **kwargs) ctx = super().get_context_data(*args, **kwargs)
ctx['sources'] = self.conference.schedule_sources.select_related('assembly').all() ctx['sources'] = self.conference.schedule_sources.select_related('assembly').all().order_by('assembly__name')
return ctx return ctx
...@@ -119,3 +120,23 @@ class ScheduleSourcesDeleteView(ScheduleAdminMixin, DeleteView): ...@@ -119,3 +120,23 @@ class ScheduleSourcesDeleteView(ScheduleAdminMixin, DeleteView):
class ScheduleSourceImportDetailView(ScheduleAdminMixin, DetailView): class ScheduleSourceImportDetailView(ScheduleAdminMixin, DetailView):
template_name = 'backoffice/schedule_source_import-detail.html' template_name = 'backoffice/schedule_source_import-detail.html'
model = ScheduleSourceImport model = ScheduleSourceImport
def get_context_data(self, *args, **kwargs):
action2sort = {'error': '01', 'removed': '02', 'added': '03', 'seen': '08'}
type2sort = {'room': '10', 'event': '20', 'speaker': '50'}
ctx = super().get_context_data(*args, **kwargs)
if data := ctx['object'].data:
ctx['activity'] = sorted(
data.get('_activity', []),
key=lambda item: f'{action2sort.get(item["action"], "99")}__{type2sort.get(item["type"], "99")}__{item["source_id"]:>10}',
)
else:
ctx['activity'] = None
return ctx
class ScheduleSourceImportDataView(ScheduleAdminMixin, DetailView):
model = ScheduleSourceImport
def get(self, *args, **kwargs):
return JsonResponse(self.get_object().data, json_dumps_params={'indent': 2})
...@@ -162,7 +162,7 @@ class ScheduleSource(models.Model): ...@@ -162,7 +162,7 @@ class ScheduleSource(models.Model):
# the very bad case: we found too many # the very bad case: we found too many
if len(candidates) > 1: if len(candidates) > 1:
raise ValueError('Multiple candidate speakers found: ' + '; '.join(x.pk for x in candidates)) raise ValueError('Multiple candidate speakers found: ' + '; '.join(str(x.pk) for x in candidates))
# hail mary attempt: see if we have an imported speaker with the same name # hail mary attempt: see if we have an imported speaker with the same name
candidates = self.conference.users.select_related('user').filter(user__user_type=PlatformUser.Type.SPEAKER, user__display_name=name).all() candidates = self.conference.users.select_related('user').filter(user__user_type=PlatformUser.Type.SPEAKER, user__display_name=name).all()
...@@ -770,6 +770,8 @@ class ScheduleSourceImport(models.Model): ...@@ -770,6 +770,8 @@ class ScheduleSourceImport(models.Model):
@property @property
def errors(self): def errors(self):
if not self.data:
return None
errors = [x for x in self.data.get('_activity', []) if x['action'] == 'error'] errors = [x for x in self.data.get('_activity', []) if x['action'] == 'error']
return errors return errors
...@@ -787,6 +789,7 @@ class ScheduleSourceImport(models.Model): ...@@ -787,6 +789,7 @@ class ScheduleSourceImport(models.Model):
return False return False
self.start = timezone.now() self.start = timezone.now()
self.end = None
self.state = self.State.STARTED self.state = self.State.STARTED
self.save(update_fields=['start', 'state']) self.save(update_fields=['start', 'state'])
logger.info('[job %s] starting import', self.pk) logger.info('[job %s] starting import', self.pk)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment