From cab3a1f344b971b0697b7f4b7e9af076dbdf85a6 Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Wed, 23 Mar 2016 19:41:14 +0100 Subject: [PATCH] Add AuthorshipClaim class, change presentation overall --- .../commentaries/commentary_detail.html | 37 ++++---- comments/models.py | 44 +++++++-- scipost/admin.py | 3 +- scipost/forms.py | 8 ++ scipost/models.py | 16 +++- scipost/static/scipost/SciPost.css | 7 +- .../templates/scipost/claim_authorships.html | 51 ++++++++++ scipost/templates/scipost/personal_page.html | 24 ++++- .../scipost/vet_authorship_claims.html | 49 ++++++++++ scipost/urls.py | 7 ++ scipost/views.py | 95 ++++++++++++++++++- submissions/models.py | 11 ++- 12 files changed, 317 insertions(+), 35 deletions(-) create mode 100644 scipost/templates/scipost/claim_authorships.html create mode 100644 scipost/templates/scipost/vet_authorship_claims.html diff --git a/commentaries/templates/commentaries/commentary_detail.html b/commentaries/templates/commentaries/commentary_detail.html index edb1c4fcb..980c2206d 100644 --- a/commentaries/templates/commentaries/commentary_detail.html +++ b/commentaries/templates/commentaries/commentary_detail.html @@ -59,26 +59,15 @@ {% for comment in comments %} <hr class="hr6"> - <div class="row"> - + +<!-- + <div class="row"> <div class="col-3"> {{ comment.print_identifier|safe }} </div> <div class="col-9"> - <div class="commentcategorydisplay"> - <h4>Category:</h4> - <ul> - {% if comment.is_rem %}<li>remark</li>{% endif %} - {% if comment.is_que %}<li>question</li>{% endif %} - {% if comment.is_ans %}<li>answer to question</li>{% endif %} - {% if comment.is_obj %}<li>objection</li>{% endif %} - {% if comment.is_rep %}<li>reply to objection</li>{% endif %} - {% if comment.is_val %}<li>validation or rederivation</li>{% endif %} - {% if comment.is_lit %}<li>pointer to related literature</li>{% endif %} - {% if comment.is_sug %}<li>suggestion for further work</li>{% endif %} - </ul> - </div> + {{ comment.categories_as_ul|safe }} <br/> <div class="opinionsDisplay"> {% if user.is_authenticated and user.contributor.rank > 0 and user.contributor != comment.author %} @@ -91,7 +80,23 @@ {{ comment.opinions_as_ul|safe }} </div> </div> - + </div> +--> + <div class="flex-container"> + <div class="flex-commentbox"> + {{ comment.print_identifier|safe }} + {{ comment.categories_as_ul|safe }} + <div class="opinionsDisplay"> + {% if user.is_authenticated and user.contributor.rank > 0 and user.contributor != comment.author %} + <form action="{% url 'comments:express_opinion' comment.id %}" method="post"> + {% csrf_token %} + {{ opinion_form }} + <input type="submit" value="Submit"/> + </form> + {% endif %} + {{ comment.opinions_as_ul|safe }} + </div> + </div> </div> <div class="row"> diff --git a/comments/models.py b/comments/models.py index b19b63187..e3f41e9aa 100644 --- a/comments/models.py +++ b/comments/models.py @@ -78,23 +78,28 @@ class Comment(models.Model): def opinions_as_ul(self): output = '<div class="opinionsDisplay"><ul>' - output += '<li>Agree: ' + str(self.nr_A) + '</li>' - output += '<li>Neutral: ' + str(self.nr_N) + '</li>' - output += '<li>Disagree: ' + str(self.nr_D) + '</li>' + output += '<li style="background-color: #000099">Agree: ' + str(self.nr_A) + '</li>' + output += '<li style="background-color: #555555">Not sure: ' + str(self.nr_N) + '</li>' + output += '<li style="background-color: #990000">Disagree: ' + str(self.nr_D) + '</li>' output += '</ul></div>' return output def print_identifier (self): output = '<div class="commentid">\n' - output += '<h3><a id="comment_id' + str(self.id) + '">' + str(self.id) + '</a>' + #output += '<h3><a id="comment_id' + str(self.id) + '">' + str(self.id) + '</a>' + output += '<h3><a id="comment_id' + str(self.id) + '"></a>' if not self.anonymous: - output += (' by <a href="/contributor/' + str(self.author.id) + '">' + - self.author.user.first_name + ' ' + self.author.user.last_name + '</a>') - output += '</h3>' + output += (' <a href="/contributor/' + str(self.author.id) + '">' + + self.author.user.first_name + ' ' + self.author.user.last_name + '</a> on ') + output += self.date_submitted.strftime("%Y-%m-%d") + #output += '</h3>' if self.in_reply_to: - output += '<h4>in reply to ' + str(self.in_reply_to.id) + '</h4>\n' - output += '<h4>' + self.date_submitted.strftime("%Y-%m-%d") + '</h4>\n</div>\n' + #output += '<h4>in reply to ' + str(self.in_reply_to.id) + '</h4>\n' + output += (' <a href="#comment_id' + str(self.in_reply_to_id) + '" style="font-size: 80%">(in reply to ' + str(self.in_reply_to.author.user.first_name) + ' ' + + str(self.in_reply_to.author.user.last_name) + ' on ' + self.in_reply_to.date_submitted.strftime("%Y-%m-%d") + ')</a>') + #output += '<h4>' + self.date_submitted.strftime("%Y-%m-%d") + '</h4>\n</div>\n' + output += '</h3></div>' return output def header_as_li (self): @@ -119,6 +124,27 @@ class Comment(models.Model): header += '</div></li>' return header + def categories_as_ul(self): + output = '<div class="commentcategorydisplay"><h4>Category:</h4><ul>' + if self.is_rem: + output += '<li>remark</li>' + if self.is_que: + output += '<li>question</li>' + if self.is_ans: + output += '<li>answer to question</li>' + if self.is_obj: + output += '<li>objection</li>' + if self.is_rep: + output += '<li>reply to objection</li>' + if self.is_val: + output += '<li>validation or rederivation</li>' + if self.is_lit: + output += '<li>pointer to related literature</li>' + if self.is_sug: + output += '<li>suggestion for further work</li>' + output += '</ul></div>' + return output + class AuthorReply(models.Model): """ Reply to a Comment or Report. """ diff --git a/scipost/admin.py b/scipost/admin.py index 471b408b4..389e0dd5d 100644 --- a/scipost/admin.py +++ b/scipost/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User -from scipost.models import Contributor, Opinion +from scipost.models import Contributor, AuthorshipClaim, Opinion class ContributorInline(admin.StackedInline): #class ContributorInline(admin.TabularInline): @@ -20,4 +20,5 @@ admin.site.register(User, UserAdmin) #admin.site.register(Contributor) +admin.site.register(AuthorshipClaim) admin.site.register(Opinion) diff --git a/scipost/forms.py b/scipost/forms.py index fb5126aa2..d19ab2680 100644 --- a/scipost/forms.py +++ b/scipost/forms.py @@ -60,6 +60,14 @@ class PasswordChangeForm(forms.Form): password_new = forms.CharField(label='New password', widget=forms.PasswordInput()) password_verif = forms.CharField(label='Reenter new password', widget=forms.PasswordInput()) +AUTHORSHIP_CLAIM_CHOICES = ( + ('-', '-'), + ('True', 'I am an author'), + ('False', 'I am not an author'), + ) + +class AuthorshipClaimForm(forms.Form): + claim = forms.ChoiceField(choices=AUTHORSHIP_CLAIM_CHOICES, required=False) class OpinionForm(forms.Form): opinion = forms.ChoiceField(choices=OPINION_CHOICES, label='Your opinion on this Comment: ') diff --git a/scipost/models.py b/scipost/models.py index 1208e41e6..6d484c5d5 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -82,6 +82,20 @@ class Contributor(models.Model): output += '</table>' return output +AUTHORSHIP_CLAIM_STATUS = ( + (1, 'accepted'), + (0, 'not yet vetted (pending)'), + (-1, 'rejected'), +) + +class AuthorshipClaim(models.Model): + claimant = models.ForeignKey(Contributor, related_name='claimant') + submission = models.ForeignKey('submissions.Submission', blank=True, null=True) + commentary = models.ForeignKey('commentaries.Commentary', blank=True, null=True) + vetted = models.BooleanField(default=False) + vetted_by = models.ForeignKey (Contributor, blank=True, null=True) + status = models.SmallIntegerField(choices=AUTHORSHIP_CLAIM_STATUS, default=0) + ####################### @@ -117,7 +131,7 @@ class Assessment(models.Model): OPINION_CHOICES = ( ('ABS', '-'), ('A', 'agree'), - ('N', 'neutral'), + ('N', 'not sure'), ('D', 'disagree'), ) opinion_choices_dict = dict(OPINION_CHOICES) diff --git a/scipost/static/scipost/SciPost.css b/scipost/static/scipost/SciPost.css index c0eefa280..4286ba29c 100644 --- a/scipost/static/scipost/SciPost.css +++ b/scipost/static/scipost/SciPost.css @@ -66,7 +66,7 @@ hr.hr12 { } .commentcategorydisplay li { display: inline-block; - margin: 0px; + margin: 2px; padding: 4px 8px; background-color: #dddddd; font-size: 90%; @@ -203,6 +203,11 @@ hr.hr12 { align-self: center; margin-left: auto; } +.flex-commentbox { + background-color: #f4f4f4; + margin: 0px; + padding: 0px; +} .flex-greybox { background-color: #f4f4f4; margin: 10px; diff --git a/scipost/templates/scipost/claim_authorships.html b/scipost/templates/scipost/claim_authorships.html new file mode 100644 index 000000000..a34381e57 --- /dev/null +++ b/scipost/templates/scipost/claim_authorships.html @@ -0,0 +1,51 @@ +{% extends 'scipost/base.html' %} + +{% block pagetitle %}: authorship claims{% endblock pagetitle %} + +{% block headsup %} + +{% endblock headsup %} + +{% block bodysup %} + +<section> + <div class="flex-greybox"> + <h1>Contributor Authorship Claims</h1> + </div> + + <hr class="hr12"> + <div class="flex-greybox"> + <h1>SciPost Submissions</h1> + </div> + {% if submission_authorships_to_claim %} + <h3>Potential authorships to claim (auto-detected)</h3> + <ul> + {% for sub in submission_authorships_to_claim %} + {{ sub.header_as_li | safe }} + <form action="{% url 'scipost:claim_sub_authorship' submission_id=sub.id claim=1%}" method="post"> + {% csrf_token %} + <input type="submit" value="I am an author" /> + </form> + <form action="{% url 'scipost:claim_sub_authorship' submission_id=sub.id claim=0%}" method="post"> + {% csrf_token %} + <input type="submit" value="I am not an author" /> + </form> + {% endfor %} + </ul> + {% endif %} + + <hr class="hr12"> + <div class="flex-greybox"> + <h1>SciPost Commentaries</h1> + </div> + {% if commentary_authorships_to_claim %} + <h3>Potential authorships to claim (auto-detected)</h3> + <ul> + {% for com in commentary_authorships_to_claim %} + {{ com.header_as_li | safe }} + {% endfor %} + </ul> + {% endif %} +</section> + +{% endblock bodysup %} diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html index 87274d43b..c059e584e 100644 --- a/scipost/templates/scipost/personal_page.html +++ b/scipost/templates/scipost/personal_page.html @@ -68,7 +68,8 @@ <li><a href="{% url 'comments:vet_submitted_comments' %}">Vet submitted Comments</a> ({{ nr_comments_to_vet }})</li> <li><a href="{% url 'comments:vet_author_replies' %}">Vet submitted Author Replies</a> ({{ nr_author_replies_to_vet }})</li> <li><a href="{% url 'submissions:vet_submitted_reports' %}">Vet submitted Reports</a> ({{ nr_reports_to_vet }})</li> - <li><a href="{% url 'theses:vet_thesislink_requests' %}">Vet Thesis Link requests</a> ({{ nr_thesislink_requests_to_vet }})</li> + <li><a href="{% url 'theses:vet_thesislink_requests' %}">Vet Thesis Link Requests</a> ({{ nr_thesislink_requests_to_vet }})</li> + <li><a href="{% url 'scipost:vet_authorship_claims' %}">Vet Authorship Claims</a> ({{ nr_authorship_claims_to_vet }})</li> </ul> </div> {% if contributor.rank >= 3 %} @@ -90,12 +91,18 @@ <div class="flex-greybox"> <h1>SciPost Submissions</h1> </div> - {% if submission_authorships_to_claim %} + {% if own_submissions %} + <h3>Submissions for which you are an author:</h3> <ul> - {% for sub in submission_authorships_to_claim %} + {% for sub in own_submissions %} + {{ sub.header_as_li|safe }} {% endfor %} + </ul> {% endif %} <ul> + {% if nr_submission_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_submission_authorships_to_claim}})</a></li> + {% endif %} <li><a href="{% url 'submissions:submit_manuscript' %}">Submit an arXiv preprint to a SciPost Journal</a></li> </ul> </section> @@ -105,7 +112,18 @@ <div class="flex-greybox"> <h1>SciPost Commentaries</h1> </div> + {% if own_commentaries %} + <h3>Commentaries for which you are an author:</h3> <ul> + {% for com in own_commentaries %} + {{ com.header_as_li|safe }} + {% endfor %} + </ul> + {% endif %} + <ul> + {% if nr_commentary_authorships_to_claim > 0 %} + <li><a href="{% url 'scipost:claim_authorships' %}">Potential authorships to claim (auto-detected: {{ nr_commentary_authorships_to_claim}})</a></li> + {% endif %} <li><a href="{% url 'commentaries:request_commentary' %}">Request opening a SciPost Commentary Page</a></li> </ul> </section> diff --git a/scipost/templates/scipost/vet_authorship_claims.html b/scipost/templates/scipost/vet_authorship_claims.html new file mode 100644 index 000000000..f956a6504 --- /dev/null +++ b/scipost/templates/scipost/vet_authorship_claims.html @@ -0,0 +1,49 @@ +{% extends 'scipost/base.html' %} + +{% block pagetitle %}: vet authorship claims{% endblock pagetitle %} + +{% block headsup %} + +{% endblock headsup %} + +{% block bodysup %} + +<section> + <div class="flex-greybox"> + <h1>Vet Authorship Claims</h1> + </div> + {% if not claims_to_vet %} + <h3>There are no authorship claims to vet %}</h3> + {% else %} + <hr class="hr12"> + <ul> + {% for claim in claims_to_vet %} + {% if claim.submission %} + <h4>Contributor {{ claim.claimant.user.first_name }} {{ claim.claimant.user.last_name }} claims to be an author of Submission:</h4> + {{ claim.submission.header_as_li | safe }} + <form action="{% url 'scipost:vet_sub_authorship_claim' submission_id=claim.submission.id claim=1%}" method="post"> + {% csrf_token %} + <input type="submit" value="Accept" /> + </form> + <form action="{% url 'scipost:vet_sub_authorship_claim' submission_id=claim.submission.id claim=0%}" method="post"> + {% csrf_token %} + <input type="submit" value="Deny" /> + </form> + {% elif claim.commentary %} + <h4>Commentary:</h4> + {{ claim.commentary.header_as_li | safe }} + <form action="{% url 'scipost:vet_com_authorship_claim' commentary_id=claim.commentary.id claim=1%}" method="post"> + {% csrf_token %} + <input type="submit" value="Accept" /> + </form> + <form action="{% url 'scipost:vet_com_authorship_claim' commentary_id=claim.commentary.id claim=0%}" method="post"> + {% csrf_token %} + <input type="submit" value="Deny" /> + </form> + {% endif %} + {% endfor %} + </ul> + {% endif %} +</section> + +{% endblock bodysup %} diff --git a/scipost/urls.py b/scipost/urls.py index 835a76537..f145e2d0c 100644 --- a/scipost/urls.py +++ b/scipost/urls.py @@ -40,4 +40,11 @@ urlpatterns = [ # Contributor info url(r'^(?P<contributor_id>[0-9]+)$', views.contributor_info, name="contributor_info"), + + # Authorship claims + url(r'^claim_authorships$', views.claim_authorships, name="claim_authorships"), + url(r'^claim_sub_authorship/(?P<submission_id>[0-9]+)/(?P<claim>[0-1])$', views.claim_sub_authorship, name="claim_sub_authorship"), + url(r'^vet_authorship_claims$', views.vet_authorship_claims, name="vet_authorship_claims"), + url(r'^vet_sub_authorship_claim/(?P<submission_id>[0-9]+)/(?P<claim>[0-1])$', views.vet_sub_authorship_claim, name="vet_sub_authorship_claim"), + url(r'^vet_com_authorship_claim/(?P<commentary_id>[0-9]+)/(?P<claim>[0-1])$', views.vet_com_authorship_claim, name="vet_com_authorship_claim"), ] diff --git a/scipost/views.py b/scipost/views.py index 8983e98fc..7099fb949 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -225,14 +225,19 @@ def personal_page(request): nr_author_replies_to_vet = 0 nr_reports_to_vet = 0 nr_thesislink_requests_to_vet = 0 + nr_authorship_claims_to_vet = 0 if contributor.rank >= 2: nr_commentary_page_requests_to_vet = Commentary.objects.filter(vetted=False).count() nr_comments_to_vet = Comment.objects.filter(status=0).count() nr_author_replies_to_vet = AuthorReply.objects.filter(status=0).count() nr_reports_to_vet = Report.objects.filter(status=0).count() nr_thesislink_requests_to_vet = ThesisLink.objects.filter(vetted=False).count() + nr_authorship_claims_to_vet = AuthorshipClaim.objects.filter(status='0').count() # Verify if there exist objects authored by this contributor, whose authorship hasn't been claimed yet - submission_authorships_to_claim = Submission.objects.filter(author_list__contains=contributor.user.last_name) + own_submissions = Submission.objects.filter(authors__in=[contributor]) + own_commentaries = Commentary.objects.filter(authors__in=[contributor]) + nr_submission_authorships_to_claim = Submission.objects.filter(author_list__contains=contributor.user.last_name).exclude(authors__in=[contributor]).exclude(authors_claims__in=[contributor]).exclude(authors_false_claims__in=[contributor]).count() + nr_commentary_authorships_to_claim = Commentary.objects.filter(author_list__contains=contributor.user.last_name).count() own_comments = Comment.objects.filter(author=contributor).order_by('-date_submitted') own_authorreplies = AuthorReply.objects.filter(author=contributor).order_by('-date_submitted') context = {'contributor': contributor, 'nr_reg_to_vet': nr_reg_to_vet, @@ -243,7 +248,10 @@ def personal_page(request): 'nr_reports_to_vet': nr_reports_to_vet, 'nr_submissions_to_process': nr_submissions_to_process, 'nr_thesislink_requests_to_vet': nr_thesislink_requests_to_vet, - 'submission_authorships_to_claim': submission_authorships_to_claim, + 'nr_authorship_claims_to_vet': nr_authorship_claims_to_vet, + 'nr_submission_authorships_to_claim': nr_submission_authorships_to_claim, + 'nr_commentary_authorships_to_claim': nr_commentary_authorships_to_claim, + 'own_submissions': own_submissions, 'own_commentaries': own_commentaries, 'own_comments': own_comments, 'own_authorreplies': own_authorreplies} return render(request, 'scipost/personal_page.html', context) else: @@ -311,6 +319,89 @@ def update_personal_data(request): return render(request, 'scipost/login.html', {'form': form}) +def claim_authorships(request): + if request.user.is_authenticated: + contributor = Contributor.objects.get(user=request.user) + + submission_authorships_to_claim = Submission.objects.filter(author_list__contains=contributor.user.last_name).exclude(authors__in=[contributor]).exclude(authors_claims__in=[contributor]).exclude(authors_false_claims__in=[contributor]) + sub_auth_claim_form = AuthorshipClaimForm() + commentary_authorships_to_claim = Commentary.objects.filter(author_list__contains=contributor.user.last_name) + + context = {'submission_authorships_to_claim': submission_authorships_to_claim, + 'sub_auth_claim_form': sub_auth_claim_form, + 'commentary_authorships_to_claim': commentary_authorships_to_claim,} + return render(request, 'scipost/claim_authorships.html', context) + else: + form = AuthenticationForm() + return render(request, 'scipost/login.html', {'form': form}) + + +def claim_sub_authorship(request, submission_id, claim): + if request.method == 'POST': + contributor = Contributor.objects.get(user=request.user) + submission = get_object_or_404(Submission,pk=submission_id) + if claim == '1': + submission.authors_claims.add(contributor) + newclaim = AuthorshipClaim(claimant=contributor, submission=submission) + newclaim.save() + elif claim == '0': + submission.authors_false_claims.add(contributor) + submission.save() + return render(request, 'scipost/claim_authorships.html') + +def claim_com_authorship(request, commentary_id, claim): + if request.method == 'POST': + contributor = Contributor.objects.get(user=request.user) + commentary = get_object_or_404(Commentary,pk=commentary_id) + if claim == '1': + commentary.authors_claims.add(contributor) + newclaim = AuthorshipClaim(claimant=contributor, commentary=commentary) + newclaim.save() + elif claim == '0': + commentary.authors_false_claims.add(contributor) + commentary.save() + return render(request, 'scipost/claim_authorships.html') + + +def vet_authorship_claims(request): + contributor = Contributor.objects.get(user=request.user) + claims_to_vet = AuthorshipClaim.objects.filter(status='0') + context = {'claims_to_vet': claims_to_vet } + return render(request, 'scipost/vet_authorship_claims.html', context) + +def vet_sub_authorship_claim(request, submission_id, claim): + if request.method == 'POST': + contributor = Contributor.objects.get(user=request.user) + submission = Submission.objects.get(pk=submission_id) + submission.authors_claims.remove(contributor) + claim_to_vet = AuthorshipClaim.objects.get(claimant=contributor, submission=submission) + if claim == '1': + submission.authors.add(contributor) + claim_to_vet.status = '1' + elif claim == '0': + submission.authors_false_claims.add(contributor) + claim_to_vet.status = '-1' + submission.save() + claim_to_vet.save() + return render(request, 'scipost/claim_authorships.html') + +def vet_com_authorship_claim(request, commentary_id, claim): + if request.method == 'POST': + contributor = Contributor.objects.get(user=request.user) + commentary = Commentary.objects.get(pk=commentary_id) + commentary.authors_claims.remove(contributor) + claim_to_vet = AuthorshipClaim.objects.get(claimant=contributor, commentary=commentary) + if claim == '1': + commentary.authors.add(contributor) + elif claim == '0': + commentary.authors_false_claims.add(contributor) + claim_to_vet.status = claim + commentary.save() + claim_to_vet.save() + return render(request, 'scipost/claim_authorships.html') + + + def contributor_info(request, contributor_id): if request.user.is_authenticated(): contributor = Contributor.objects.get(pk=contributor_id) diff --git a/submissions/models.py b/submissions/models.py index 15c076cf4..063c141f0 100644 --- a/submissions/models.py +++ b/submissions/models.py @@ -39,6 +39,8 @@ class Submission(models.Model): author_list = models.CharField(max_length=1000, verbose_name="author list") # Authors which have been mapped to contributors: authors = models.ManyToManyField (Contributor, blank=True, related_name='authors_sub') + authors_claims = models.ManyToManyField (Contributor, blank=True, related_name='authors_sub_claims') + authors_false_claims = models.ManyToManyField (Contributor, blank=True, related_name='authors_sub_false_claims') abstract = models.TextField() arxiv_link = models.URLField(verbose_name='arXiv link (including version nr)') submission_date = models.DateField(verbose_name='submission date') @@ -62,8 +64,13 @@ class Submission(models.Model): def header_as_li (self): header = '<li><div class="flex-container">' - header += '<div class="flex-whitebox0"><p><a href="/submission/' + str(self.id) + '" class="pubtitleli">' + self.title + '</a></p>' - header += '<p>by ' + self.author_list + '</p><p> (submitted ' + str(self.submission_date) + ' to ' + journals_submit_dict[self.submitted_to_journal] + ') - latest activity: ' + self.latest_activity.strftime('%Y-%m-%d %H:%M') + '</p></div>' + header += ('<div class="flex-whitebox0"><p><a href="/submission/' + str(self.id) + + '" class="pubtitleli">' + self.title + '</a></p>') + header += ('<p>by ' + self.author_list + + '</p><p> (submitted ' + str(self.submission_date) + + ' to ' + journals_submit_dict[self.submitted_to_journal] + + ') - latest activity: ' + self.latest_activity.strftime('%Y-%m-%d %H:%M') + + '</p></div>') header += '</div></li>' return header -- GitLab