diff --git a/scipost/admin.py b/scipost/admin.py index d9684a15476a077acf50da4e62215da9440296e4..87df8ce71cbb0db9e7a7289f731f4639c396f6a8 100644 --- a/scipost/admin.py +++ b/scipost/admin.py @@ -10,7 +10,7 @@ from scipost.models import Contributor, Remark,\ AffiliationObject,\ SupportingPartner, SPBMembershipAgreement, RegistrationInvitation,\ AuthorshipClaim, PrecookedEmail,\ - EditorialCollege, EditorialCollegeFellow + EditorialCollege, EditorialCollegeFellowship class ContributorInline(admin.StackedInline): @@ -94,13 +94,14 @@ def college_fellow_is_active(fellow): return fellow.is_active() -class EditorialCollegeFellowAdmin(admin.ModelAdmin): +class EditorialCollegeFellowshipAdmin(admin.ModelAdmin): list_display = ('__str__', 'college', college_fellow_is_active) list_filter = ('college', 'contributor__user') - search_fields = ['college', 'contributor__user'] + search_fields = ['college__discipline', + 'contributor__user__first_name', 'contributor__user__last_name'] fields = ('contributor', 'college', 'start_date', 'until_date') college_fellow_is_active.boolean = True -admin.site.register(EditorialCollegeFellow, EditorialCollegeFellowAdmin) +admin.site.register(EditorialCollegeFellowship, EditorialCollegeFellowshipAdmin) diff --git a/scipost/models.py b/scipost/models.py index 668f536447d2e54e65469348f65ce80d1a48db21..25f53183d01b014721f4db19fc65c460d5f8169c 100644 --- a/scipost/models.py +++ b/scipost/models.py @@ -525,14 +525,14 @@ class SPBMembershipAgreement(models.Model): ###################### class FellowManager(models.Manager): - def current_fellows(self, *args, **kwargs): + def active(self, *args, **kwargs): today = datetime.date.today() return self.filter( Q(start_date__lte=today, until_date__isnull=True) | Q(start_date__isnull=True, until_date__gte=today) | Q(start_date__lte=today, until_date__gte=today) | Q(start_date__isnull=True, until_date__isnull=True), - **kwargs) + **kwargs).order_by('contributor__user__last_name') class EditorialCollege(models.Model): @@ -542,17 +542,19 @@ class EditorialCollege(models.Model): def __str__(self): return self.discipline - @property - def active_fellows(self): - return self.fellows.current_fellows() + def active_fellowships(self): + return self.fellowships.current_fellowships() -class EditorialCollegeFellow(TimeStampedModel): - '''Editorial College Fellow connecting Editorial College and Contributors.''' +class EditorialCollegeFellowship(TimeStampedModel): + """ + Editorial College Fellowship connecting Editorial College and Contributors, + maybe with a limiting start/until date. + """ contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE, related_name='+') college = models.ForeignKey('scipost.EditorialCollege', on_delete=models.CASCADE, - related_name='fellows') + related_name='fellowships') start_date = models.DateField(null=True, blank=True) until_date = models.DateField(null=True, blank=True) @@ -569,23 +571,7 @@ class EditorialCollegeFellow(TimeStampedModel): if not self.start_date: if not self.until_date: return True - elif today <= self.until_date: - return True - return False + return today <= self.until_date elif not self.until_date: - if today >= self.start_date: - return True - elif today >= self.start_date and today <= self.until_date: - return True - return False - # - # - # if not self.start_date and not self.until_date: - # return True - # elif not self.start_date and today <= self.until_date: - # return True - # elif today >= self.start_date and not self.until_date: - # return True - # elif today >= self.start_date and today <= self.until_date: - # return True - # return False + return today >= self.start_date + return today >= self.start_date and today <= self.until_date diff --git a/scipost/templates/scipost/_contributor_short.html b/scipost/templates/scipost/_contributor_short.html index 52c7fb8bbe34a3b1b611dfd58313aef159f972ea..cd9f9700ba7823f21f2f9f1b5ffdb54dab32d9bf 100644 --- a/scipost/templates/scipost/_contributor_short.html +++ b/scipost/templates/scipost/_contributor_short.html @@ -1,4 +1,22 @@ -{% if contributor.personalwebpage %}<a target="_blank" href="{{ contributor.personalwebpage }}">{% endif %}{{ contributor.get_title_display }} {{ contributor.user.first_name }} {{ contributor.user.last_name }}{% if contributor.personalwebpage %}</a>{% endif %} +{% load scipost_extras %} + +{% load static %} + +<span class="d-block"> + {% if contributor.personalwebpage %} + <a target="_blank" href="{{ contributor.personalwebpage }}"> + {% endif %} + {{ contributor.get_title_display }} {{ contributor.user.first_name }} {{ contributor.user.last_name }} + {% if contributor.personalwebpage %} + </a> + {% endif %} +</span> + {% if contributor.affiliation %} -<br/>({{contributor.affiliation}}) + <span class="text-muted">({{contributor.affiliation}})</span> {% endif %} +<div class="d-block"> + {% for expertise in contributor.expertises %} + <div class="specialization d-inline" data-specialization="{{expertise}}" >{{expertise|remove_main_specialization}}</div> + {% endfor %} +</div> diff --git a/scipost/templates/scipost/about.html b/scipost/templates/scipost/about.html index 36028f1376da29d7c81b0fbf13523744109b54b1..ecfa33666335b3c59f50d96c70447ecc4af2e58b 100644 --- a/scipost/templates/scipost/about.html +++ b/scipost/templates/scipost/about.html @@ -4,6 +4,8 @@ {% load staticfiles %} +{% load scipost_extras %} + {% block content %} @@ -155,9 +157,9 @@ </div> <div class="row"> - {% for fellow in college.active_fellows %} - <div class="col-md-4 py-1"> - {% include 'scipost/_contributor_short.html' with contributor=fellow.contributor %} + {% for fellowship in college.current_fellows|reorder_list_three %} + <div class="col-md-4 py-1 contributor"> + {% include 'scipost/_contributor_short.html' with contributor=fellowship.contributor %} </div> {% endfor %} </div> diff --git a/scipost/templatetags/scipost_extras.py b/scipost/templatetags/scipost_extras.py index 40863a5f2d987024c06caeb3c480f2477293a174..9d05e456f23857876a5f97118a570466e129618a 100644 --- a/scipost/templatetags/scipost_extras.py +++ b/scipost/templatetags/scipost_extras.py @@ -28,3 +28,13 @@ def is_in_group(user, group_name): def associated_contributors(draft): return Contributor.objects.filter( user__last_name__icontains=draft.last_name) + + +@register.filter(name='reorder_list_three') +def reorder_list_three(ul): + return ul[::3] + ul[1::3] + ul[2::3] + + +@register.filter(name='remove_main_specialization') +def remove_main_specialization(specialization_code): + return specialization_code.split(':')[1] diff --git a/scipost/views.py b/scipost/views.py index c491d98e54669e234db3bfaa07beb17f8f6ef913..6509a8e4ee5a8eccb5f8940080e5c2a054a644af 100644 --- a/scipost/views.py +++ b/scipost/views.py @@ -22,13 +22,15 @@ from django.template import Context, Template from django.utils.http import is_safe_url from django.views.generic.list import ListView +from django.db.models import Prefetch + from guardian.decorators import permission_required from .constants import SCIPOST_SUBJECT_AREAS from .models import Contributor, CitationNotification, UnavailabilityPeriod,\ DraftInvitation, RegistrationInvitation,\ title_dict, SciPost_from_addresses_dict,\ - AuthorshipClaim, SupportingPartner, SPBMembershipAgreement, EditorialCollege + AuthorshipClaim, SupportingPartner, SPBMembershipAgreement, EditorialCollege, EditorialCollegeFellowship from .forms import AuthenticationForm, DraftInvitationForm, UnavailabilityPeriodForm,\ RegistrationForm, RegistrationInvitationForm, AuthorshipClaimForm,\ ModifyPersonalMessageForm, SearchForm, VetRegistrationForm, reg_ref_dict,\ @@ -38,18 +40,13 @@ from .forms import AuthenticationForm, DraftInvitationForm, UnavailabilityPeriod from .utils import Utils, EMAIL_FOOTER, SCIPOST_SUMMARY_FOOTER, SCIPOST_SUMMARY_FOOTER_HTML from commentaries.models import Commentary -from commentaries.forms import CommentarySearchForm from comments.models import Comment from journals.models import Publication, Issue from news.models import NewsItem from submissions.models import SUBMISSION_STATUS_PUBLICLY_UNLISTED from submissions.models import Submission, EditorialAssignment from submissions.models import RefereeInvitation, Report, EICRecommendation -from submissions.forms import SubmissionSearchForm from theses.models import ThesisLink -from theses.forms import ThesisLinkSearchForm -# from virtualmeetings.models import VGM, Feedback, Nomination, Motion -# from virtualmeetings.constants import motion_categories_dict ############## @@ -1464,241 +1461,6 @@ def Fellow_activity_overview(request, Fellow_id=None): context['assignments_of_Fellow'] = assignments_of_Fellow return render(request, 'scipost/Fellow_activity_overview.html', context) -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', return_403=True) -# def VGMs(request): -# VGM_list = VGM.objects.all().order_by('start_date') -# context = {'VGM_list': VGM_list} -# return render(request, 'scipost/VGMs.html', context) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', return_403=True) -# def VGM_detail(request, VGM_id): -# VGM_instance = get_object_or_404(VGM, id=VGM_id) -# VGM_information = Template(VGM_instance.information).render(Context({})) -# feedback_received = Feedback.objects.filter(VGM=VGM_instance).order_by('date') -# feedback_form = FeedbackForm() -# current_Fellows = Contributor.objects.filter( -# user__groups__name='Editorial College').order_by('user__last_name') -# sent_inv_Fellows = RegistrationInvitation.objects.filter( -# invitation_type='F', responded=False) -# pending_inv_Fellows = sent_inv_Fellows.filter(declined=False).order_by('last_name') -# declined_inv_Fellows = sent_inv_Fellows.filter(declined=True).order_by('last_name') -# nomination_form = NominationForm() -# nominations = Nomination.objects.filter(accepted=None).order_by('last_name') -# motion_form = MotionForm() -# remark_form = RemarkForm() -# context = { -# 'VGM': VGM_instance, -# 'VGM_information': VGM_information, -# 'feedback_received': feedback_received, -# 'feedback_form': feedback_form, -# 'current_Fellows': current_Fellows, -# 'pending_inv_Fellows': pending_inv_Fellows, -# 'declined_inv_Fellows': declined_inv_Fellows, -# 'nominations': nominations, -# 'nomination_form': nomination_form, -# 'motion_categories_dict': motion_categories_dict, -# 'motion_form': motion_form, -# 'remark_form': remark_form, -# } -# return render(request, 'scipost/VGM_detail.html', context) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', return_403=True) -# def feedback(request, VGM_id=None): -# if request.method == 'POST': -# feedback_form = FeedbackForm(request.POST) -# if feedback_form.is_valid(): -# feedback = Feedback(by=request.user.contributor, -# date=timezone.now().date(), -# feedback=feedback_form.cleaned_data['feedback'],) -# if VGM_id: -# VGM_instance = get_object_or_404(VGM, id=VGM_id) -# feedback.VGM = VGM_instance -# feedback.save() -# ack_message = 'Your feedback has been received.' -# context = {'ack_message': ack_message} -# if VGM_id: -# context['followup_message'] = 'Return to the ' -# context['followup_link'] = reverse('scipost:VGM_detail', -# kwargs={'VGM_id': VGM_id}) -# context['followup_link_label'] = 'VGM page' -# return render(request, 'scipost/acknowledgement.html', context) -# else: -# errormessage = 'The form was not filled properly.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', raise_exception=True) -# def add_remark_on_feedback(request, VGM_id, feedback_id): -# # contributor = request.user.contributor -# feedback = get_object_or_404(Feedback, pk=feedback_id) -# if request.method == 'POST': -# remark_form = RemarkForm(request.POST) -# if remark_form.is_valid(): -# remark = Remark(contributor=request.user.contributor, -# feedback=feedback, -# date=timezone.now(), -# remark=remark_form.cleaned_data['remark']) -# remark.save() -# return HttpResponseRedirect('/VGM/' + str(VGM_id) + -# '/#feedback_id' + str(feedback.id)) -# else: -# errormessage = 'The form was invalidly filled.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', return_403=True) -# def nominate_Fellow(request, VGM_id): -# VGM_instance = get_object_or_404(VGM, id=VGM_id) -# if request.method == 'POST': -# nomination_form = NominationForm(request.POST) -# if nomination_form.is_valid(): -# nomination = Nomination( -# VGM=VGM_instance, -# by=request.user.contributor, -# date=timezone.now().date(), -# first_name=nomination_form.cleaned_data['first_name'], -# last_name=nomination_form.cleaned_data['last_name'], -# discipline=nomination_form.cleaned_data['discipline'], -# expertises=nomination_form.cleaned_data['expertises'], -# webpage=nomination_form.cleaned_data['webpage'], -# voting_deadline=VGM_instance.end_date + datetime.timedelta(days=7), -# ) -# nomination.save() -# nomination.update_votes(request.user.contributor.id, 'A') -# ack_message = 'The nomination has been registered.' -# context = {'ack_message': ack_message, -# 'followup_message': 'Return to the ', -# 'followup_link': reverse('scipost:VGM_detail', kwargs={'VGM_id': VGM_id}), -# 'followup_link_label': 'VGM page'} -# return render(request, 'scipost/acknowledgement.html', context) -# else: -# errormessage = 'The form was not filled properly.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', raise_exception=True) -# def add_remark_on_nomination(request, VGM_id, nomination_id): -# # contributor = request.user.contributor -# nomination = get_object_or_404(Nomination, pk=nomination_id) -# if request.method == 'POST': -# remark_form = RemarkForm(request.POST) -# if remark_form.is_valid(): -# remark = Remark(contributor=request.user.contributor, -# nomination=nomination, -# date=timezone.now(), -# remark=remark_form.cleaned_data['remark']) -# remark.save() -# return HttpResponseRedirect('/VGM/' + str(VGM_id) + -# '/#nomination_id' + str(nomination.id)) -# else: -# errormessage = 'The form was invalidly filled.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', raise_exception=True) -# def vote_on_nomination(request, nomination_id, vote): -# contributor = request.user.contributor -# nomination = get_object_or_404(Nomination, pk=nomination_id) -# if timezone.now() > nomination.voting_deadline: -# errormessage = 'The voting deadline on this nomination has passed.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# nomination.update_votes(contributor.id, vote) -# return HttpResponseRedirect('/VGM/' + str(nomination.VGM.id) + -# '/#nomination_id' + str(nomination.id)) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', return_403=True) -# def put_motion_forward(request, VGM_id): -# VGM_instance = get_object_or_404(VGM, id=VGM_id) -# if timezone.now().date() > VGM_instance.end_date: -# errormessage = 'This VGM has ended. No new motions can be put forward.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# if request.method == 'POST': -# motion_form = MotionForm(request.POST) -# if motion_form.is_valid(): -# motion = Motion( -# category=motion_form.cleaned_data['category'], -# VGM=VGM_instance, -# background=motion_form.cleaned_data['background'], -# motion=motion_form.cleaned_data['motion'], -# put_forward_by=request.user.contributor, -# date=timezone.now().date(), -# voting_deadline=VGM_instance.end_date + datetime.timedelta(days=7), -# ) -# motion.save() -# motion.update_votes(request.user.contributor.id, 'A') -# ack_message = 'Your motion has been registered.' -# context = {'ack_message': ack_message, -# 'followup_message': 'Return to the ', -# 'followup_link': reverse('scipost:VGM_detail', kwargs={'VGM_id': VGM_id}), -# 'followup_link_label': 'VGM page'} -# return render(request, 'scipost/acknowledgement.html', context) -# else: -# errormessage = 'The form was not filled properly.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', raise_exception=True) -# def add_remark_on_motion(request, motion_id): -# # contributor = request.user.contributor -# motion = get_object_or_404(Motion, pk=motion_id) -# if request.method == 'POST': -# remark_form = RemarkForm(request.POST) -# if remark_form.is_valid(): -# remark = Remark(contributor=request.user.contributor, -# motion=motion, -# date=timezone.now(), -# remark=remark_form.cleaned_data['remark']) -# remark.save() -# return HttpResponseRedirect('/VGM/' + str(motion.VGM.id) + -# '/#motion_id' + str(motion.id)) -# else: -# errormessage = 'The form was invalidly filled.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# else: -# errormessage = 'This view can only be posted to.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# -# -# @login_required -# @permission_required('scipost.can_attend_VGMs', raise_exception=True) -# def vote_on_motion(request, motion_id, vote): -# contributor = request.user.contributor -# motion = get_object_or_404(Motion, pk=motion_id) -# if timezone.now() > motion.voting_deadline: -# errormessage = 'The voting deadline on this motion has passed.' -# return render(request, 'scipost/error.html', {'errormessage': errormessage}) -# motion.update_votes(contributor.id, vote) -# return HttpResponseRedirect('/VGM/' + str(motion.VGM.id) + -# '/#motion_id' + str(motion.id)) -# ############################# # Supporting Partners Board # @@ -1756,4 +1518,8 @@ def SPB_membership_request(request): class AboutView(ListView): model = EditorialCollege template_name = 'scipost/about.html' - queryset = EditorialCollege.objects.prefetch_related('fellows__contributor') + queryset = EditorialCollege.objects.prefetch_related( + Prefetch('fellowships', + queryset=EditorialCollegeFellowship.objects.active().select_related( + 'contributor__user'), + to_attr='current_fellows'))