diff --git a/castellum/execution/templates/execution/participation_detail.html b/castellum/execution/templates/execution/participation_detail.html
index c105b696f480d400f53ecbeaaedd69bda876c7a8..54afacf581100bb49aeb4417e0dc5637e1e3c4c4 100644
--- a/castellum/execution/templates/execution/participation_detail.html
+++ b/castellum/execution/templates/execution/participation_detail.html
@@ -2,19 +2,27 @@
{% load i18n utils auth %}
{% block content %}
- {% if pseudonyms|length > 1 %}
+ {% if domains|length > 1 %}
{% translate 'Pseudonyms' %}
- {% for domain, pseudonym in pseudonyms %}
+ {% for domain in domains %}
- {{ domain }}
- - {{ pseudonym }}
+ -
+
+ {% translate 'get pseudonym' %}
+
+
{% endfor %}
{% else %}
- {% translate 'Pseudonym' %}
- {% for domain, pseudonym in pseudonyms %}
- - {{ pseudonym }}
+ {% for domain in domains %}
+ -
+
+ {% translate 'get pseudonym' %}
+
+
{% endfor %}
{% endif %}
diff --git a/castellum/execution/templates/execution/participation_pseudonyms.html b/castellum/execution/templates/execution/participation_pseudonyms.html
index 8035b2d4d335b3acb837f0e7abaee5ab92f149e3..60a9c8997f3bbfd8283ed822a6bea724bd49fe41 100644
--- a/castellum/execution/templates/execution/participation_pseudonyms.html
+++ b/castellum/execution/templates/execution/participation_pseudonyms.html
@@ -15,11 +15,15 @@
- {% for domain, pseudonym in pseudonyms %}
+ {% for domain in domains %}
{{ domain|display:'key' }}
| {{ domain|display:'name' }}
- | {{ pseudonym }}
+ |
+
+ {% translate 'get pseudonym' %}
+
+
|
{% endfor %}
diff --git a/castellum/execution/urls.py b/castellum/execution/urls.py
index 799563742be7facbfc459c27f5487934fee30c7a..4164144231d75beed6f271687eed41690d99fe23 100644
--- a/castellum/execution/urls.py
+++ b/castellum/execution/urls.py
@@ -36,6 +36,7 @@ from .views import ParticipationDetailView
from .views import ParticipationDropoutConfirmView
from .views import ParticipationDropoutView
from .views import ParticipationPseudonymsView
+from .views import ParticipationPseudonymView
from .views import ParticipationUpdateView
from .views import ProgressView
from .views import ResolveView
@@ -64,6 +65,11 @@ urlpatterns = [
ParticipationPseudonymsView.as_view(),
name='participation-pseudonyms',
),
+ path(
+ '//pseudonyms//',
+ ParticipationPseudonymView.as_view(),
+ name='participation-pseudonym',
+ ),
path(
'//dropout/',
ParticipationDropoutView.as_view(),
diff --git a/castellum/execution/views.py b/castellum/execution/views.py
index 73a12eaa72696a0181f2585893205d37d77535a1..264c9fcb30dc40b56214e39a149384d59c4811de 100644
--- a/castellum/execution/views.py
+++ b/castellum/execution/views.py
@@ -38,6 +38,7 @@ from django.views.generic import FormView
from django.views.generic import ListView
from django.views.generic import TemplateView
from django.views.generic import UpdateView
+from django.views.generic import View
from castellum.appointments.mixins import BaseAppointmentsUpdateView
from castellum.appointments.mixins import BaseCalendarView
@@ -167,9 +168,7 @@ class ParticipationDetailView(ParticipationDetailMixin, DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
- context['pseudonyms'] = [
- (d, get_pseudonym(self.subject, d.key)) for d in self.study.domains.all()
- ]
+ context['domains'] = self.study.domains.all()
return context
@@ -193,12 +192,30 @@ class ParticipationPseudonymsView(ParticipationDetailMixin, DetailView):
context['subject'] = None
context['participation'] = None
- context['pseudonyms'] = [
- (d, get_pseudonym(self.subject, d.key)) for d in self.study.domains.all()
- ]
+ context['domains'] = self.study.domains.all()
+
return context
+class ParticipationPseudonymView(ParticipationDetailMixin, View):
+ def has_permission(self):
+ return (
+ super().has_permission()
+ or self.request.user.has_perm('subjects.export_subject')
+ or self.request.user.has_perm('subjects.delete_subject')
+ )
+
+ def get(self, request, *args, **kwargs):
+ domain = get_object_or_404(self.study.domains, key=kwargs['domain'])
+ pseudonym = get_pseudonym(self.subject, domain.key)
+
+ monitoring_logger.info('Pseudonym access: domain {} by {}'.format(
+ domain.key, self.request.user.pk
+ ))
+
+ return HttpResponse(pseudonym)
+
+
class ParticipationDropoutView(ParticipationDetailMixin, DetailView):
template_name = 'execution/participation_dropout.html'
tab = 'overview'
diff --git a/castellum/static/js/utils.js b/castellum/static/js/utils.js
index 62f4de501de477a1d3a0d92446961291ed99da6c..1ae90745bfee6db59796b7092d7d3e62dc8a01d9 100644
--- a/castellum/static/js/utils.js
+++ b/castellum/static/js/utils.js
@@ -90,6 +90,19 @@
}, 800);
});
+ $$.on(document, 'click', '[data-js="replace-me"]', function(event) {
+ event.preventDefault();
+
+ var spinner = document.createElement('i');
+ spinner.className = 'fa fa-spinner fa-pulse';
+ this.append(spinner);
+
+ fetch(this.href, {credentials: 'same-origin'})
+ .then(response => response.text())
+ .then(pseudonym => this.parentElement.textContent = pseudonym)
+ .catch(() => spinner.remove());
+ });
+
$.fn.select2.defaults.set('theme', 'bootstrap4');
$('[data-js="select2"]').select2();
$('[data-js="select2-tags"]').select2({tags: true});