mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-25 20:18:38 +02:00
Replace form with modelform
Pull in content from related PR and refactor around it
This commit is contained in:
parent
d202d2601f
commit
9a6ccc1c44
10 changed files with 230 additions and 363 deletions
|
@ -873,35 +873,16 @@ function hideDeletedForms() {
|
|||
let fieldId = getInputFieldId(fieldName)
|
||||
let inputField = document.querySelector(fieldId);
|
||||
|
||||
let nameFieldset = document.querySelector("#contact-full-name-fieldset");
|
||||
let nameFieldset = document.querySelector("#profile-name-fieldset");
|
||||
if (nameFieldset){
|
||||
nameFieldset.classList.remove("display-none");
|
||||
}
|
||||
|
||||
if (inputField) {
|
||||
let readonlyId = getReadonlyFieldId(fieldName)
|
||||
let readonlyField = document.querySelector(readonlyId)
|
||||
if (readonlyField) {
|
||||
// Update the <use> element's xlink:href attribute
|
||||
let useElement = readonlyField.querySelector("use");
|
||||
if (useElement) {
|
||||
let currentHref = useElement.getAttribute("xlink:href");
|
||||
let parts = currentHref.split("#");
|
||||
|
||||
// Update the icon reference to the info icon
|
||||
if (parts.length > 1) {
|
||||
parts[1] = "info_outline";
|
||||
useElement.setAttribute("xlink:href", parts.join("#"));
|
||||
|
||||
// Change the color to => $dhs-dark-gray-60
|
||||
useElement.closest('svg').style.fill = '#444547';
|
||||
}
|
||||
}
|
||||
|
||||
let parentDiv = readonlyField.closest("div");
|
||||
if (parentDiv) {
|
||||
parentDiv.classList.toggle("overlapped-full-name-field");
|
||||
}
|
||||
// Remove the "full_name" field
|
||||
inputFieldParentDiv = inputField.closest("div");
|
||||
if (inputFieldParentDiv) {
|
||||
inputFieldParentDiv.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,23 +10,8 @@ fieldset:not(:first-child) {
|
|||
}
|
||||
|
||||
fieldset.registrar-fieldset__contact {
|
||||
border-width: 2px;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
fieldset.registrar-fieldset__contact {
|
||||
margin-top: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px){
|
||||
fieldset.registrar-fieldset__contact {
|
||||
padding: 0;
|
||||
// This fieldset is for SR purposes only
|
||||
border: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
padding: 0;
|
||||
}
|
|
@ -103,8 +103,8 @@ urlpatterns = [
|
|||
path(
|
||||
# We embed the current user ID here, but we have a permission check
|
||||
# that ensures the user is who they say they are.
|
||||
"finish-user-setup/<int:pk>",
|
||||
views.FinishUserSetupView.as_view(),
|
||||
"finish-profile-setup/<int:pk>",
|
||||
views.FinishProfileSetupView.as_view(),
|
||||
name="finish-user-profile-setup",
|
||||
),
|
||||
path(
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
from django import forms
|
||||
from phonenumber_field.formfields import PhoneNumberField # type: ignore
|
||||
|
||||
|
||||
class FinishUserSetupForm(forms.Form):
|
||||
"""Form for adding or editing user information"""
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
# Remove the full name property
|
||||
if "full_name" in cleaned_data:
|
||||
# Delete the full name element as its purely decorative.
|
||||
# We include it as a normal Charfield for all the advantages
|
||||
# and utility that it brings, but we're playing pretend.
|
||||
del cleaned_data["full_name"]
|
||||
return cleaned_data
|
||||
|
||||
full_name = forms.CharField(
|
||||
label="Full name",
|
||||
error_messages={"required": "Enter your full name"},
|
||||
)
|
||||
first_name = forms.CharField(
|
||||
label="First name / given name",
|
||||
error_messages={"required": "Enter your first name / given name."},
|
||||
)
|
||||
middle_name = forms.CharField(
|
||||
required=False,
|
||||
label="Middle name (optional)",
|
||||
)
|
||||
last_name = forms.CharField(
|
||||
label="Last name / family name",
|
||||
error_messages={"required": "Enter your last name / family name."},
|
||||
)
|
||||
title = forms.CharField(
|
||||
label="Title or role in your organization",
|
||||
error_messages={
|
||||
"required": ("Enter your title or role in your organization (e.g., Chief Information Officer).")
|
||||
},
|
||||
)
|
||||
email = forms.EmailField(
|
||||
label="Organization email",
|
||||
required=False,
|
||||
max_length=None,
|
||||
)
|
||||
phone = PhoneNumberField(
|
||||
label="Phone",
|
||||
error_messages={"invalid": "Enter a valid 10-digit phone number.", "required": "Enter your phone number."},
|
||||
)
|
|
@ -55,6 +55,34 @@ class UserProfileForm(forms.ModelForm):
|
|||
"required": "Enter your email address in the required format, like name@example.com."
|
||||
}
|
||||
self.fields["phone"].error_messages["required"] = "Enter your phone number."
|
||||
self.domainInfo = None
|
||||
|
||||
DomainHelper.disable_field(self.fields["email"], disable_required=True)
|
||||
|
||||
|
||||
class FinishSetupProfileForm(UserProfileForm):
|
||||
"""Form for updating user profile."""
|
||||
|
||||
full_name = forms.CharField(required=True, label="Full name")
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
# Remove the full name property
|
||||
if "full_name" in cleaned_data:
|
||||
# Delete the full name element as its purely decorative.
|
||||
# We include it as a normal Charfield for all the advantages
|
||||
# and utility that it brings, but we're playing pretend.
|
||||
del cleaned_data["full_name"]
|
||||
return cleaned_data
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Override the inerited __init__ method to update the fields."""
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Set custom form label for email
|
||||
self.fields["email"].label = "Organization email"
|
||||
self.fields["title"].label = "Title or role in your organization"
|
||||
|
||||
# Define the "full_name" value
|
||||
if self.instance and hasattr(self.instance, 'full_name'):
|
||||
self.fields["full_name"].initial = self.instance.get_formatted_name()
|
||||
|
|
|
@ -102,13 +102,6 @@ class Contact(TimeStampedModel):
|
|||
names = [n for n in [self.first_name, self.middle_name, self.last_name] if n]
|
||||
return " ".join(names) if names else "Unknown"
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""
|
||||
Returns the full name (first_name, middle_name, last_name) of this contact.
|
||||
"""
|
||||
return self.get_formatted_name()
|
||||
|
||||
def has_contact_info(self):
|
||||
return bool(self.title or self.email or self.phone)
|
||||
|
||||
|
|
|
@ -63,24 +63,16 @@
|
|||
Your contact information
|
||||
</legend>
|
||||
|
||||
{# TODO: if an error is thrown here or edit clicked, show first last and middle fields #}
|
||||
{# Also todo: consolidate all of the scattered classes into this usa form one #}
|
||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-readonly padding-top-2" %}
|
||||
{% input_with_errors form.full_name %}
|
||||
{% endwith %}
|
||||
|
||||
<fieldset id="contact-full-name-fieldset" class="registrar-fieldset__contact display-none">
|
||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-readonly" %}
|
||||
<fieldset id="profile-name-fieldset" class="registrar-fieldset__contact display-none">
|
||||
{% input_with_errors form.first_name %}
|
||||
{% endwith %}
|
||||
|
||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-readonly padding-top-2" %}
|
||||
{% input_with_errors form.middle_name %}
|
||||
{% endwith %}
|
||||
|
||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-readonly padding-top-2"%}
|
||||
{% input_with_errors form.last_name %}
|
||||
{% endwith %}
|
||||
</fieldset>
|
||||
|
||||
{# This field doesn't have the readonly button but it has common design elements from it #}
|
|
@ -14,9 +14,6 @@ from .domain import (
|
|||
DomainInvitationDeleteView,
|
||||
DomainDeleteUserView,
|
||||
)
|
||||
from .user_profile import UserProfileView
|
||||
from .finish_user_setup import (
|
||||
FinishUserSetupView,
|
||||
)
|
||||
from .user_profile import UserProfileView, FinishProfileSetupView
|
||||
from .health import *
|
||||
from .index import *
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
from enum import Enum
|
||||
from waffle.decorators import waffle_flag
|
||||
from urllib.parse import quote
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from registrar.forms.finish_user_setup import FinishUserSetupForm
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.templatetags.url_helpers import public_site_url
|
||||
from registrar.views.utility.permission_views import ContactPermissionView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from registrar.models.utility.generic_helper import replace_url_queryparams, to_database, from_database
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseContactView(SuccessMessageMixin, ContactPermissionView):
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
"""Content of the returned success message"""
|
||||
return "Contact updated successfully."
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self._update_object_and_session(request)
|
||||
context = self.get_context_data(object=self.object)
|
||||
return self.render_to_response(context)
|
||||
|
||||
def _update_object_and_session(self, request):
|
||||
self.session = request.session
|
||||
|
||||
contact_pk = "contact:" + str(self.kwargs.get("pk"))
|
||||
cached_contact = self.session.get(contact_pk)
|
||||
|
||||
if cached_contact:
|
||||
self.object = cached_contact
|
||||
else:
|
||||
self.object = self.get_object()
|
||||
|
||||
self._refresh_session()
|
||||
|
||||
def _refresh_session(self):
|
||||
"""
|
||||
Set contact pk in the session cache
|
||||
"""
|
||||
contact_pk = "contact:" + str(self.kwargs.get("pk"))
|
||||
self.session[contact_pk] = self.object
|
||||
|
||||
|
||||
class ContactFormBaseView(BaseContactView, FormMixin):
|
||||
"""Adds a FormMixin to BaseContactView, and handles post"""
|
||||
|
||||
def form_invalid(self, form):
|
||||
# updates session cache with contact
|
||||
self._refresh_session()
|
||||
|
||||
# superclass has the redirect
|
||||
return super().form_invalid(form)
|
||||
|
||||
|
||||
class FinishUserSetupView(ContactFormBaseView):
|
||||
"""This view forces the user into providing additional details that
|
||||
we may have missed from Login.gov"""
|
||||
|
||||
template_name = "finish_contact_setup.html"
|
||||
form_class = FinishUserSetupForm
|
||||
model = Contact
|
||||
|
||||
redirect_type = None
|
||||
|
||||
class RedirectType(Enum):
|
||||
"""
|
||||
Enums for each type of redirection. Enforces behaviour on `get_redirect_url()`.
|
||||
|
||||
- HOME: We want to redirect to reverse("home")
|
||||
- BACK_TO_SELF: We want to redirect back to reverse("finish-user-profile-setup")
|
||||
- TO_SPECIFIC_PAGE: We want to redirect to the page specified in the queryparam "redirect"
|
||||
- COMPLETE_SETUP: Indicates that we want to navigate BACK_TO_SELF, but the subsequent
|
||||
redirect after the next POST should be either HOME or TO_SPECIFIC_PAGE
|
||||
"""
|
||||
|
||||
HOME = "home"
|
||||
BACK_TO_SELF = "back_to_self"
|
||||
COMPLETE_SETUP = "complete_setup"
|
||||
TO_SPECIFIC_PAGE = "domain_request"
|
||||
|
||||
def get_initial(self):
|
||||
"""The initial value for the form (which is a formset here)."""
|
||||
db_object = from_database(form_class=self.form_class, obj=self.object)
|
||||
return db_object
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["email_sublabel_text"] = self._email_sublabel_text()
|
||||
|
||||
if self.redirect_type == self.RedirectType.COMPLETE_SETUP:
|
||||
context["confirm_changes"] = True
|
||||
|
||||
return context
|
||||
|
||||
def _email_sublabel_text(self):
|
||||
"""Returns the lengthy sublabel for the email field"""
|
||||
help_url = public_site_url("help/account-management/#get-help-with-login.gov")
|
||||
return mark_safe(
|
||||
"We recommend using your work email for your .gov account. "
|
||||
"If the wrong email is displayed below, you’ll need to update your Login.gov account "
|
||||
f'and log back in. <a class="usa-link" href={help_url}>Get help with your Login.gov account.</a>'
|
||||
) # nosec
|
||||
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
"""Content of the returned success message"""
|
||||
return "Your profile has been successfully updated."
|
||||
|
||||
@waffle_flag("profile_feature")
|
||||
@method_decorator(csrf_protect)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
"""
|
||||
Handles dispatching of the view, applying CSRF protection and checking the 'profile_feature' flag.
|
||||
|
||||
This method sets the redirect type based on the 'redirect' query parameter,
|
||||
defaulting to BACK_TO_SELF if not provided.
|
||||
It updates the session with the redirect view name if the redirect type is TO_SPECIFIC_PAGE.
|
||||
|
||||
Returns:
|
||||
HttpResponse: The response generated by the parent class's dispatch method.
|
||||
"""
|
||||
|
||||
# Update redirect type based on the query parameter if present
|
||||
redirect_type = request.GET.get("redirect", self.RedirectType.BACK_TO_SELF)
|
||||
|
||||
all_redirect_types = [r.value for r in self.RedirectType]
|
||||
if redirect_type in all_redirect_types:
|
||||
self.redirect_type = self.RedirectType(redirect_type)
|
||||
else:
|
||||
# If the redirect type is undefined, then we assume that
|
||||
# we are specifying a particular page to redirect to.
|
||||
self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE
|
||||
|
||||
# Store the page that we want to redirect to for later use
|
||||
request.session["redirect_viewname"] = str(redirect_type)
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Form submission posts to this view.
|
||||
|
||||
This post method harmonizes using BaseContactView and FormMixin
|
||||
"""
|
||||
|
||||
# Set the current object in cache
|
||||
self._update_object_and_session(request)
|
||||
|
||||
form = self.get_form()
|
||||
|
||||
# Get the current form and validate it
|
||||
if form.is_valid():
|
||||
|
||||
completed_states = [self.RedirectType.TO_SPECIFIC_PAGE, self.RedirectType.HOME]
|
||||
if self.redirect_type in completed_states:
|
||||
self.request.user.finished_setup = True
|
||||
self.request.user.save()
|
||||
|
||||
if "contact_setup_save_button" in request.POST:
|
||||
# Logic for when the 'Save' button is clicked
|
||||
self.redirect_type = self.RedirectType.COMPLETE_SETUP
|
||||
elif "contact_setup_submit_button" in request.POST:
|
||||
if "redirect_viewname" in self.session:
|
||||
self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE
|
||||
else:
|
||||
self.redirect_type = self.RedirectType.HOME
|
||||
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Saves the current contact to the database, and if the user is complete
|
||||
with their setup, then we mark user.finished_setup to True."""
|
||||
completed_states = [self.RedirectType.TO_SPECIFIC_PAGE, self.RedirectType.HOME]
|
||||
if self.redirect_type in completed_states:
|
||||
self.request.user.finished_setup = True
|
||||
self.request.user.save()
|
||||
|
||||
to_database(form=form, obj=self.object)
|
||||
self._refresh_session()
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the nameservers page for the domain."""
|
||||
redirect_url = self.get_redirect_url()
|
||||
return redirect_url
|
||||
|
||||
def get_redirect_url(self):
|
||||
"""
|
||||
Returns a URL string based on the current value of self.redirect_type.
|
||||
|
||||
Depending on self.redirect_type, constructs a base URL and appends a
|
||||
'redirect' query parameter. Handles different redirection types such as
|
||||
HOME, BACK_TO_SELF, COMPLETE_SETUP, and TO_SPECIFIC_PAGE.
|
||||
|
||||
Returns:
|
||||
str: The full URL with the appropriate query parameters.
|
||||
"""
|
||||
|
||||
# These redirect types redirect to the same page
|
||||
self_redirect = [
|
||||
self.RedirectType.BACK_TO_SELF,
|
||||
self.RedirectType.COMPLETE_SETUP
|
||||
]
|
||||
|
||||
# Maps the redirect type to a URL
|
||||
base_url = ""
|
||||
try:
|
||||
if self.redirect_type in self_redirect:
|
||||
base_url = reverse("finish-user-profile-setup", kwargs={"pk": self.object.pk})
|
||||
elif self.redirect_type == self.RedirectType.TO_SPECIFIC_PAGE:
|
||||
# We only allow this session value to use viewnames,
|
||||
# because this restricts what can be redirected to.
|
||||
desired_view = self.session["redirect_viewname"]
|
||||
base_url = reverse(desired_view)
|
||||
else:
|
||||
base_url = reverse("home")
|
||||
except NoReverseMatch as err:
|
||||
logger.error(f"get_redirect_url -> Could not find the specified page. Err: {err}")
|
||||
|
||||
query_params = {}
|
||||
|
||||
# Quote cleans up the value so that it can be used in a url
|
||||
query_params["redirect"] = quote(self.redirect_type.value)
|
||||
|
||||
# Generate the full url from the given query params
|
||||
full_url = replace_url_queryparams(base_url, query_params)
|
||||
return full_url
|
||||
|
|
@ -2,18 +2,25 @@
|
|||
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
import logging
|
||||
from urllib.parse import quote
|
||||
|
||||
from django.contrib import messages
|
||||
from django.views.generic.edit import FormMixin
|
||||
from registrar.forms.user_profile import UserProfileForm
|
||||
from django.urls import reverse
|
||||
from registrar.forms.user_profile import UserProfileForm, FinishSetupProfileForm
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from registrar.models import (
|
||||
Contact,
|
||||
)
|
||||
from registrar.views.utility.permission_views import UserProfilePermissionView
|
||||
from waffle.decorators import flag_is_active, waffle_flag
|
||||
|
||||
from registrar.templatetags.url_helpers import public_site_url
|
||||
from registrar.models.utility.generic_helper import replace_url_queryparams
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -30,11 +37,16 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
|
|||
def get(self, request, *args, **kwargs):
|
||||
"""Handle get requests by getting user's contact object and setting object
|
||||
and form to context before rendering."""
|
||||
self.object = self.get_object()
|
||||
self._refresh_session_and_object(request)
|
||||
form = self.form_class(instance=self.object)
|
||||
context = self.get_context_data(object=self.object, form=form)
|
||||
return self.render_to_response(context)
|
||||
|
||||
def _refresh_session_and_object(self, request):
|
||||
"""Sets the current session to self.session and the current object to self.object"""
|
||||
self.session = request.session
|
||||
self.object = self.get_object()
|
||||
|
||||
@waffle_flag("profile_feature") # type: ignore
|
||||
def dispatch(self, request, *args, **kwargs): # type: ignore
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
@ -52,7 +64,7 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Handle post requests (form submissions)"""
|
||||
self.object = self.get_object()
|
||||
self._refresh_session_and_object(request)
|
||||
form = self.form_class(request.POST, instance=self.object)
|
||||
|
||||
if form.is_valid():
|
||||
|
@ -75,3 +87,171 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
|
|||
if hasattr(user, "contact"): # Check if the user has a contact instance
|
||||
return user.contact
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class FinishProfileSetupView(UserProfileView):
|
||||
"""This view forces the user into providing additional details that
|
||||
we may have missed from Login.gov"""
|
||||
|
||||
template_name = "finish_profile_setup.html"
|
||||
form_class = FinishSetupProfileForm
|
||||
model = Contact
|
||||
|
||||
redirect_type = None
|
||||
|
||||
class RedirectType(Enum):
|
||||
"""
|
||||
Enums for each type of redirection. Enforces behaviour on `get_redirect_url()`.
|
||||
|
||||
- HOME: We want to redirect to reverse("home")
|
||||
- BACK_TO_SELF: We want to redirect back to reverse("finish-user-profile-setup")
|
||||
- TO_SPECIFIC_PAGE: We want to redirect to the page specified in the queryparam "redirect"
|
||||
- COMPLETE_SETUP: Indicates that we want to navigate BACK_TO_SELF, but the subsequent
|
||||
redirect after the next POST should be either HOME or TO_SPECIFIC_PAGE
|
||||
"""
|
||||
|
||||
HOME = "home"
|
||||
BACK_TO_SELF = "back_to_self"
|
||||
COMPLETE_SETUP = "complete_setup"
|
||||
TO_SPECIFIC_PAGE = "domain_request"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["email_sublabel_text"] = self._email_sublabel_text()
|
||||
|
||||
if self.redirect_type == self.RedirectType.COMPLETE_SETUP:
|
||||
context["confirm_changes"] = True
|
||||
|
||||
return context
|
||||
|
||||
def _email_sublabel_text(self):
|
||||
"""Returns the lengthy sublabel for the email field"""
|
||||
help_url = public_site_url("help/account-management/#get-help-with-login.gov")
|
||||
return mark_safe(
|
||||
"We recommend using your work email for your .gov account. "
|
||||
"If the wrong email is displayed below, you’ll need to update your Login.gov account "
|
||||
f'and log back in. <a class="usa-link" href={help_url}>Get help with your Login.gov account.</a>'
|
||||
) # nosec
|
||||
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
"""Content of the returned success message"""
|
||||
return "Your profile has been successfully updated."
|
||||
|
||||
@method_decorator(csrf_protect)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
"""
|
||||
Handles dispatching of the view, applying CSRF protection and checking the 'profile_feature' flag.
|
||||
|
||||
This method sets the redirect type based on the 'redirect' query parameter,
|
||||
defaulting to BACK_TO_SELF if not provided.
|
||||
It updates the session with the redirect view name if the redirect type is TO_SPECIFIC_PAGE.
|
||||
|
||||
Returns:
|
||||
HttpResponse: The response generated by the parent class's dispatch method.
|
||||
"""
|
||||
|
||||
# Update redirect type based on the query parameter if present
|
||||
redirect_type = request.GET.get("redirect", self.RedirectType.BACK_TO_SELF)
|
||||
|
||||
all_redirect_types = [r.value for r in self.RedirectType]
|
||||
if redirect_type in all_redirect_types:
|
||||
self.redirect_type = self.RedirectType(redirect_type)
|
||||
else:
|
||||
# If the redirect type is undefined, then we assume that
|
||||
# we are specifying a particular page to redirect to.
|
||||
self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE
|
||||
|
||||
# Store the page that we want to redirect to for later use
|
||||
request.session["redirect_viewname"] = str(redirect_type)
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Form submission posts to this view.
|
||||
|
||||
This post method harmonizes using BaseContactView and FormMixin
|
||||
"""
|
||||
self._refresh_session_and_object(request)
|
||||
form = self.form_class(request.POST, instance=self.object)
|
||||
|
||||
# Get the current form and validate it
|
||||
if form.is_valid():
|
||||
|
||||
completed_states = [self.RedirectType.TO_SPECIFIC_PAGE, self.RedirectType.HOME]
|
||||
if self.redirect_type in completed_states:
|
||||
self.request.user.finished_setup = True
|
||||
self.request.user.save()
|
||||
|
||||
if "contact_setup_save_button" in request.POST:
|
||||
# Logic for when the 'Save' button is clicked
|
||||
self.redirect_type = self.RedirectType.COMPLETE_SETUP
|
||||
elif "contact_setup_submit_button" in request.POST:
|
||||
if "redirect_viewname" in self.session:
|
||||
self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE
|
||||
else:
|
||||
self.redirect_type = self.RedirectType.HOME
|
||||
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Saves the current contact to the database, and if the user is complete
|
||||
with their setup, then we mark user.finished_setup to True."""
|
||||
completed_states = [self.RedirectType.TO_SPECIFIC_PAGE, self.RedirectType.HOME]
|
||||
if self.redirect_type in completed_states:
|
||||
self.request.user.finished_setup = True
|
||||
self.request.user.save()
|
||||
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the nameservers page for the domain."""
|
||||
redirect_url = self.get_redirect_url()
|
||||
return redirect_url
|
||||
|
||||
def get_redirect_url(self):
|
||||
"""
|
||||
Returns a URL string based on the current value of self.redirect_type.
|
||||
|
||||
Depending on self.redirect_type, constructs a base URL and appends a
|
||||
'redirect' query parameter. Handles different redirection types such as
|
||||
HOME, BACK_TO_SELF, COMPLETE_SETUP, and TO_SPECIFIC_PAGE.
|
||||
|
||||
Returns:
|
||||
str: The full URL with the appropriate query parameters.
|
||||
"""
|
||||
|
||||
# These redirect types redirect to the same page
|
||||
self_redirect = [
|
||||
self.RedirectType.BACK_TO_SELF,
|
||||
self.RedirectType.COMPLETE_SETUP
|
||||
]
|
||||
|
||||
# Maps the redirect type to a URL
|
||||
base_url = ""
|
||||
try:
|
||||
if self.redirect_type in self_redirect:
|
||||
base_url = reverse("finish-user-profile-setup", kwargs={"pk": self.object.pk})
|
||||
elif self.redirect_type == self.RedirectType.TO_SPECIFIC_PAGE:
|
||||
# We only allow this session value to use viewnames,
|
||||
# because this restricts what can be redirected to.
|
||||
desired_view = self.session["redirect_viewname"]
|
||||
base_url = reverse(desired_view)
|
||||
else:
|
||||
base_url = reverse("home")
|
||||
except NoReverseMatch as err:
|
||||
logger.error(f"get_redirect_url -> Could not find the specified page. Err: {err}")
|
||||
|
||||
query_params = {}
|
||||
|
||||
# Quote cleans up the value so that it can be used in a url
|
||||
query_params["redirect"] = quote(self.redirect_type.value)
|
||||
|
||||
# Generate the full url from the given query params
|
||||
full_url = replace_url_queryparams(base_url, query_params)
|
||||
return full_url
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue