From e7a4bfaa366d516584f6e7f7c5bb95cde92501a9 Mon Sep 17 00:00:00 2001
From: Jorran de Wit <jorrandewit@outlook.com>
Date: Thu, 13 Dec 2018 07:32:34 +0100
Subject: [PATCH] ..

---
 submissions/models.py                         |  27 +-
 submissions/refereeing_cycles.py              | 104 +++++-
 .../pool/required_actions_block.html          |   4 +-
 .../pool/required_actions_tooltip.html        |   4 +-
 .../submissions/pool/submission_details.html  |  13 +-
 .../pool/submission_info_table.html           |  17 +-
 .../pool/submission_info_table_extended.html  |  32 ++
 .../submissions/pool/submission_li.html       |   7 +-
 .../submission_author_information.html        |  16 +-
 .../submission_editorial_information.html     |   4 +-
 .../submissions/submission_summary.html       |   6 +
 .../submissions/submission_topics.html        |  30 +-
 .../admin/submission_presassign_editors.html  |   2 +-
 .../admin/submission_prescreening.html        |  11 +-
 .../admin/submission_reassign.html            |   2 +-
 submissions/utils.py                          | 297 +-----------------
 .../submission_cycle_reinvite_referee.html    |  28 --
 .../submission_cycle_reinvite_referee.txt     |  15 -
 18 files changed, 204 insertions(+), 415 deletions(-)
 create mode 100644 submissions/templates/partials/submissions/pool/submission_info_table_extended.html
 delete mode 100644 templates/email/submission_cycle_reinvite_referee.html
 delete mode 100644 templates/email/submission_cycle_reinvite_referee.txt

diff --git a/submissions/models.py b/submissions/models.py
index 426281dfa..4a1edea25 100644
--- a/submissions/models.py
+++ b/submissions/models.py
@@ -29,9 +29,7 @@ from .constants import (
 from .managers import (
     SubmissionQuerySet, EditorialAssignmentQuerySet, EICRecommendationQuerySet, ReportQuerySet,
     SubmissionEventQuerySet, RefereeInvitationQuerySet, EditorialCommunicationQueryset)
-from .refereeing_cycles import RegularCycle
-from .utils import (
-    ShortSubmissionCycle, DirectRecommendationSubmissionCycle, GeneralSubmissionCycle)
+from .refereeing_cycles import ShortCycle, DirectCycle, RegularCycle
 
 from comments.behaviors import validate_file_extension, validate_max_file_size
 from comments.models import Comment
@@ -174,34 +172,25 @@ class Submission(models.Model):
 
     def comments_set_complete(self):
         """Return Comments on Submissions, Reports and other Comments."""
-        return Comment.objects.filter(Q(submissions=self) |
-                                      Q(reports__submission=self) |
-                                      Q(comments__reports__submission=self) |
-                                      Q(comments__submissions=self)).distinct()
+        return Comment.objects.filter(
+            Q(submissions=self) | Q(reports__submission=self) |
+            Q(comments__reports__submission=self) | Q(comments__submissions=self)).distinct()
 
     @property
     def cycle(self):
         """Get cycle object that's relevant for the Submission."""
         if not hasattr(self, '_cycle'):
-            self._cycle = RegularCycle(self)
-        return self._cycle
-
-    @property
-    def cycle_old(self):
-        """Get cycle object that's relevant for the Submission."""
-        if not hasattr(self, '__cycle'):
             self.set_cycle()
-        return self.__cycle
+        return self._cycle
 
     def set_cycle(self):
         """Set cycle to the Submission on request."""
         if self.refereeing_cycle == CYCLE_SHORT:
-            cycle = ShortSubmissionCycle(self)
+            self._cycle = ShortCycle(self)
         elif self.refereeing_cycle == CYCLE_DIRECT_REC:
-            cycle = DirectRecommendationSubmissionCycle(self)
+            self._cycle = DirectCycle(self)
         else:
-            cycle = GeneralSubmissionCycle(self)
-        self.__cycle = cycle
+            self._cycle = RegularCycle(self)
 
     def get_absolute_url(self):
         """Return url of the Submission detail page."""
diff --git a/submissions/refereeing_cycles.py b/submissions/refereeing_cycles.py
index 9feeb5fde..ea310ad15 100644
--- a/submissions/refereeing_cycles.py
+++ b/submissions/refereeing_cycles.py
@@ -2,13 +2,56 @@ __copyright__ = "Copyright 2016-2018, Stichting SciPost (SciPost Foundation)"
 __license__ = "AGPL v3"
 
 import datetime
+import json
 
 from django.core.urlresolvers import reverse
 from django.utils import timezone
-from django.utils.html import format_html
+from django.utils.html import format_html, format_html_join, html_safe
 
 from . import constants
-from .utils import RequiredActionsDict
+
+
+@html_safe
+class RequiredActionsDict(dict):
+    """A collection of required actions.
+
+    The required action, meant for the editors-in-charge know how to display itself in
+    various formats. Dictionary keys are the action-codes, the values are the texts
+    to present to the user.
+    """
+
+    def as_data(self):
+        return {f: e.as_data() for f, e in self.items()}
+
+    def as_list_text(self):
+        return [e.__str__() for e in self.values()]
+
+    def get_json_data(self, escape_html=False):
+        return {f: e.get_json_data(escape_html) for f, e in self.items()}
+
+    def as_json(self, escape_html=False):
+        return json.dumps(self.get_json_data(escape_html))
+
+    def as_ul(self):
+        if not self:
+            return '<div class="no-actions-msg">No required actions.</div>'
+        return format_html(
+            '<ul class="actions-list">{}</ul>', format_html_join('', '<li>{}</li>', self.values()))
+
+    def as_text(self):
+        return ' '.join([action.as_text() for action in self.values()])
+
+    def __getitem__(self, action):
+        return super().__getitem__(action.id)
+
+    def __setitem__(self, action, val):
+        super().__setitem__(action.id, val)
+
+    def __contains__(self, value):
+        return value.id in list(self.keys())
+
+    def __str__(self):
+        return self.as_ul()
 
 
 class BaseAction:
@@ -97,9 +140,11 @@ class ChoiceCycleAction(BaseAction):
 
 
 class NoEICRecommendationAction(BaseAction):
+    needs_referees = False
+
     @property
     def txt(self):
-        if not self.submission.reports.non_draft().exists():
+        if self.needs_referees:
             txt = (
                 'The refereeing deadline has passed and you have received no Reports yet.'
                 ' Please <a href="{url}">extend the reporting deadline</a> '
@@ -152,13 +197,11 @@ class BaseCycle:
     """
 
     days_for_refereeing = 28
-    minimum_number_of_referees = 3
     can_invite_referees = True
 
-    def __init__(self, submission, current_user=None):
+    def __init__(self, submission):
         self._submission = submission
         self._required_actions = None
-        self._current_user = current_user
 
     @property
     def required_actions(self):
@@ -166,6 +209,12 @@ class BaseCycle:
             self.update_required_actions()
         return self._required_actions
 
+    @property
+    def minimum_number_of_referees(self):
+        if self._submission.proceedings and self._submission.proceedings.minimum_referees:
+            return self._submission.proceedings.minimum_referees
+        return 3  # Three by default
+
     def has_required_actions(self):
         return bool(self.required_actions)
 
@@ -188,7 +237,9 @@ class BaseCycle:
         # The EIC is late with formulating a Recommendation.
         if self._submission.eic_recommendation_required:
             if self._submission.reporting_deadline_has_passed:
-                self.add_action(NoEICRecommendationAction())
+                action = NoEICRecommendationAction()
+                action.needs_referees = not self._submission.reports.non_draft().exists()
+                self.add_action(action)
 
         # Submission is a resubmission: EIC has to determine which cycle to proceed with.
         comments_to_vet = self._submission.comments.awaiting_vetting().values_list('id')
@@ -269,7 +320,9 @@ class BaseCycle:
         return self.as_text()
 
     def reset_refereeing_round(self):
-        """Set the Submission status to EIC_ASSIGNED and reset the reporting deadline."""
+        """
+        Set the Submission status to EIC_ASSIGNED and reset the reporting deadline.
+        """
         from .models import Submission  # Prevent circular import errors
         if self._submission.status in [constants.STATUS_INCOMING, constants.STATUS_UNASSIGNED]:
             Submission.objects.filter(id=self._submission.id).update(
@@ -279,12 +332,13 @@ class BaseCycle:
         Submission.objects.filter(id=self._submission.id).update(reporting_deadline=deadline)
 
     def reinvite_referees(self, referees, request):
-        """Duplicate and reset RefereeInvitations and send `reinvite` mail.
+        """
+        Duplicate and reset RefereeInvitations and send `reinvite` mail.
 
         referees - (list of) RefereeInvitation instances
         """
         from mails.utils import DirectMailUtil
-        SubmissionUtils.load({'submission': self._submission})
+        # SubmissionUtils.load({'submission': self._submission})
         for referee in referees:
             invitation = referee
             invitation.pk = None  # Duplicate, do not remove the old invitation
@@ -296,9 +350,33 @@ class BaseCycle:
                 mail_code='referees/reinvite_contributor_to_referee', instance=invitation)
             mail_sender.send()
 
-            # SubmissionUtils.load({'invitation': invitation}, request)
-            # SubmissionUtils.reinvite_referees_email()
-
 
 class RegularCycle(BaseCycle):
     pass
+
+
+class ShortCycle(BaseCycle):
+    """
+    Short (two weeks) version of the regular refereeing cycle, used for resubmissions on request
+    by the editor.
+    """
+    days_for_refereeing = 14
+
+    @property
+    def minimum_number_of_referees(self):
+        return 1
+
+
+class DirectCycle(BaseCycle):
+    """
+    Refereeing cycle without refereeing. The editor directly formulates an EICRecommendation.
+    """
+    can_invite_referees = False
+
+    def update_required_actions(self):
+        """Gather the required actions list and populate self._required_actions."""
+        super().update_required_actions()
+
+        # Always show `EICRec required` action disregarding the refereeing deadline.
+        if self._submission.eic_recommendation_required:
+            self.add_action(NoEICRecommendationAction())
diff --git a/submissions/templates/partials/submissions/pool/required_actions_block.html b/submissions/templates/partials/submissions/pool/required_actions_block.html
index 7b82edb3c..7ae18b18c 100644
--- a/submissions/templates/partials/submissions/pool/required_actions_block.html
+++ b/submissions/templates/partials/submissions/pool/required_actions_block.html
@@ -5,8 +5,8 @@
         </div>
         <div class="card-body">
             <ul class="mb-0">
-                {% for action in submission.cycle.required_actions %}
-                    <li>{{action.1}}</li>
+                {% for key, action in submission.cycle.required_actions.items %}
+                    <li>{{ action|safe }}</li>
                 {% empty %}
                     <li>No actions required</li>
                 {% endfor %}
diff --git a/submissions/templates/partials/submissions/pool/required_actions_tooltip.html b/submissions/templates/partials/submissions/pool/required_actions_tooltip.html
index 4b42c758a..b4fd08f77 100644
--- a/submissions/templates/partials/submissions/pool/required_actions_tooltip.html
+++ b/submissions/templates/partials/submissions/pool/required_actions_tooltip.html
@@ -2,8 +2,8 @@
     <i class="fa fa-exclamation-circle {{ classes }}" data-toggle="tooltip" data-html="true" title="
         Required Actions:
         <ul class='mb-0 pl-3 text-left'>
-            {% for action in submission.cycle.required_actions %}
-                <li>{{ action.1 }}</li>
+            {% for key, action in submission.cycle.required_actions.items %}
+                <li>{{ action }}</li>
             {% endfor %}
         </ul>
     "></i>
diff --git a/submissions/templates/partials/submissions/pool/submission_details.html b/submissions/templates/partials/submissions/pool/submission_details.html
index 85a54a447..05fe5dcc9 100644
--- a/submissions/templates/partials/submissions/pool/submission_details.html
+++ b/submissions/templates/partials/submissions/pool/submission_details.html
@@ -38,8 +38,17 @@
         </ul>
 
         {% if is_editor_in_charge or is_editorial_admin or submission|is_voting_fellow:request.user %}
-            <br>
-            {% include 'partials/submissions/pool/required_actions_block.html' with submission=submission %}
+            <div class="my-4 p-3 border{% if submission.cycle.has_required_actions %} border-danger bg-light{% endif %}" id="required-actions" {% if submission.cycle.has_required_actions %}style="border-width: 2px !important;"{% endif %}>
+                <h3>
+                    {% if submission.cycle.has_required_actions %}
+                        <i class="fa fa-exclamation-triangle text-danger"></i>
+                    {% else %}
+                        <i class="fa fa-check-circle"></i>
+                    {% endif %}
+                    Required actions
+                </h3>
+                {{ submission.cycle.required_actions }}
+            </div>
             <h4>
                 <a href="{% url 'submissions:editorial_page' submission.preprint.identifier_w_vn_nr %}">Go to this Submission's Editorial Page</a>
             </h4>
diff --git a/submissions/templates/partials/submissions/pool/submission_info_table.html b/submissions/templates/partials/submissions/pool/submission_info_table.html
index 3594325cb..72dedee19 100644
--- a/submissions/templates/partials/submissions/pool/submission_info_table.html
+++ b/submissions/templates/partials/submissions/pool/submission_info_table.html
@@ -5,7 +5,7 @@
     </tr>
     {% if submission.preprint.url %}
         <tr>
-            <td>Arxiv Link:</td>
+            <td>Arxiv Link</td>
             <td>
                 <a href="{{ submission.preprint.url }}" target="_blank">{{ submission.preprint.url }}</a>
             </td>
@@ -23,6 +23,13 @@
         <td>{{submission.submission_date}} to {{submission.submitted_to}}</td>
     </tr>
 
+    {% if submission.proceedings %}
+        <tr>
+            <td>Proceedings issue</td>
+            <td>{{ submission.proceedings }}</td>
+        </tr>
+    {% endif %}
+
     {% if submission.acceptance_date %}
         <tr>
             <td>Accepted</td>
@@ -39,10 +46,10 @@
         <td>
             {% if submission.editor_in_charge %}
                 {{ submission.editor_in_charge }}
-            {% elif perms.scipost.can_assign_submissions %}
-                <a href="{% url 'submissions:assign_submission' submission.preprint.identifier_w_vn_nr %}">Send a new assignment request</a>
-            {% else %}
+            {% elif request.user.contributor.is_MEC %}
                 <strong class="text-danger">You can volunteer to become Editor-in-charge by <a href="{% url 'submissions:volunteer_as_EIC' submission.preprint.identifier_w_vn_nr %}">clicking here</a>.</strong>
+            {% else %}
+                <em>No editor assigned yet.</em>
             {% endif %}
         </td>
     </tr>
@@ -101,4 +108,6 @@
 
     {% endif %}
 
+    {% block extended_info_table %}{% endblock %}
+
 </table>
diff --git a/submissions/templates/partials/submissions/pool/submission_info_table_extended.html b/submissions/templates/partials/submissions/pool/submission_info_table_extended.html
new file mode 100644
index 000000000..d33b030d0
--- /dev/null
+++ b/submissions/templates/partials/submissions/pool/submission_info_table_extended.html
@@ -0,0 +1,32 @@
+{% extends 'partials/submissions/pool/submission_info_table.html' %}
+
+{% block extended_info_table %}
+    <tr>
+        <td colspan="2"><br></td>
+    </tr>
+    <tr>
+        <td>As Contributors</td>
+        <td>
+            {% for author in submission.authors.all %}
+                {% if not forloop.first %}<span class="text-blue">&middot;</span> {% endif %}<a href="{% url 'scipost:contributor_info' author.id %}">{{author.user.first_name}} {{author.user.last_name}}</a>
+            {% empty %}
+                (none claimed)
+            {% endfor %}
+        </td>
+    </tr>
+    <tr>
+        <td>Submitted by</td>
+        <td>
+            {{submission.submitted_by.user.first_name}} {{submission.submitted_by.user.last_name}}
+        </td>
+    </tr>
+    <tr>
+        <td>Domain(s)</td>
+        <td>{{submission.get_domain_display}}</td>
+    </tr>
+    <tr>
+        <td>Subject area</td>
+        <td>{{submission.get_subject_area_display}}</td>
+    </tr>
+
+{% endblock %}
diff --git a/submissions/templates/partials/submissions/pool/submission_li.html b/submissions/templates/partials/submissions/pool/submission_li.html
index 708bfc31b..d20e0cafd 100644
--- a/submissions/templates/partials/submissions/pool/submission_li.html
+++ b/submissions/templates/partials/submissions/pool/submission_li.html
@@ -43,9 +43,9 @@
             {% endif %}
         </div>
         <div class="col-md-2">
-            <small class="text-muted">Original Submission date</small>
+            <small class="text-muted">Latest activity</small>
             <br>
-            {{ submission.original_submission_date }}
+            {{ submission.latest_activity }}
         </div>
         <div class="col-md-5">
             <small class="text-muted">Submission Status</small>
@@ -56,7 +56,8 @@
 
     {% if submission.cycle.has_required_actions %}
         <div class="card-text bg-danger text-white mt-1 py-1 px-2">
-            This Submission contains required actions, <a href="{% url 'submissions:pool' submission.preprint.identifier_w_vn_nr %}" class="text-white" data-toggle="dynamic" data-target="#container_{{ submission.id }}">click to see details.</a> {% include 'partials/submissions/pool/required_actions_tooltip.html' with submission=submission classes='text-white' %}
+            <a href="{% url 'submissions:pool' submission.preprint.identifier_w_vn_nr %}" class="text-white mr-1" data-toggle="dynamic" data-target="#container_{{ submission.id }}">This Submission contains required actions, click here to see details.</a>
+            {% include 'partials/submissions/pool/required_actions_tooltip.html' with submission=submission classes='text-white' %}
         </div>
     {% endif %}
 
diff --git a/submissions/templates/partials/submissions/submission_author_information.html b/submissions/templates/partials/submissions/submission_author_information.html
index f56b18926..3b47d2a5f 100644
--- a/submissions/templates/partials/submissions/submission_author_information.html
+++ b/submissions/templates/partials/submissions/submission_author_information.html
@@ -2,14 +2,12 @@
 
 <h3 class="highlight">
     Author information
-    <small><a href="javascript:;" class="text-muted" data-toggle="tooltip" data-title="You see this information because you are a verified author of this Submission.">?</a></small>
-    <br>
-    <small><a href="javascript:;" class="mt-2 d-inline-block text-sm" data-toggle="toggle" data-target="#authorinformation">Show/hide author information</a></small>
+    <a href="javascript:;" class="text-muted" data-toggle="tooltip" data-title="You see this information because you are a verified author of this Submission."><i class="fa fa-question-circle"></i></a>
 </h3>
 
 <div id="authorinformation" class="mt-2">
     <div class="mb-4">
-        <h3 class="mt-3">Status summary</h3>
+        <h4 class="mt-3">Status summary</h4>
         <p>
             {% if not submission.editor_in_charge %}
                 No Editor-in-charge is assigned yet. The SciPost administration will inform you as soon as one is assigned.
@@ -67,7 +65,7 @@
 
     {% if submission.eicrecommendations.active %}
         <div class="mb-4">
-            <h3 class="mb-2">Editorial Recommendation:</h3>
+            <h4 class="mb-2">Editorial Recommendation:</h4>
             {% for recommendation in submission.eicrecommendations.active %}
                 {% include 'partials/submissions/recommendation_author_content.html' with recommendation=recommendation %}
             {% empty %}
@@ -77,7 +75,7 @@
     {% endif %}
 
     <div class="mb-4">
-        <h3>Communication</h3>
+        <h4>Communication</h4>
         <div id="communications">
             {% if submission.editor_in_charge %}
                 <a href="{% url 'submissions:communication' submission.preprint.identifier_w_vn_nr 'AtoE' %}">Write to the Editor-in-charge</a>
@@ -87,7 +85,7 @@
     </div>
 
     <div class="mb-4">
-        <h3>Events</h3>
+        <h4>Events</h4>
         <div id="eventslist">
             {% include 'partials/submissions/submission_events.html' with events=submission.events.for_author %}
         </div>
@@ -95,7 +93,7 @@
 
 
     <div class="mb-4" id="proofsslist">
-        <h3>Proofs</h3>
+        <h4>Proofs</h4>
         <ul class="list-group list-group-flush events-list">
             {% for proofs in submission.production_stream.proofs.for_authors %}
                 <li>
@@ -103,7 +101,7 @@
                     status: <span class="label label-secondary label-sm">{{ proofs.get_status_display }}</span>
                     {% if proofs.status == 'accepted_sup' or proofs.status == 'sent' %}
                         {% if proofs_decision_form and is_author %}
-                            <h3 class="mb-0 mt-2">Please advise the Production Team on your findings on Proofs version {{ proofs.version }}</h3>
+                            <h4 class="mb-0 mt-2">Please advise the Production Team on your findings on Proofs version {{ proofs.version }}</h4>
                             <form method="post" enctype="multipart/form-data" action="{% url 'production:author_decision' proofs.slug %}" class="my-2">
                                 {% csrf_token %}
                                 {{ proofs_decision_form|bootstrap }}
diff --git a/submissions/templates/partials/submissions/submission_editorial_information.html b/submissions/templates/partials/submissions/submission_editorial_information.html
index 0808c075f..3adca2073 100644
--- a/submissions/templates/partials/submissions/submission_editorial_information.html
+++ b/submissions/templates/partials/submissions/submission_editorial_information.html
@@ -1,7 +1,7 @@
 {% load bootstrap %}
 
-<h3 class="highlight">Editorial information</h3>
-<a href="javascript:;" class="btn btn-default mb-2" data-toggle="toggle" data-target="#editorialinformation">Show/hide editorial information</a>
+<h3>Editorial information</h3>
+<a href="javascript:;" class="d-block mb-2" data-toggle="toggle" data-target="#editorialinformation">Show/hide editorial information</a>
 
 <div id="editorialinformation" class="mt-2" style="display:none;">
     <div class="mb-4">
diff --git a/submissions/templates/partials/submissions/submission_summary.html b/submissions/templates/partials/submissions/submission_summary.html
index b75a9ae12..f69bb8e9f 100644
--- a/submissions/templates/partials/submissions/submission_summary.html
+++ b/submissions/templates/partials/submissions/submission_summary.html
@@ -52,6 +52,12 @@
         <td>Submitted to:</td>
         <td>{{submission.submitted_to}}</td>
     </tr>
+    {% if submission.proceedings %}
+        <tr>
+            <td>Proceedings issue:</td>
+            <td>{{ submission.proceedings }}</td>
+        </tr>
+    {% endif %}
     <tr>
         <td>Domain(s):</td>
         <td>{{submission.get_domain_display}}</td>
diff --git a/submissions/templates/partials/submissions/submission_topics.html b/submissions/templates/partials/submissions/submission_topics.html
index 6f4d50c6d..793304181 100644
--- a/submissions/templates/partials/submissions/submission_topics.html
+++ b/submissions/templates/partials/submissions/submission_topics.html
@@ -1,4 +1,5 @@
 {% load user_groups %}
+{% load bootstrap %}
 
 {% is_scipost_admin request.user as is_scipost_admin %}
 {% is_edcol_admin request.user as is_edcol_admin %}
@@ -11,7 +12,7 @@
 
     <div>
       {% for topic in submission.topics.all %}
-          <span class="label label-secondary"><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a>{% if perms.scipost.can_manage_ontology %} <a href="{% url 'submissions:submission_remove_topic' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr slug=topic.slug %}"><i class="fa fa-times-circle text-danger"></i></a>{% endif %}</span>
+          <span class="label label-secondary mb-2"><a href="{% url 'ontology:topic_details' slug=topic.slug %}">{{ topic }}</a>{% if perms.scipost.can_manage_ontology %} <a href="{% url 'submissions:submission_remove_topic' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr slug=topic.slug %}"><i class="fa fa-times-circle text-danger"></i></a>{% endif %}</span>
       {% empty %}
           <div>No Topic has yet been associated to this Submission</div>
       {% endfor %}
@@ -19,17 +20,20 @@
     {% if perms.scipost.can_manage_ontology %}
 
         <br>
-        <ul class="list-inline">
-          <li class="list-inline-item">
-        	<form class="form-inline" action="{% url 'submissions:submission_add_topic' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}" method="post">
-        	  <ul class="list-inline">
-        	    <li class="list-inline-item">Add an existing Topic:</li>
-        	    <li class="list-inline-item">{% csrf_token %}{{ select_topic_form }}</li>
-        	    <li class="list-inline-item"><input class="btn btn-outline-secondary" type="submit" value="Link"></li>
-        	  </ul>
-        	</form>
-          </li>
-          <li class="list-inline-item p-2">Can't find the Topic you need? <a href="{% url 'ontology:topic_create' %}" target="_blank">Create it</a> (opens in new window)</li>
-        </ul>
+      <div class="d-inline-block">
+    	<form action="{% url 'submissions:submission_add_topic' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr %}" method="post">
+    	    <div class="d-inline-block">Add an existing Topic:</div>
+    	    <div class="d-inline-block p-2">
+                {% csrf_token %}
+                {{ select_topic_form }}
+            </div>
+    	    <div class="d-inline-block">
+                <input class="btn btn-outline-secondary" type="submit" value="Link">
+            </div>
+    	</form>
+      </div>
+      <div class="d-inline-block p-2">
+          Can't find the Topic you need? <a href="{% url 'ontology:topic_create' %}" target="_blank">Create it</a> (opens in new window)
+      </div>
     {% endif %}
 {% endif %}
diff --git a/submissions/templates/submissions/admin/submission_presassign_editors.html b/submissions/templates/submissions/admin/submission_presassign_editors.html
index 27c28a589..8b4724bd2 100644
--- a/submissions/templates/submissions/admin/submission_presassign_editors.html
+++ b/submissions/templates/submissions/admin/submission_presassign_editors.html
@@ -20,7 +20,7 @@
 
 
 <h1 class="highlight">Submission editor invitations</h1>
-<h3 class="mb-0"><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
+<h3><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
 <h4>by {{submission.author_list}}</h4>
 <br>
 
diff --git a/submissions/templates/submissions/admin/submission_prescreening.html b/submissions/templates/submissions/admin/submission_prescreening.html
index d41fc2cc6..2ef0e744f 100644
--- a/submissions/templates/submissions/admin/submission_prescreening.html
+++ b/submissions/templates/submissions/admin/submission_prescreening.html
@@ -14,15 +14,16 @@
 
 {% block content %}
     <h1 class="highlight">Pre-screening of Submission</h1>
-    <h3 class="mb-0"><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
+    <h3><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
     <h4>by {{submission.author_list}}</h4>
-    <br>
 
-    <h3>Submission summary</h3>
-    {% include 'partials/submissions/submission_summary.html' with submission=submission hide_title=1 show_abstract=1 %}
+    <h3 class="mt-4">Submission summary</h3>
+    {% include 'partials/submissions/pool/submission_info_table_extended.html' with submission=submission %}
 
+    <h3 class="mt-4">Abstract</h3>
+    <p>{{submission.abstract}}</p>
 
-    <h3>Pre-screening steps</h3>
+    <h3 class="mt-4">Pre-screening steps</h3>
     <ul class="fa-ul">
         <li>
             <i class="fa-li fa fa-check-square text-success"></i>
diff --git a/submissions/templates/submissions/admin/submission_reassign.html b/submissions/templates/submissions/admin/submission_reassign.html
index c49cfa1d6..24cd7fcfa 100644
--- a/submissions/templates/submissions/admin/submission_reassign.html
+++ b/submissions/templates/submissions/admin/submission_reassign.html
@@ -14,7 +14,7 @@
 
 {% block content %}
     <h1 class="highlight">Reassign Submission</h1>
-    <h3 class="mb-0"><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
+    <h3><a href="{{ submission.get_absolute_url }}">{{submission.title}}</a></h3>
     <h4>by {{submission.author_list}}</h4>
     <br>
     <p>Current Editor-in-charge: {{ submission.editor_in_charge }}</p>
diff --git a/submissions/utils.py b/submissions/utils.py
index 8855acd84..813c9e503 100644
--- a/submissions/utils.py
+++ b/submissions/utils.py
@@ -3,316 +3,21 @@ __license__ = "AGPL v3"
 
 
 import datetime
-import json
 
 from django.core.mail import EmailMessage, EmailMultiAlternatives
 from django.template import Context, Template
-from django.utils import timezone
-from django.utils.html import format_html, format_html_join, html_safe
 
 from .constants import (
-    NO_REQUIRED_ACTION_STATUSES, STATUS_VETTED, STATUS_UNCLEAR, STATUS_INCORRECT, STATUS_INCOMING,
-    STATUS_NOT_USEFUL, STATUS_NOT_ACADEMIC, STATUS_EIC_ASSIGNED)
+    STATUS_VETTED, STATUS_UNCLEAR, STATUS_INCORRECT, STATUS_NOT_USEFUL, STATUS_NOT_ACADEMIC)
 
 from scipost.utils import EMAIL_FOOTER
 from common.utils import BaseMailUtil
 
 
-@html_safe
-class RequiredActionsDict(dict):
-    """A collection of required actions.
-
-    The required action, meant for the editors-in-charge know how to display itself in
-    various formats. Dictionary keys are the action-codes, the values are the texts
-    to present to the user.
-    """
-
-    def as_data(self):
-        return {f: e.as_data() for f, e in self.items()}
-
-    def as_list_text(self):
-        return [e.__str__() for e in self.values()]
-
-    def get_json_data(self, escape_html=False):
-        return {f: e.get_json_data(escape_html) for f, e in self.items()}
-
-    def as_json(self, escape_html=False):
-        return json.dumps(self.get_json_data(escape_html))
-
-    def as_ul(self):
-        if not self:
-            return '<div class="no-actions-msg">No required actions.</div>'
-        return format_html(
-            '<ul class="actions-list">{}</ul>', format_html_join('', '<li>{}</li>', self.values()))
-
-    def as_text(self):
-        return ' '.join([action.as_text() for action in self.values()])
-
-    def __getitem__(self, action):
-        return super().__getitem__(action.id)
-
-    def __setitem__(self, action, val):
-        super().__setitem__(action.id, val)
-
-    def __contains__(self, value):
-        return value.id in list(self.keys())
-
-    def __str__(self):
-        return self.as_ul()
-
-
-class BaseSubmissionCycle:
-    """
-    The submission cycle may take different approaches. All steps within a specific
-    cycle are handles by the class related to the specific cycle chosen. This class
-    is meant as an abstract blueprint for the overall submission cycle and its needed
-    actions.
-    """
-    default_days = 28
-    may_add_referees = True
-    may_reinvite_referees = True
-    minimum_referees = 3
-    name = None
-    required_actions = []
-    submission = None
-    updated_action = False
-
-    def __init__(self, submission):
-        self.submission = submission
-
-    def __str__(self):
-        return self.submission.get_refereeing_cycle_display()
-
-    def _update_actions(self):
-        """Create the list of actions for the current submission."""
-        self.required_actions = []
-        if self.submission.status in NO_REQUIRED_ACTION_STATUSES:
-            # Submission does not appear in the pool, no action required.
-            return False
-
-        if self.submission.revision_requested:
-            # Editor-in-charge has requested revision.
-            return False
-
-        if self.submission.eicrecommendations.active().exists():
-            # An Editorial Recommendation has already been submitted. Cycle done.
-            return False
-
-        if not self.submission.refereeing_cycle:
-            # Submission is a resubmission: EIC has to determine which cycle to proceed with.
-            self.required_actions.append(
-                ('choose_cycle', 'Choose the submission cycle to proceed with.'))
-            return False
-
-        comments_to_vet = self.submission.comments.awaiting_vetting().count()
-        if comments_to_vet > 0:
-            # There are comments on the submission awaiting vetting.
-            if comments_to_vet > 1:
-                text = '%i Comments have' % comments_to_vet
-            else:
-                text = 'One Comment has'
-            text += ' been delivered but is not yet vetted. Please vet it.'
-            self.required_actions.append(('vet_comments', text,))
-
-        nr_ref_inv = self.submission.referee_invitations.count()
-        if nr_ref_inv < self.minimum_referees:
-            # The submission cycle does not meet the criteria of a minimum of
-            # `self.minimum_referees` referees yet.
-            text = 'No' if nr_ref_inv == 0 else 'Only %i' % nr_ref_inv
-            text += ' Referees have yet been invited.'
-            text += ' At least %i should be.' % self.minimum_referees
-            self.required_actions.append(('invite_referees', text,))
-
-        reports_awaiting_vetting = self.submission.reports.awaiting_vetting().count()
-        if reports_awaiting_vetting > 0:
-            # There are reports on the submission awaiting vetting.
-            if reports_awaiting_vetting > 1:
-                text = '%i Reports have' % reports_awaiting_vetting
-            else:
-                text = 'One Report has'
-            text += ' been delivered but is not yet vetted. Please vet it.'
-            self.required_actions.append(('vet_reports', text,))
-        return True
-
-    def reinvite_referees(self, referees, request=None):
-        """
-        Reinvite referees if allowed. This method does not check if it really is
-        a reinvitation or just a new invitation.
-        """
-        if self.may_reinvite_referees:
-            SubmissionUtils.load({'submission': self.submission})
-            for referee in referees:
-                invitation = referee
-                invitation.pk = None  # Duplicate, do not remove the old invitation
-                invitation.submission = self.submission
-                invitation.reset_content()
-                invitation.date_invited = timezone.now()
-                invitation.save()
-                SubmissionUtils.load({'invitation': invitation}, request)
-                SubmissionUtils.reinvite_referees_email()
-
-    def update_deadline(self, period=None):
-        """
-        Reset the reporting deadline according to current datetime and default cycle length.
-        New reporting deadline may be explicitly given as datetime instance.
-        """
-        delta_d = period or self.default_days
-        deadline = timezone.now() + datetime.timedelta(days=delta_d)
-
-        from .models import Submission
-        Submission.objects.filter(id=self.submission.id).update(reporting_deadline=deadline)
-
-    def get_required_actions(self):
-        '''Return list of the submission its required actions'''
-        if not self.updated_action:
-            self._update_actions()
-            self.updated_action = True
-        return self.required_actions
-
-    def has_required_actions(self):
-        """
-        Certain submission statuses will not show the required actions block.
-        The decision to show this block is taken by this method.
-        """
-        return self.submission.status not in NO_REQUIRED_ACTION_STATUSES
-
-    def update_status(self):
-        """
-        Implement:
-        Let the submission status be centrally handled by this method. This makes sure
-        the status cycle is clear and makes sure the cycle isn't broken due to unclear coding
-        elsewhere. The next status to go to should ideally be determined on all the
-        available in the submission with only few exceptions to explicilty force a new status code.
-        """
-        raise NotImplementedError
-
-
-class BaseRefereeSubmissionCycle(BaseSubmissionCycle):
-    """
-    This *abstract* submission cycle adds the specific actions needed for submission cycles
-    that require referees to be invited.
-    """
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        if self.submission.proceedings:
-            # Check if proceedings has overwritten the `minimum_referees`
-            if self.submission.proceedings.minimum_referees:
-                self.minimum_referees = self.submission.proceedings.minimum_referees
-
-    def update_status(self):
-        if self.submission.status == STATUS_INCOMING and self.submission.is_resubmission:
-            from .models import Submission
-            Submission.objects.filter(id=self.submission.id).update(status=STATUS_EIC_ASSIGNED)
-
-    def _update_actions(self):
-        continue_update = super()._update_actions()
-        if not continue_update:
-            return False
-
-        for ref_inv in self.submission.referee_invitations.all():
-            if not ref_inv.cancelled:
-                if ref_inv.accepted is None:
-                    # An invited referee may have not responded yet.
-                    timelapse = timezone.now() - ref_inv.date_invited
-                    if timelapse > datetime.timedelta(days=3):
-                        text = ('Referee %s has not responded for %i days. '
-                                'Consider sending a reminder or cancelling the invitation.'
-                                % (ref_inv.referee_str, timelapse.days))
-                        self.required_actions.append(('referee_no_response', text,))
-                elif ref_inv.accepted and not ref_inv.fulfilled:
-                    # A referee has not fulfilled its duty and the deadline is closing in.
-                    timeleft = self.submission.reporting_deadline - timezone.now()
-                    if timeleft < datetime.timedelta(days=7):
-                        text = ('Referee %s has accepted to send a Report, '
-                                'but not yet delivered it ' % ref_inv.referee_str)
-                        if timeleft.days < 0:
-                            text += '(%i days overdue). ' % (- timeleft.days)
-                        elif timeleft.days == 1:
-                            text += '(with 1 day left). Consider sending an urgent reminder.'
-                        else:
-                            text += ('(with %i days left). Consider sending a reminder if '
-                                     'you think it can ensure a timely Report.' % timeleft.days)
-                        self.required_actions.append(('referee_no_delivery', text,))
-
-        if self.submission.reporting_deadline < timezone.now():
-            text = ('The refereeing deadline has passed. Please either extend it, '
-                    'or formulate your Editorial Recommendation if at least '
-                    'one Report has been received.')
-            self.required_actions.append(('deadline_passed', text,))
-
-        return True
-
-
-class GeneralSubmissionCycle(BaseRefereeSubmissionCycle):
-    """
-    The default submission cycle assigned to all 'regular' submissions and resubmissions
-    which are explicitly assigned to go trough the default cycle by the EIC.
-    It's a four week cycle with full capabilities i.e. invite referees, vet reports, etc. etc.
-    """
-    pass
-
-
-class ShortSubmissionCycle(BaseRefereeSubmissionCycle):
-    """
-    This cycle is used if the EIC has explicitly chosen to do a short version of the general
-    submission cycle. The deadline is within two weeks instead of the default four weeks.
-
-    This cycle is only available for resubmitted submissions!
-    """
-    default_days = 14
-    may_add_referees = False
-    minimum_referees = 1
-    pass
-
-
-class DirectRecommendationSubmissionCycle(BaseSubmissionCycle):
-    """
-    This cycle is used if the EIC has explicitly chosen to immediately write an
-    editorial recommendation.
-
-    This cycle is only available for resubmitted submissions!
-    """
-    may_add_referees = False
-    may_reinvite_referees = False
-    minimum_referees = 0
-
-    def update_status(self):
-        if self.submission.status == STATUS_INCOMING and self.submission.is_resubmission:
-            from .models import Submission
-            Submission.objects.filter(id=self.submission.id).update(status=STATUS_EIC_ASSIGNED)
-            # TODO: Generate draft-EICRecommendation.
-
-    def _update_actions(self):
-        continue_update = super()._update_actions()
-        if not continue_update:
-            return False
-
-        # No EIC Recommendation has been formulated yet
-        text = 'Formulate an Editorial Recommendation.'
-        self.required_actions.append(('need_eic_rec', text,))
-
-        return True
-
-
 class SubmissionUtils(BaseMailUtil):
     mail_sender = 'submissions@scipost.org'
     mail_sender_title = 'SciPost Editorial Admin'
 
-    @classmethod
-    def reinvite_referees_email(cls):
-        """
-        Email to be sent to referees when they are being reinvited by the EIC.
-
-        Requires context to contain:
-        - `invitation`
-        """
-        extra_bcc_list = [cls._context['invitation'].submission.editor_in_charge.user.email]
-        cls._send_mail(cls, 'submission_cycle_reinvite_referee',
-                       [cls._context['invitation'].email_address],
-                       'Invitation on resubmission',
-                       extra_bcc=extra_bcc_list)
-
     @classmethod
     def send_authors_submission_ack_email(cls):
         """ Requires loading 'submission' attribute. """
diff --git a/templates/email/submission_cycle_reinvite_referee.html b/templates/email/submission_cycle_reinvite_referee.html
deleted file mode 100644
index 08db16275..000000000
--- a/templates/email/submission_cycle_reinvite_referee.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<p>Dear {{invitation.get_title_display}} {{invitation.last_name}},</p>
-
-<p>
-    The authors of submission
-</p>
-
-<p>
-    {{invitation.submission.title}}
-    <br>
-    by {{invitation.submission.author_list}}
-    <br>
-    (<a href="https://scipost.org{{invitation.submission.get_absolute_url}}">see on SciPost.org</a>)
-<p>
-    have resubmitted their manuscript to SciPost. On behalf of the Editor-in-charge {{invitation.submission.editor_in_charge.get_title_display}} {{invitation.submission.editor_in_charge.user.last_name}}, we would like to invite you to quickly review this new version.
-    Please accept or decline the invitation (login required) as soon as possible (ideally within the next 2 days).
-</p>
-<p>
-    If you accept, your report can be submitted by simply clicking on the "Contribute a Report" link on the Submission's Page before the reporting deadline (currently set at {{invitation.submission.reporting_deadline|date:'N j, Y'}}; your report will be automatically recognized as an invited report).
-</p>
-<p>
-    You might want to make sure you are familiar with our refereeing code of conduct and with the refereeing procedure.
-</p>
-<p>
-    We would be extremely grateful for your contribution, and thank you in advance for your consideration.<br>
-    The SciPost Team.
-</p>
-
-{% include 'email/_footer.html' %}
diff --git a/templates/email/submission_cycle_reinvite_referee.txt b/templates/email/submission_cycle_reinvite_referee.txt
deleted file mode 100644
index 34c67aa8d..000000000
--- a/templates/email/submission_cycle_reinvite_referee.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-Dear {{invitation.get_title_display}} {{invitation.last_name}},
-
-The authors of submission
-
-{{invitation.submission.title}} by {{invitation.submission.author_list}}
-
-have resubmitted their manuscript to SciPost. On behalf of the Editor-in-charge {{invitation.submission.editor_in_charge.get_title_display}} {{invitation.submission.editor_in_charge.user.last_name}}, we would like to invite you to quickly review this new version.
-Please accept or decline the invitation (login required) as soon as possible (ideally within the next 2 days).
-
-If you accept, your report can be submitted by simply clicking on the "Contribute a Report" link on the Submission's Page before the reporting deadline (currently set at {{invitation.submission.reporting_deadline|date:'N j, Y'}}; your report will be automatically recognized as an invited report).
-
-You might want to make sure you are familiar with our refereeing code of conduct and with the refereeing procedure.
-
-We would be extremely grateful for your contribution, and thank you in advance for your consideration.
-The SciPost Team.
-- 
GitLab