-
Geert Kapteijns authored7c2fc7b3
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
models.py 17.26 KiB
from django.utils import timezone
from django.db import models
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from django.template import Template, Context
from django.utils.safestring import mark_safe
from .models import *
from commentaries.models import Commentary
from scipost.models import TimeStampedModel, Contributor
from submissions.models import Submission, Report
from theses.models import ThesisLink
COMMENT_CATEGORIES = (
('ERR', 'erratum'),
('REM', 'remark'),
('QUE', 'question'),
('ANS', 'answer to question'),
('OBJ', 'objection'),
('REP', 'reply to objection'),
('VAL', 'validation or rederivation'),
('LIT', 'pointer to related literature'),
('SUG', 'suggestion for further work'),
)
COMMENT_STATUS = (
(1, 'vetted'),
(0, 'not yet vetted (pending)'),
(-1, 'rejected (unclear)'),
(-2, 'rejected (incorrect)'),
(-3, 'rejected (not useful)'),
)
comment_status_dict = dict(COMMENT_STATUS)
class Comment(TimeStampedModel):
""" A Comment is an unsollicited note, submitted by a Contributor,
on a particular publication or in reply to an earlier Comment. """
status = models.SmallIntegerField(default=0)
vetted_by = models.ForeignKey(Contributor, blank=True, null=True,
on_delete=models.CASCADE,
related_name='comment_vetted_by')
# a Comment is either for a Commentary or Submission or a ThesisLink.
commentary = models.ForeignKey(Commentary, blank=True, null=True, on_delete=models.CASCADE)
submission = models.ForeignKey(Submission, blank=True, null=True, on_delete=models.CASCADE)
thesislink = models.ForeignKey(ThesisLink, blank=True, null=True, on_delete=models.CASCADE)
is_author_reply = models.BooleanField(default=False)
in_reply_to_comment = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE)
in_reply_to_report = models.ForeignKey(Report, blank=True, null=True, on_delete=models.CASCADE)
author = models.ForeignKey(Contributor, default=1, on_delete=models.CASCADE)
anonymous = models.BooleanField(default=False, verbose_name='Publish anonymously')
# Categories:
is_cor = models.BooleanField(default=False, verbose_name='correction/erratum')
is_rem = models.BooleanField(default=False, verbose_name='remark')
is_que = models.BooleanField(default=False, verbose_name='question')
is_ans = models.BooleanField(default=False, verbose_name='answer to question')
is_obj = models.BooleanField(default=False, verbose_name='objection')
is_rep = models.BooleanField(default=False, verbose_name='reply to objection')
is_val = models.BooleanField(default=False, verbose_name='validation or rederivation')
is_lit = models.BooleanField(default=False, verbose_name='pointer to related literature')
is_sug = models.BooleanField(default=False, verbose_name='suggestion for further work')
comment_text = models.TextField()
remarks_for_editors = models.TextField(default='', blank=True,
verbose_name='optional remarks for the Editors only')
date_submitted = models.DateTimeField('date submitted')
# Opinions
nr_A = models.PositiveIntegerField(default=0)
in_agreement = models.ManyToManyField(Contributor,
related_name='in_agreement', blank=True)
nr_N = models.PositiveIntegerField(default=0)
in_notsure = models.ManyToManyField(Contributor,
related_name='in_notsure', blank=True)
nr_D = models.PositiveIntegerField(default=0)
in_disagreement = models.ManyToManyField(Contributor,
related_name='in_disagreement', blank=True)
def __str__ (self):
return ('by ' + self.author.user.first_name + ' ' + self.author.user.last_name +
' on ' + self.date_submitted.strftime('%Y-%m-%d') + ', ' + self.comment_text[:30])
def update_opinions(self, contributor_id, opinion):
contributor = get_object_or_404(Contributor, pk=contributor_id)
self.in_agreement.remove(contributor)
self.in_notsure.remove(contributor)
self.in_disagreement.remove(contributor)
if opinion == 'A':
self.in_agreement.add(contributor)
elif opinion == 'N':
self.in_notsure.add(contributor)
elif opinion == 'D':
self.in_disagreement.add(contributor)
self.nr_A = self.in_agreement.count()
self.nr_N = self.in_notsure.count()
self.nr_D = self.in_disagreement.count()
self.save()
def opinions_as_ul(self):
template = Template('''
<ul class="opinionsDisplay">
<li style="background-color: #000099">Agree {{ nr_A }}</li>
<li style="background-color: #555555">Not sure {{ nr_N }}</li>
<li style="background-color: #990000">Disagree {{ nr_D }}</li>
</ul>
''')
context = Context ({'nr_A': self.nr_A, 'nr_N': self.nr_N, 'nr_D': self.nr_D})
return template.render(context)
def opinions_as_ul_tiny(self):
template = Template('''
<ul class="opinionsDisplay">
<li style="background-color: #000099; font-size: 8px; padding: 2px;">Agree {{ nr_A }}</li>
<li style="background-color: #555555; font-size: 8px; padding: 2px;">Not sure {{ nr_N }}</li>
<li style="background-color: #990000; font-size: 8px; padding: 2px;">Disagree {{ nr_D }}</li>
</ul>
''')
context = Context ({'nr_A': self.nr_A, 'nr_N': self.nr_N, 'nr_D': self.nr_D})
return template.render(context)
def print_identifier (self):
# for display
output = '<div class="commentid">\n'
output += '<h3><a id="comment_id{{ id }}"></a>'
context = Context({'id': self.id})
if self.is_author_reply:
output += 'Author '
if not self.anonymous:
output += (' <a href="/contributor/{{ author_id }}">'
+ '{{ first_name }} {{ last_name }}</a> on ')
context['author_id'] = self.author.id
context['first_name'] = self.author.user.first_name
context['last_name'] = self.author.user.last_name
output += '{{ date_comment_submitted }}'
context['date_comment_submitted'] = self.date_submitted.strftime("%Y-%m-%d")
if self.in_reply_to_comment:
output += (' (in reply to <a href="#comment_id{{ in_reply_to_comment_id }}">'
'{{ in_reply_to_comment_first_name }} '
'{{ in_reply_to_comment_last_name }} on '
'{{ in_reply_to_comment_date }}</a>)')
context['in_reply_to_comment_id'] = self.in_reply_to_comment_id
context['in_reply_to_comment_first_name'] = (self.in_reply_to_comment
.author.user.first_name)
context['in_reply_to_comment_last_name'] = (self.in_reply_to_comment
.author.user.last_name)
context['in_reply_to_comment_date'] = (self.in_reply_to_comment
.date_submitted.strftime("%Y-%m-%d"))
elif self.in_reply_to_report:
output += ' (in reply to <a href="#report_id{{ in_reply_to_report_id }}">'
context['in_reply_to_report_id'] = self.in_reply_to_report_id
if not self.in_reply_to_report.anonymous:
output += '{{ in_reply_to_report_first_name }} {{ in_reply_to_report_last_name}}'
context['in_reply_to_report_first_name'] = (self.in_reply_to_report
.author.user.first_name)
context['in_reply_to_report_last_name'] = (self.in_reply_to_report
.author.user.last_name)
else:
output += 'Report {{ in_reply_to_report_id }}'
context['in_reply_to_report_id'] = self.in_reply_to_report_id
output += ' on {{ date_report_submitted }}</a>)'
context['date_report_submitted'] = self.in_reply_to_report.date_submitted.strftime("%Y-%m-%d")
output += '</h3></div>'
template = Template(output)
return template.render(context)
def print_identifier_for_vetting (self):
# for display, same as print_identifier but named even if anonymous, not linked
output = '<div class="commentid">\n'
output += '<h3>'
context = Context()
if self.is_author_reply:
output += 'Author '
output += ' <a href="/contributor/{{ author_id }}">{{ first_name }} {{ last_name }}</a> on '
context['author_id'] = self.author.id
context['first_name'] = self.author.user.first_name
context['last_name'] = self.author.user.last_name
output += '{{ date_submitted }}'
context['date_submitted'] = self.date_submitted.strftime("%Y-%m-%d")
if self.in_reply_to_comment:
output += (' (in reply to <a href="#comment_id{{ in_reply_to_comment_id }}">'
'{{ in_reply_to_comment_first_name }} {{ in_reply_to_comment_last_name }} '
'on {{ in_reply_to_comment_date }}</a>)')
context['in_reply_to_comment_id'] = self.in_reply_to_comment_id
context['in_reply_to_comment_first_name'] = (self.in_reply_to_comment
.author.user.first_name)
context['in_reply_to_comment_last_name'] = (self.in_reply_to_comment
.author.user.last_name)
context['in_reply_to_comment_date'] = (self.in_reply_to_comment
.date_submitted.strftime("%Y-%m-%d"))
elif self.in_reply_to_report:
output += ' (in reply to <a href="#report_id{{ in_reply_to_report_id }}">'
context['in_reply_to_report_id'] = self.in_reply_to_report_id
if not self.in_reply_to_report.anonymous:
output += '{{ in_reply_to_report_first_name }} {{ in_reply_to_report_last_name}}'
context['in_reply_to_report_first_name'] = (self.in_reply_to_report
.author.user.first_name)
context['in_reply_to_report_last_name'] = (self.in_reply_to_report
.author.user.last_name)
else:
output += 'Report {{ in_reply_to_report_id }}'
context['in_reply_to_report_id'] = self.in_reply_to_report_id
output += '</a> on {{ date_submitted }})'
context['date_submitted'] = self.in_reply_to_report.date_submitted.strftime("%Y-%m-%d")
output += '</h3></div>'
template = Template(output)
return template.render(context)
def header_as_li (self):
# for search lists
header = '<li>'
#header += '<div class="flex-container"><div class="flex-whitebox0">'
header += 'Nr {{ id }}'
context = Context({'id': self.id})
header += ', <div class="opinionsDisplay">' + self.opinions_as_ul_tiny() + '</div>'
if self.status <= 0:
header += (', status: <span style="color:red">'
+ comment_status_dict[self.status] + '</span>')
text_cut = self.comment_text[:50]
if len(self.comment_text) > 50:
text_cut += '...'
context['id'] = self.id
context['text_cut'] = text_cut
context['date_submitted'] = self.date_submitted.strftime("%Y-%m-%d")
header += ': '
if not self.anonymous:
header += (' <a href="/contributor/{{ author_id }}">'
'{{ first_name }} {{ last_name }}</a>, ')
context['author_id'] = self.author.id
context['first_name'] = self.author.user.first_name
context['last_name'] = self.author.user.last_name
if self.submission is not None:
header += ('<a href="/submission/{{ arxiv_identifier_w_vn_nr }}#comment_id{{ id }}">'
' \"{{ text_cut }}\"</a><p>submitted on {{ date_submitted }}')
header += (' in submission on <a href="/submission/{{ arxiv_identifier_w_vn_nr }}"'
' class="pubtitleli">{{ submission_title }}</a> by '
'{{ submission_author_list }}</p>')
context['arxiv_identifier_w_vn_nr'] = self.submission.arxiv_identifier_w_vn_nr
context['submission_title'] = self.submission.title
context['submission_author_list'] = self.submission.author_list
if self.commentary is not None:
header += ('<a href="/commentary/{{ commentary_url }}#comment_id{{ id }}">'
' \"{{ text_cut }}\"</a><p>submitted on {{ date_submitted }}')
header += (' in commentary on <a href="/commentary/{{ commentary_url }}"'
' class="pubtitleli">'
'{{ commentary_pub_title }}</a> by {{ commentary_author_list }}</p>')
context['commentary_url'] = self.commentary.arxiv_or_DOI_string
context['commentary_pub_title'] = self.commentary.pub_title
context['commentary_author_list'] = self.commentary.author_list
if self.thesislink is not None:
header += ('<a href="/thesis/{{ thesislink_id }}#comment_id{{ id }}">'
' \"{{ text_cut }}\"</a><p>submitted on {{ date_submitted }}')
header += (' in thesislink on <a href="/thesis/{{ thesislink_id }}" class="pubtitleli">'
'{{ thesislink_title }}</a> by {{ thesislink_author }}</p>')
context['thesislink_id'] = self.thesislink.id
context['thesislink_title'] = self.thesislink.title
context['thesislink_author'] = self.thesislink.author
#header += '</div></div>'
header += '</li>'
template = Template(header)
return template.render(context)
def simple_header_as_li (self):
# for Lists
header = '<li>'
#header += '<div class="flex-container"><div class="flex-whitebox0">'
context = Context({})
text_cut = self.comment_text[:30]
if len(self.comment_text) > 30:
text_cut += '...'
context['text_cut'] = text_cut
if not self.anonymous:
header += ' <a href="/contributor/{{ author_id }}">{{ first_name }} {{ last_name }}</a>, '
context['author_id'] = self.author.id
context['first_name'] = self.author.user.first_name
context['last_name'] = self.author.user.last_name
if self.submission is not None:
header += ('<a href="/submission/{{ arxiv_identifier_w_vn_nr }}#comment_id{{ id }}"> '
'\"{{ text_cut }}\"</a>'
' in submission on <a href="/submission/{{ arxiv_identifier_w_vn_nr }}" class="pubtitleli">'
'{{ submission_title }}</a> by {{ submission_author_list }}</p>')
context['arxiv_identifier_w_vn_nr'] = self.submission.arxiv_identifier_w_vn_nr
context['submission_title'] = self.submission.title
context['submission_author_list'] = self.submission.author_list
if self.commentary is not None:
header += ('<a href="/commentary/{{ commentary_url }}#comment_id{{ id }}"> '
'\"{{ text_cut }}\"</a>'
' in commentary on <a href="/commentary/{{ commentary_url }}" class="pubtitleli">'
'{{ commentary_pub_title }}</a> by {{ commentary_author_list }}</p>')
context['commentary_url'] = self.commentary.arxiv_or_DOI_string
context['commentary_pub_title'] = self.commentary.pub_title
context['commentary_author_list'] = self.commentary.author_list
if self.thesislink is not None:
header += '<a href="/thesis/{{ thesislink_id }}#comment_id{{ id }}"> \"{{ text_cut }}\"</a>'
header += (' in thesislink on <a href="/thesis/{{ thesislink_id }}" class="pubtitleli">' +
'{{ thesislink_title }}</a> by {{ thesislink_author }}</p>')
context['thesislink_id'] = self.thesislink.id
context['thesislink_title'] = self.thesislink.title
context['thesislink_author'] = self.thesislink.author
#header += '</div></div>'
header += '</li>'
template = Template(header)
return template.render(context)
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_cor:
output += '<li>correction</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 mark_safe(output)