diff --git a/scipost_django/profiles/forms.py b/scipost_django/profiles/forms.py index e8dc9a032603a089c445a2f08cd8c8134625b229..f84ca99f7794a95b81069093eca217b23b91802a 100644 --- a/scipost_django/profiles/forms.py +++ b/scipost_django/profiles/forms.py @@ -8,7 +8,7 @@ from django import forms from django.db.models import Q from crispy_forms.helper import FormHelper -from crispy_forms.layout import Layout, Field, Div +from crispy_forms.layout import Layout, Field, Div, Submit from crispy_bootstrap5.bootstrap5 import FloatingField from dal import autocomplete from django.forms import ChoiceField @@ -247,13 +247,33 @@ class ProfileMergeForm(forms.Form): ) # Retrieve again because of all the db updates. -class ProfileEmailForm(forms.ModelForm): +class AddProfileEmailForm(forms.ModelForm): class Meta: model = ProfileEmail - fields = ["email", "still_valid", "primary"] + fields = ["email"] def __init__(self, *args, **kwargs): + self.request = kwargs.pop("request", None) self.profile = kwargs.pop("profile", None) + + self.helper = FormHelper() + self.helper.layout = Layout( + Div( + Div( + Field("email", type="email", placeholder="Email address"), + css_class="col", + ), + Div(Submit("submit", "Add"), css_class="col-auto mt-auto"), + css_class="row", + ), + ) + self.helper.attrs = { + "hx-post": reverse( + "profiles:add_profile_email", kwargs={"profile_id": self.profile.id} + ), + "hx-target": "#email-action-container", + } + super().__init__(*args, **kwargs) def clean_email(self): @@ -264,10 +284,18 @@ class ProfileEmailForm(forms.ModelForm): return email def save(self): - """Save to a profile.""" - if self.cleaned_data["primary"]: - self.profile.emails.update(primary=False) + """Mark the email as still_valid but not primary.""" + self.instance.profile = self.profile + + if self.request: + is_editing_self = self.request.user.contributor.profile == self.profile + is_ed_admin = self.request.user.contributor.is_ed_admin + self.instance.verified = is_editing_self or is_ed_admin + + self.instance.still_valid = True + self.instance.primary = False + self.instance.added_by = self.request.user.contributor return super().save() diff --git a/scipost_django/profiles/migrations/0038_auto_20240220_1604.py b/scipost_django/profiles/migrations/0038_auto_20240220_1604.py new file mode 100644 index 0000000000000000000000000000000000000000..31f18e7a8fdb015cb73e46baa809c5a036d19d61 --- /dev/null +++ b/scipost_django/profiles/migrations/0038_auto_20240220_1604.py @@ -0,0 +1,31 @@ +# Generated by Django 3.2.18 on 2024-02-20 15:04 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("scipost", "0040_auto_20210310_2026"), + ("profiles", "0037_enable_unaccent"), + ] + + operations = [ + migrations.AddField( + model_name="profileemail", + name="added_by", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="profile_emails_added", + to="scipost.contributor", + ), + ), + migrations.AddField( + model_name="profileemail", + name="verified", + field=models.BooleanField(default=False), + ), + ] diff --git a/scipost_django/profiles/models.py b/scipost_django/profiles/models.py index 5210cf554ee6afd16a52d66ce33a1b684850c3b7..052b9762efc2f77f9c2218e4fa39c940d6b701dc 100644 --- a/scipost_django/profiles/models.py +++ b/scipost_django/profiles/models.py @@ -191,6 +191,14 @@ class ProfileEmail(models.Model): profile = models.ForeignKey("profiles.Profile", on_delete=models.CASCADE) email = models.EmailField() still_valid = models.BooleanField(default=True) + verified = models.BooleanField(default=False) + added_by = models.ForeignKey( + "scipost.Contributor", + on_delete=models.SET_NULL, + blank=True, + null=True, + related_name="profile_emails_added", + ) primary = models.BooleanField(default=False) class Meta: diff --git a/scipost_django/profiles/templates/profiles/_profile_card.html b/scipost_django/profiles/templates/profiles/_profile_card.html index dbb1c6d02c00b6c72098e466a40a57e9905a34b3..ef028444e964a25297e53f11716391bb8b0f34b2 100644 --- a/scipost_django/profiles/templates/profiles/_profile_card.html +++ b/scipost_django/profiles/templates/profiles/_profile_card.html @@ -238,18 +238,6 @@ <ul> <li><a href="{% url 'profiles:profile_update' pk=profile.id %}">Update</a> this Profile</li> <li><a href="{% url 'profiles:profile_delete' pk=profile.id %}" class="text-danger">Delete</a> this Profile</li> - {% if email_form %} - <li> - <div> - Add an email to this Profile: - <form class="form-inline" action="{% url 'profiles:add_profile_email' profile_id=profile.id %}" method="post"> - {% csrf_token %} - {{ email_form|bootstrap }} - <input class="btn btn-outline-secondary" type="submit" value="Add"> - </form> - </div> - </li> - {% endif %} </ul> </div> </div> diff --git a/scipost_django/profiles/views.py b/scipost_django/profiles/views.py index a2875c19b28179b54baa0048671adff651c22a6b..06d72a8a4d0f83b1d5cc0325e187035700f9b201 100644 --- a/scipost_django/profiles/views.py +++ b/scipost_django/profiles/views.py @@ -36,7 +36,7 @@ from .forms import ( ProfileForm, ProfileDynSelForm, ProfileMergeForm, - ProfileEmailForm, + AddProfileEmailForm, AffiliationForm, ) @@ -242,11 +242,6 @@ class ProfileDetailView(PermissionsMixin, DetailView): permission_required = "scipost.can_view_profiles" model = Profile - def get_context_data(self, *args, **kwargs): - context = super().get_context_data(*args, **kwargs) - context["email_form"] = ProfileEmailForm() - return context - class ProfileListView(PermissionsMixin, PaginationMixin, ListView): """ @@ -302,7 +297,6 @@ class ProfileListView(PermissionsMixin, PaginationMixin, ListView): "next_refinv_wo_profile": refinv_wo_profile.first(), "nr_reginv_wo_profile": reginv_wo_profile.count(), "next_reginv_wo_profile": reginv_wo_profile.first(), - "email_form": ProfileEmailForm(), } ) return context @@ -443,7 +437,7 @@ def add_profile_email(request, profile_id): Add an email address to a Profile. """ profile = get_object_or_404(Profile, pk=profile_id) - form = ProfileEmailForm(request.POST or None, profile=profile) + form = AddProfileEmailForm(request.POST or None, profile=profile, request=request) if form.is_valid(): form.save() messages.success(request, "Email successfully added.") diff --git a/scipost_django/submissions/templates/submissions/select_referee.html b/scipost_django/submissions/templates/submissions/select_referee.html index 1d1c38fc6d4054772126283f306e1cb0bef82cc1..febde94f53428e0f66c9e72f5f856cfefbdb0d45 100644 --- a/scipost_django/submissions/templates/submissions/select_referee.html +++ b/scipost_django/submissions/templates/submissions/select_referee.html @@ -112,13 +112,7 @@ {% if profile.email %} Send refereeing invitation <a href="{% url 'submissions:invite_referee' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr profile_id=profile.id auto_reminders_allowed=1 %}">with</a> or <a href="{% url 'submissions:invite_referee' identifier_w_vn_nr=submission.preprint.identifier_w_vn_nr profile_id=profile.id auto_reminders_allowed=0 %}">without</a> auto-reminders. {% include 'submissions/_refinv_auto_reminders_tooltip.html' %} {% else %} - <span class="text-danger">Cannot send an invitation without an email</span> {% include 'bi/arrow-right.html' %} Add one: - <form class="form-inline" action="{% url 'profiles:add_profile_email' profile_id=profile.id %}" method="post"> - {% csrf_token %} - {{ profile_email_form|bootstrap }} - <input type="hidden" name="next" value="{{ request.get_full_path }}"> - <input class="btn btn-outline-secondary" type="submit" value="Add"> - </form> + <span class="text-danger">Cannot send an invitation without an email</span> {% endif %} {% else %} <span class="text-danger">This person does not accept refereeing requests</span> diff --git a/scipost_django/submissions/views/__init__.py b/scipost_django/submissions/views/__init__.py index ba971351bbeba4f10ad6c7f99cbf67287dd7386d..00eea54e906c5e2b476805f47d8d05d8b60cbcfd 100644 --- a/scipost_django/submissions/views/__init__.py +++ b/scipost_django/submissions/views/__init__.py @@ -117,7 +117,7 @@ from preprints.models import Preprint from production.forms import ProofsDecisionForm from production.utils import get_or_create_production_stream from profiles.models import Profile -from profiles.forms import SimpleProfileForm, ProfileEmailForm +from profiles.forms import SimpleProfileForm from scipost.constants import TITLE_DR, INVITATION_REFEREEING from scipost.decorators import is_contributor_user from scipost.forms import RemarkForm, SearchTextForm @@ -1184,7 +1184,6 @@ def select_referee(request, identifier_w_vn_nr): ), "referee_search_form": form, "queryresults": queryresults, - "profile_email_form": ProfileEmailForm(initial={"primary": True}), } ) return render(request, "submissions/select_referee.html", context)