From 26b9d8edd21a39d0b02089c5b51a828ac999c36c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-S=C3=A9bastien=20Caux?= <git@jscaux.org>
Date: Mon, 5 Dec 2022 10:43:00 +0100
Subject: [PATCH] Build facilities for EdAdmin to handle plagiarism

---
 scipost_django/edadmin/forms/plagiarism.py    |  40 ++++-
 .../edadmin/_hx_plagiarism_assessment.html    |  51 ++++++
 .../edadmin/_hx_plagiarism_iThenticate.html   | 123 ++++++++-------
 .../_hx_plagiarism_iThenticate_assess.html    |   9 ++
 .../edadmin/_hx_plagiarism_internal.html      | 145 ++++++++++--------
 .../_hx_plagiarism_internal_assess.html       |   9 ++
 .../edadmin/_hx_submission_incoming.html      |  25 ++-
 .../edadmin/_hx_submissions_list.html         |   6 +-
 .../edadmin/templates/edadmin/edadmin.html    |  28 ++--
 .../plagiarism_assessment_status_span.html    |   1 +
 scipost_django/edadmin/urls/incoming.py       |  10 ++
 scipost_django/edadmin/views/incoming.py      |  82 +++++++++-
 scipost_django/ontology/views.py              |   1 -
 .../migrations/0128_auto_20221205_0500.py     |  28 ++++
 .../models/plagiarism_assessment.py           |   6 +-
 .../submissions/submission_detail.html        |   2 +-
 16 files changed, 392 insertions(+), 174 deletions(-)
 create mode 100644 scipost_django/edadmin/templates/edadmin/_hx_plagiarism_assessment.html
 create mode 100644 scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate_assess.html
 create mode 100644 scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal_assess.html
 create mode 100644 scipost_django/edadmin/templates/edadmin/plagiarism_assessment_status_span.html
 create mode 100644 scipost_django/submissions/migrations/0128_auto_20221205_0500.py

diff --git a/scipost_django/edadmin/forms/plagiarism.py b/scipost_django/edadmin/forms/plagiarism.py
index bd23e2045..69f1c7d30 100644
--- a/scipost_django/edadmin/forms/plagiarism.py
+++ b/scipost_django/edadmin/forms/plagiarism.py
@@ -3,32 +3,60 @@ __license__ = "AGPL v3"
 
 
 from django import forms
+from django.utils import timezone
+
+from crispy_forms.helper import FormHelper
+from crispy_forms.layout import Layout, Div, Field, ButtonHolder, Submit
 
 from submissions.models import (
+    PlagiarismAssessment,
     InternalPlagiarismAssessment,
     iThenticatePlagiarismAssessment,
 )
 
 
-class InternalPlagiarismAssessmentForm(forms.ModelForm):
+class PlagiarismAssessmentForm(forms.ModelForm):
+    class Meta:
+        model = PlagiarismAssessment
+        fields = [
+            "status",
+            "comments_for_edadmin",
+            "comments_for_authors",
+        ]
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.helper = FormHelper()
+        self.helper.layout = Layout(
+            Field("status"),
+            Field("comments_for_edadmin"),
+            Field("comments_for_authors"),
+            ButtonHolder(Submit("submit", "Submit", css_class="btn btn-primary")),
+        )
+
+    def save(self):
+        assessment = super().save(commit=False)
+        if self.cleaned_data["status"] == self.instance.STATUS_PASSED:
+            assessment.date_set = timezone.now()
+        assessment.save()
+        return assessment
+
+
+class InternalPlagiarismAssessmentForm(PlagiarismAssessmentForm):
     class Meta:
         model = InternalPlagiarismAssessment
         fields = [
-            "submission",
             "status",
-            "passed_on",
             "comments_for_edadmin",
             "comments_for_authors",
         ]
 
 
-class iThenticatePlagiarismAssessmentForm(forms.ModelForm):
+class iThenticatePlagiarismAssessmentForm(PlagiarismAssessmentForm):
     class Meta:
         model = iThenticatePlagiarismAssessment
         fields = [
-            "submission",
             "status",
-            "passed_on",
             "comments_for_edadmin",
             "comments_for_authors",
         ]
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_assessment.html b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_assessment.html
new file mode 100644
index 000000000..dac3572c5
--- /dev/null
+++ b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_assessment.html
@@ -0,0 +1,51 @@
+{% load automarkup %}
+
+<h3>
+  Assessment
+  {% if assessment %}
+    <span class="ms-4">
+      {% include "edadmin/plagiarism_assessment_status_span.html" with assessment=assessment %}
+      {% if assessment.date_set %}
+	&emsp;<span>set on {{ assessment.date_set }}</span>&emsp;
+      {% endif %}
+    </span>
+  {% endif %}
+  <button class="m-2 btn btn-primary"
+	  hx-get="{% if method == 'internal' %}{% url 'edadmin:_hx_plagiarism_internal_assess' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}{% elif method == 'iThenticate' %}{% url 'edadmin:_hx_plagiarism_iThenticate_assess' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}{% endif %}"
+	  hx-target="#submission-{{ submission.pk }}-plagiarism-{{ method }}-assessment"
+	  hx-trigger="click"
+	  hx-indicator="#indicator-{{ submission.pk }}-plagiarism-{{ method }}-assess"
+  >
+    {% if assessment %}
+      Edit assessment
+    {% else %}
+      Start assessment
+    {% endif %}
+  </button>
+</h3>
+
+{% if assessment %}
+  <div class="row">
+    {% if assessment.comments_for_edadmin %}
+      <div class="col col-lg-6">
+	<h4>Comments for EdAdmin</h4>
+	{% automarkup assessment.comments_for_edadmin %}
+      </div>
+    {% endif %}
+    {% if assessment.comments_for_authors %}
+      <div class="col col-lg-6">
+	<h4>Comments for Authors</h4>
+	{% automarkup assessment.comments_for_authors %}
+      </div>
+    {% endif %}
+  </div>
+{% endif %}
+
+<div class="htmx-indicator"
+     id="indicator-{{ submission.pk }}-plagiarism-{{ method }}-assess"
+>
+  <button class="btn btn-sm btn-warning" type="button" disabled>
+    <strong>Loading...</strong>
+    <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div>
+  </button>
+</div>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate.html b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate.html
index 1ed0f83bf..d64e15803 100644
--- a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate.html
+++ b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate.html
@@ -1,70 +1,79 @@
 {% load bootstrap %}
 
-<div class="row">
-  <div class="col">
-    <h3>iThenticate report</h3>
-    {% if submission.iThenticate_plagiarism_report %}
-      <table>
-	<tr>
-	  <td>Latest update</td>
-	  <td>{{ submission.iThenticate_plagiarism_report.latest_activity }}</td>
-	</tr>
-	<tr>
-	  <td style="min-width: 150px;">iThenticate document</td>
-	  <td>{{ submission.iThenticate_plagiarism_report.doc_id }}</td>
-	</tr>
-	<tr>
-	  <td>Uploaded</td>
-	  <td>{{ submission.iThenticate_plagiarism_report.uploaded_time }}</td>
-	</tr>
-	{% if submission.iThenticate_plagiarism_report.processed %}
+<details class="border border-2">
+  <summary class="bg-primary bg-opacity-10 p-2">
+    <h2>
+      iThenticate checks
+      {% if submission.iThenticate_plagiarism_assessment %}
+	&emsp;{% include "edadmin/plagiarism_assessment_status_span.html" with assessment=submission.iThenticate_plagiarism_assessment %}
+      {% endif %}
+    </h2>
+  </summary>
+  <div class="row m-2">
+    <div class="col col-lg-4">
+      <h3>iThenticate report</h3>
+      {% if submission.iThenticate_plagiarism_report %}
+	<table>
 	  <tr>
-	    <td>Processed</td>
-	    <td>{{ submission.iThenticate_plagiarism_report.processed_time }}</td>
+	    <td>Latest update</td>
+	    <td>{{ submission.iThenticate_plagiarism_report.latest_activity }}</td>
 	  </tr>
 	  <tr>
-	    <td>Percent match</td>
-	    <td>{{ submission.iThenticate_plagiarism_report.percent_match }}%</td>
+	    <td style="min-width: 150px;">iThenticate document</td>
+	    <td>{{ submission.iThenticate_plagiarism_report.doc_id }}</td>
 	  </tr>
 	  <tr>
-	    <td><a href="{% url 'submissions:iThenticate_plagiarism_report' submission.preprint.identifier_w_vn_nr %}" class="btn btn-success text-white" target="_blank">Download report pdf</a></td>
+	    <td>Uploaded</td>
+	    <td>{{ submission.iThenticate_plagiarism_report.uploaded_time }}</td>
 	  </tr>
-	{% else %}
-	  <tr>
-	    <td>Report not yet received</td>
-	  </tr>
-	{% endif %}
-      </table>
-    {% else %}
-      <p>No report yet</p>
-    {% endif %}
-    {% if not submission.iThenticate_plagiarism_report.processed %}
-      <form
-	  class="mt-3" enctype="multipart/form-data"
-	  hx-post="{% url 'edadmin:_hx_plagiarism_iThenticate' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-	hx-target="#submission-{{ submission.pk }}-iThenticate"
-	hx-indicator="#indicator-{{ submission.pk }}-iThenticate"
+	  {% if submission.iThenticate_plagiarism_report.processed %}
+	    <tr>
+	      <td>Processed</td>
+	      <td>{{ submission.iThenticate_plagiarism_report.processed_time }}</td>
+	    </tr>
+	    <tr>
+	      <td>Percent match</td>
+	      <td>{{ submission.iThenticate_plagiarism_report.percent_match }}%</td>
+	    </tr>
+	    <tr>
+	      <td><a href="{% url 'submissions:iThenticate_plagiarism_report' submission.preprint.identifier_w_vn_nr %}" class="btn btn-success text-white" target="_blank">Download report pdf</a></td>
+	    </tr>
+	  {% else %}
+	    <tr>
+	      <td>Report not yet received</td>
+	    </tr>
+	  {% endif %}
+	</table>
+      {% else %}
+	<p>No report yet</p>
+      {% endif %}
+    </div>
+    <div class="col col-lg-4">
+      {% if not submission.iThenticate_plagiarism_report.processed %}
+	<form
+	    class="mt-3" enctype="multipart/form-data"
+	    hx-post="{% url 'edadmin:_hx_plagiarism_iThenticate' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+	    hx-target="#submission-{{ submission.pk }}-plagiarism-iThenticate"
+	    hx-indicator="#indicator-{{ submission.pk }}-plagiarism-iThenticate"
 	>
-	{% csrf_token %}
-	{{ form|bootstrap }}
-	<input type="submit" class="btn btn-primary" value="{% if submission.iThenticate_plagiarism_report %}Update report status{% else %}Submit document for plagiarism check{% endif %}">
-      </form>
-      <div id="indicator-{{ submission.pk }}-iThenticate" class="htmx-indicator">
-	<button class="btn btn-sm btn-warning" type="button" disabled>
-	  <strong>Loading...</strong>
-	  <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div>
-	</button>
-      </div>
-    {% endif %}
+	  {% csrf_token %}
+	  {{ form|bootstrap }}
+	  <input type="submit" class="btn btn-primary" value="{% if submission.iThenticate_plagiarism_report %}Update report status{% else %}Submit document for plagiarism check{% endif %}">
+	</form>
+	<div id="indicator-{{ submission.pk }}-plagiarism-iThenticate" class="htmx-indicator">
+	  <button class="btn btn-sm btn-warning" type="button" disabled>
+	    <strong>Loading...</strong>
+	    <div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div>
+	  </button>
+	</div>
+      {% endif %}
+    </div>
   </div>
 
-  <div class="col">
-    <h3>Assessment</h3>
-    {% if submission.iThenticate_plagiarism_assessment %}
-      {{ submission.iThenticate_plagiarism_assessment }}
-    {% else %}
-      TODO: assessment form
-    {% endif %}
+  <div id="submission-{{ submission.pk }}-plagiarism-iThenticate-assessment"
+       class="m-2 p-2 border border-2 border-warning"
+  >
+    {% include "edadmin/_hx_plagiarism_assessment.html" with submission=submission assessment=submission.iThenticate_plagiarism_assessment method="iThenticate" %}
   </div>
 
-</div>
+</details>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate_assess.html b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate_assess.html
new file mode 100644
index 000000000..da9c2b7a6
--- /dev/null
+++ b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_iThenticate_assess.html
@@ -0,0 +1,9 @@
+{% load crispy_forms_tags %}
+<h3>Update assessment of iThenticate plagiarism</h3>
+<form
+    class="mt-3"
+    hx-post="{% url 'edadmin:_hx_plagiarism_iThenticate_assess' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+    hx-target="#submission-{{ submission.pk }}-plagiarism-iThenticate-assessment"
+>
+  {% crispy form %}
+</form>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal.html b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal.html
index 498f23c42..65f30b06c 100644
--- a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal.html
+++ b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal.html
@@ -1,72 +1,89 @@
-<details open>
-  <summary class="m-2 p-2">
-    Submission matches
-    {% if not "submission_matches" in submission.internal_plagiarism_matches %}
-      <span class="text-danger border border-danger m-2 p-2">This automated internal plagiarism check has not finished running yet; please come back later!</span>
-    {% endif %}
+<details class="border border-2">
+  <summary class="bg-primary bg-opacity-10 p-2">
+    <h2>
+      Internal plagiarism checks
+      {% if submission.internal_plagiarism_assessment %}
+	&emsp;{% include "edadmin/plagiarism_assessment_status_span.html" with assessment=submission.internal_plagiarism_assessment %}
+      {% endif %}
+    </h2>
   </summary>
-  <table class="table">
-    <thead>
-      <tr>
-	<th>Submission</th>
-	<th>Title&nbsp;match&nbsp;&#37;</th>
-	<th>Authors&nbsp;match&nbsp;&#37;</th>
-	<th>Abstract&nbsp;match&nbsp;&#37;</th>
-      </tr>
-    </thead>
-    <tbody>
-      {% for match in submission_matches %}
+  <details open>
+    <summary class="m-2 p-2">
+      Submission matches
+      {% if not "submission_matches" in submission.internal_plagiarism_matches %}
+	<span class="text-danger border border-danger m-2 p-2">This automated internal plagiarism check has not finished running yet; please come back later!</span>
+      {% endif %}
+    </summary>
+    <table class="table m-2">
+      <thead>
 	<tr>
-	  <td>
-	    {{ match.submission.preprint.identifier_w_vn_nr }}
-	    &emsp;<small class="text-muted">Thread hash: {{ match.submission.thread_hash }}</small>
-	    <br>
-	    <a href="{{ match.submission.get_absolute_url }}" target="_blank">{{ match.submission.title }}</a><br>
-	    {{ match.submission.author_list }}
-	  </td>
-	  <td>{{ match.ratio_title|floatformat:2 }}</td>
-	  <td>{{ match.ratio_authors|floatformat:2 }}</td>
-	  <td>{{ match.ratio_abstract|floatformat:2 }}</td>
+	  <th>Submission</th>
+	  <th>Title&nbsp;match&nbsp;&#37;</th>
+	  <th>Authors&nbsp;match&nbsp;&#37;</th>
+	  <th>Abstract&nbsp;match&nbsp;&#37;</th>
 	</tr>
-      {% empty %}
-	<tr><td>No matching Submissions</td></tr>
-      {% endfor %}
-    </tbody>
-  </table>
-</details>
+      </thead>
+      <tbody>
+	{% for match in submission_matches %}
+	  <tr>
+	    <td>
+	      {{ match.submission.preprint.identifier_w_vn_nr }}
+	      &emsp;<small class="text-muted">Thread hash: {{ match.submission.thread_hash }}</small>
+	      <br>
+	      <a href="{{ match.submission.get_absolute_url }}" target="_blank">{{ match.submission.title }}</a><br>
+	      {{ match.submission.author_list }}
+	    </td>
+	    <td>{{ match.ratio_title|floatformat:2 }}</td>
+	    <td>{{ match.ratio_authors|floatformat:2 }}</td>
+	    <td>{{ match.ratio_abstract|floatformat:2 }}</td>
+	  </tr>
+	{% empty %}
+	  <tr><td>No matching Submissions</td></tr>
+	{% endfor %}
+      </tbody>
+    </table>
+  </details>
 
 
-<details open>
-  <summary class="m-2 p-2">
-    Publication matches
-    {% if not "publication_matches" in submission.internal_plagiarism_matches %}
-      <span class="text-danger border border-danger m-2 p-2">This automated internal plagiarism check has not finished running yet; please come back later!</span>
-    {% endif %}
-  </summary>
-  <table class="table">
-    <thead>
-      <tr>
-	<th>Publication</th>
-	<th>Title&nbsp;match&nbsp;&#37;</th>
-	<th>Authors&nbsp;match&nbsp;&#37;</th>
-	<th>Abstract&nbsp;match&nbsp;&#37;</th>
-      </tr>
-    </thead>
-    <tbody>
-      {% for match in publication_matches %}
+  <details open>
+    <summary class="m-2 p-2">
+      Publication matches
+      {% if not "publication_matches" in submission.internal_plagiarism_matches %}
+	<span class="text-danger border border-danger m-2 p-2">This automated internal plagiarism check has not finished running yet; please come back later!</span>
+      {% endif %}
+    </summary>
+    <table class="table m-2">
+      <thead>
 	<tr>
-	  <td>
-	    {{ match.publication.doi_label }}<br>
-	    <a href="{{ match.publication.get_absolute_url }}" target="_blank">{{ match.publication.title }}</a><br>
-	    {{ match.publication.author_list }}
-	  </td>
-	  <td>{{ match.ratio_title|floatformat:2 }}</td>
-	  <td>{{ match.ratio_authors|floatformat:2 }}</td>
-	  <td>{{ match.ratio_abstract|floatformat:2 }}</td>
+	  <th>Publication</th>
+	  <th>Title&nbsp;match&nbsp;&#37;</th>
+	  <th>Authors&nbsp;match&nbsp;&#37;</th>
+	  <th>Abstract&nbsp;match&nbsp;&#37;</th>
 	</tr>
-      {% empty %}
-	<tr><td>No matching Publications</td></tr>
-      {% endfor %}
-    </tbody>
-  </table>
+      </thead>
+      <tbody>
+	{% for match in publication_matches %}
+	  <tr>
+	    <td>
+	      {{ match.publication.doi_label }}<br>
+	      <a href="{{ match.publication.get_absolute_url }}" target="_blank">{{ match.publication.title }}</a><br>
+	      {{ match.publication.author_list }}
+	    </td>
+	    <td>{{ match.ratio_title|floatformat:2 }}</td>
+	    <td>{{ match.ratio_authors|floatformat:2 }}</td>
+	    <td>{{ match.ratio_abstract|floatformat:2 }}</td>
+	  </tr>
+	{% empty %}
+	  <tr><td>No matching Publications</td></tr>
+	{% endfor %}
+      </tbody>
+    </table>
+  </details>
+
+  <div id="submission-{{ submission.pk }}-plagiarism-internal-assessment"
+       class="m-2 p-2 border border-2 border-warning"
+  >
+    {% include "edadmin/_hx_plagiarism_assessment.html" with submission=submission assessment=submission.internal_plagiarism_assessment method="internal" %}
+  </div>
+
 </details>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal_assess.html b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal_assess.html
new file mode 100644
index 000000000..3eab60f15
--- /dev/null
+++ b/scipost_django/edadmin/templates/edadmin/_hx_plagiarism_internal_assess.html
@@ -0,0 +1,9 @@
+{% load crispy_forms_tags %}
+<h3>Update assessment of internal plagiarism</h3>
+<form
+    class="mt-3"
+    hx-post="{% url 'edadmin:_hx_plagiarism_internal_assess' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+    hx-target="#submission-{{ submission.pk }}-plagiarism-internal-assessment"
+>
+  {% crispy form %}
+</form>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_submission_incoming.html b/scipost_django/edadmin/templates/edadmin/_hx_submission_incoming.html
index 4f3ef8e7d..7d8475628 100644
--- a/scipost_django/edadmin/templates/edadmin/_hx_submission_incoming.html
+++ b/scipost_django/edadmin/templates/edadmin/_hx_submission_incoming.html
@@ -1,20 +1,17 @@
 <h1>Plagiarism</h1>
 <div class="p-2">
-  <h2>Internal plagiarism checks</h2>
-  <button class="m-2 btn btn-primary"
-		 id="submission-{{ submission.preprint.identifier_w_vn_nr }}"
-		 hx-get="{% url 'edadmin:_hx_plagiarism_internal' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-		 hx-swap="outerHTML"
-		 hx-trigger="revealed"
-  >load internal plagiarism info</button>
+  <div id="submission-{{ submission.pk }}-plagiarism-internal"
+       class="m-2"
+       hx-get="{% url 'edadmin:_hx_plagiarism_internal' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+       hx-trigger="revealed, {{ submission.pk }}-plagiarism-internal-updated"
+  >
+  </div>
 </div>
 <div class="p-2">
-  <h2>iThenticate checks {% if submission.iThenticate_plagiarism_assessment %}{% if submission.iThenticate_plagiarism_assessment.passed %}[passed]{% elif submission.iThenticate_plagiarism_assessment.ongoing %}[ongoing]{% elif submission.iThenticate_plagiarism_assessment.failed %}[failed]{% else %}[STATUS ERROR] {{ submission.iThenticate_plagiarism_assessment.get_status_display }}{% endif %}{% else %}[not assessed yet]{% endif %}</h2>
-  <div id="submission-{{ submission.pk }}-iThenticate">
-    <button class="m-2 btn btn-primary"
-	    hx-get="{% url 'edadmin:_hx_plagiarism_iThenticate' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-	    hx-swap="outerHTML"
-	    hx-trigger="revealed"
-    >load iThenticate plagiarism info</button>
+  <div id="submission-{{ submission.pk }}-plagiarism-iThenticate"
+       class="m-2"
+       hx-get="{% url 'edadmin:_hx_plagiarism_iThenticate' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
+       hx-trigger="revealed, {{ submission.pk }}-plagiarism-iThenticate-updated"
+  >
   </div>
 </div>
diff --git a/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html b/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html
index 757f87afa..6524664d3 100644
--- a/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html
+++ b/scipost_django/edadmin/templates/edadmin/_hx_submissions_list.html
@@ -1,7 +1,7 @@
 {% for submission in submissions %}
 
   <details class="border border-2 my-2">
-    <summary class="px-4 py-2">
+    <summary class="px-4 py-2 bg-primary bg-opacity-10">
       <table>
 	<tbody>
 	  <tr>
@@ -16,7 +16,7 @@
 	</tbody>
       </table>
     </summary>
-    <div class="p-2">
+    <div class="p-4">
       <h1>Summary</h1>
       {% include 'submissions/_submission_summary.html' with submission=submission hide_title=1 show_abstract=1 %}
 
@@ -26,7 +26,7 @@
 
       <h1>Workflow diagram</h1>
       <button class="m-2 btn btn-primary workflowDiagram"
-	      id="submission-{{ submission.preprint.identifier_w_vn_nr }}-workflow-diagram"
+	      id="submission-{{ submission.pk }}-workflow-diagram"
 	      hx-get="{% url 'submissions:_hx_submission_workflow_diagram' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
 	      hx-swap="outerHTML"
       >Load Submission processing workflow graphs</button>
diff --git a/scipost_django/edadmin/templates/edadmin/edadmin.html b/scipost_django/edadmin/templates/edadmin/edadmin.html
index 36d1eb8bf..ef28f63b6 100644
--- a/scipost_django/edadmin/templates/edadmin/edadmin.html
+++ b/scipost_django/edadmin/templates/edadmin/edadmin.html
@@ -21,30 +21,20 @@
     <summary class="bg-info px-4 py-2">
       <h1>Incoming</h1>
     </summary>
-    <div class="p-2">
+    <span class="p-2">
       <button class="m-2 btn btn-primary"
 	      id="incoming"
 	      hx-get="{% url 'edadmin:_hx_incoming_list' %}"
 	      hx-swap="outerHTML"
+	      hx-indicator="#indicator-submissions-incoming"
       >Load incoming Submissions</button>
-    </div>
-  </details>
-
-  <details>
-    <summary>Preassignment</summary>
-    {% for submission in preassignment %}
-
-      {% include 'submissions/_submission_events.html' with events=submission.events.for_edadmin %}
-
-      <details>
-	<summary>{{ submission }}</summary>
-	<button class="m-2 btn btn-primary workflowDiagram"
-		id="submission-{{ submission.preprint.identifier_w_vn_nr }}-workflow-diagram"
-		hx-get="{% url 'submissions:_hx_submission_workflow_diagram' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
-		hx-swap="outerHTML"
-	>Load Submission processing workflow graphs</button>
-      </details>
-    {% endfor %}
+    </span>
+    <span id="indicator-submissions-incoming" class="htmx-indicator">
+      <button class="btn btn-sm btn-warning" type="button" disabled>
+	<strong>Loading...</strong>
+	<div class="spinner-grow spinner-grow-sm ms-2" role="status" aria-hidden="true"></div>
+      </button>
+    </span>
   </details>
 
 {% endblock content %}
diff --git a/scipost_django/edadmin/templates/edadmin/plagiarism_assessment_status_span.html b/scipost_django/edadmin/templates/edadmin/plagiarism_assessment_status_span.html
new file mode 100644
index 000000000..0acf012c5
--- /dev/null
+++ b/scipost_django/edadmin/templates/edadmin/plagiarism_assessment_status_span.html
@@ -0,0 +1 @@
+<span class="px-2 py-1 bg-{% if assessment.ongoing %}warning{% elif assessment.passed %}success{% else %}danger{% endif %} text-white">{{ assessment.get_status_display }}</span>
diff --git a/scipost_django/edadmin/urls/incoming.py b/scipost_django/edadmin/urls/incoming.py
index d7815dc60..b3cae05f4 100644
--- a/scipost_django/edadmin/urls/incoming.py
+++ b/scipost_django/edadmin/urls/incoming.py
@@ -21,11 +21,21 @@ urlpatterns = [
                 incoming._hx_plagiarism_internal,
                 name="_hx_plagiarism_internal",
             ),
+            path(
+                "_hx_plagiarism_internal_assess",
+                incoming._hx_plagiarism_internal_assess,
+                name="_hx_plagiarism_internal_assess",
+            ),
             path(
                 "_hx_plagiarism_iThenticate",
                 incoming._hx_plagiarism_iThenticate,
                 name="_hx_plagiarism_iThenticate",
             ),
+            path(
+                "_hx_plagiarism_iThenticate_assess",
+                incoming._hx_plagiarism_iThenticate_assess,
+                name="_hx_plagiarism_iThenticate_assess",
+            ),
         ])
     ),
 ]
diff --git a/scipost_django/edadmin/views/incoming.py b/scipost_django/edadmin/views/incoming.py
index b9dd0f279..a7038c5bb 100644
--- a/scipost_django/edadmin/views/incoming.py
+++ b/scipost_django/edadmin/views/incoming.py
@@ -3,14 +3,25 @@ __license__ = "AGPL v3"
 
 
 from django.contrib.auth.decorators import login_required, user_passes_test
-from django.shortcuts import get_object_or_404, render
+from django.http import HttpResponse
+from django.shortcuts import get_object_or_404, redirect, render
+from django.urls import reverse
 
 from guardian.shortcuts import get_objects_for_user
 
 from colleges.permissions import is_edadmin
-from submissions.models import Submission
+from submissions.models import (
+    Submission,
+    InternalPlagiarismAssessment,
+    iThenticatePlagiarismAssessment,
+)
 from submissions.forms import iThenticateReportForm
 
+from edadmin.forms.plagiarism import (
+    InternalPlagiarismAssessmentForm,
+    iThenticatePlagiarismAssessmentForm,
+)
+
 
 @login_required
 @user_passes_test(is_edadmin)
@@ -26,13 +37,21 @@ def _hx_incoming_list(request):
     return render(request, "edadmin/_hx_submissions_list.html", context)
 
 
+########################
+# Plagiarism: internal #
+########################
+
 @login_required
 @user_passes_test(is_edadmin)
 def _hx_plagiarism_internal(request, identifier_w_vn_nr):
     submission = get_object_or_404(
         Submission, preprint__identifier_w_vn_nr=identifier_w_vn_nr
     )
-    context = {"submission_matches": [], "publication_matches": []}
+    context = {
+        "submission": submission,
+        "submission_matches": [],
+        "publication_matches": [],
+    }
     if "submission_matches" in submission.internal_plagiarism_matches:
         for sub_match in submission.internal_plagiarism_matches["submission_matches"]:
             context["submission_matches"].append(
@@ -64,10 +83,32 @@ def _hx_plagiarism_internal_assess(request, identifier_w_vn_nr):
     submission = get_object_or_404(
         Submission, preprint__identifier_w_vn_nr=identifier_w_vn_nr
     )
-    form = InternalPlagiarismAssessmentForm(request.POST or None)
-    if form.is_valid():
-        form.save()
+    # if Submission has no assessment yet, create one:
+    try:
+        submission.internal_plagiarism_assessment
+    except InternalPlagiarismAssessment.DoesNotExist:
+        assessment = InternalPlagiarismAssessment(submission=submission)
+        assessment.save()
+        submission.refresh_from_db()
+    form = InternalPlagiarismAssessmentForm(
+        request.POST or None,
+        instance=submission.internal_plagiarism_assessment,
+    )
+    if form.is_valid(): # just trigger re-rendering of iThenticate div
+        assessment = form.save()
+        response = HttpResponse()
+        response["HX-Trigger"] = f"{submission.pk}-plagiarism-internal-updated"
+        return response
+    context = {
+        "submission": submission,
+        "form": form,
+    }
+    return render(request, "edadmin/_hx_plagiarism_internal_assess.html", context)
+
 
+###########################
+# Plagiarism: iThenticate #
+###########################
 
 @login_required
 @user_passes_test(is_edadmin)
@@ -84,3 +125,32 @@ def _hx_plagiarism_iThenticate(request, identifier_w_vn_nr):
         "form": form,
     }
     return render(request, "edadmin/_hx_plagiarism_iThenticate.html", context)
+
+
+@login_required
+@user_passes_test(is_edadmin)
+def _hx_plagiarism_iThenticate_assess(request, identifier_w_vn_nr):
+    submission = get_object_or_404(
+        Submission, preprint__identifier_w_vn_nr=identifier_w_vn_nr
+    )
+    # if Submission has no assessment yet, create one:
+    try:
+        submission.iThenticate_plagiarism_assessment
+    except iThenticatePlagiarismAssessment.DoesNotExist:
+        assessment = iThenticatePlagiarismAssessment(submission=submission)
+        assessment.save()
+        submission.refresh_from_db()
+    form = iThenticatePlagiarismAssessmentForm(
+        request.POST or None,
+        instance=submission.iThenticate_plagiarism_assessment,
+    )
+    if form.is_valid(): # just trigger re-rendering of iThenticate div
+        assessment = form.save()
+        response = HttpResponse()
+        response["HX-Trigger"] = f"{submission.pk}-plagiarism-iThenticate-updated"
+        return response
+    context = {
+        "submission": submission,
+        "form": form,
+    }
+    return render(request, "edadmin/_hx_plagiarism_iThenticate_assess.html", context)
diff --git a/scipost_django/ontology/views.py b/scipost_django/ontology/views.py
index 9dc67cc56..8dcc3dd71 100644
--- a/scipost_django/ontology/views.py
+++ b/scipost_django/ontology/views.py
@@ -3,7 +3,6 @@ __license__ = "AGPL v3"
 
 
 from django.contrib import messages
-from django.http import HttpResponse
 from django.urls import reverse, reverse_lazy
 from django.db.models import Q
 from django.shortcuts import get_object_or_404, redirect, render
diff --git a/scipost_django/submissions/migrations/0128_auto_20221205_0500.py b/scipost_django/submissions/migrations/0128_auto_20221205_0500.py
new file mode 100644
index 000000000..9de4772ce
--- /dev/null
+++ b/scipost_django/submissions/migrations/0128_auto_20221205_0500.py
@@ -0,0 +1,28 @@
+# Generated by Django 3.2.16 on 2022-12-05 04:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('submissions', '0127_auto_20221204_1439'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='plagiarismassessment',
+            old_name='passed_on',
+            new_name='date_set',
+        ),
+        migrations.AlterField(
+            model_name='plagiarismassessment',
+            name='comments_for_authors',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='plagiarismassessment',
+            name='comments_for_edadmin',
+            field=models.TextField(blank=True),
+        ),
+    ]
diff --git a/scipost_django/submissions/models/plagiarism_assessment.py b/scipost_django/submissions/models/plagiarism_assessment.py
index c4b3b89cb..8766e6545 100644
--- a/scipost_django/submissions/models/plagiarism_assessment.py
+++ b/scipost_django/submissions/models/plagiarism_assessment.py
@@ -21,9 +21,9 @@ class PlagiarismAssessment(models.Model):
         choices=STATUS_CHOICES,
         default=STATUS_ONGOING,
     )
-    passed_on = models.DateTimeField(blank=True, null=True)
-    comments_for_edadmin = models.TextField()
-    comments_for_authors = models.TextField()
+    date_set = models.DateTimeField(blank=True, null=True)
+    comments_for_edadmin = models.TextField(blank=True)
+    comments_for_authors = models.TextField(blank=True)
 
     @property
     def ongoing(self):
diff --git a/scipost_django/submissions/templates/submissions/submission_detail.html b/scipost_django/submissions/templates/submissions/submission_detail.html
index 64abe82fb..1d0476e66 100644
--- a/scipost_django/submissions/templates/submissions/submission_detail.html
+++ b/scipost_django/submissions/templates/submissions/submission_detail.html
@@ -163,7 +163,7 @@
 
   {% if is_ed_admin %}
     <button class="m-2 btn btn-primary workflowDiagram"
-	    id="submission-{{ submission.preprint.identifier_w_vn_nr }}-workflow-diagram"
+	    id="submission-{{ submission.pk }}-workflow-diagram"
 	    hx-get="{% url 'submissions:_hx_submission_workflow_diagram' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}"
 	    hx-swap="outerHTML"
     >Load Submission processing workflow graphs</button>
-- 
GitLab