minimally works, requires cleanup

This commit is contained in:
David Kennedy 2024-06-19 14:26:36 -04:00
parent c020007d51
commit a6c4710777
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
7 changed files with 130 additions and 97 deletions

View file

@ -10,6 +10,8 @@ from registrar.models.utility.domain_helper import DomainHelper
class UserProfileForm(forms.ModelForm): class UserProfileForm(forms.ModelForm):
"""Form for updating user profile.""" """Form for updating user profile."""
redirect = forms.CharField(widget=forms.HiddenInput(), required=False)
class Meta: class Meta:
model = Contact model = Contact
fields = ["first_name", "middle_name", "last_name", "title", "email", "phone"] fields = ["first_name", "middle_name", "last_name", "title", "email", "phone"]

View file

@ -38,21 +38,6 @@ class CheckUserProfileMiddleware:
def __init__(self, get_response): def __init__(self, get_response):
self.get_response = get_response self.get_response = get_response
self.setup_page = reverse("finish-user-profile-setup")
self.profile_page = reverse("user-profile")
self.logout_page = reverse("logout")
self.regular_excluded_pages = [
self.setup_page,
self.logout_page,
"/admin",
]
self.other_excluded_pages = [
self.profile_page,
self.logout_page,
"/admin",
]
def __init__(self):
self.setup_page = reverse("finish-user-profile-setup") self.setup_page = reverse("finish-user-profile-setup")
self.profile_page = reverse("user-profile") self.profile_page = reverse("user-profile")
self.logout_page = reverse("logout") self.logout_page = reverse("logout")

View file

@ -18,7 +18,7 @@
completing your domain request might take around 15 minutes.</p> completing your domain request might take around 15 minutes.</p>
{% if has_profile_feature_flag %} {% if has_profile_feature_flag %}
<h2>How well reach you</h2> <h2>How well reach you</h2>
<p>While reviewing your domain request, we may need to reach out with questions. Well also email you when we complete our review If the contact information below is not correct, visit <a href="{% url 'user-profile' %}?return_to_request=True" class="usa-link">your profile</a> to make updates.</p> <p>While reviewing your domain request, we may need to reach out with questions. Well also email you when we complete our review If the contact information below is not correct, visit <a href="{% url 'user-profile' %}?redirect=domain-request:" class="usa-link">your profile</a> to make updates.</p>
{% include "includes/profile_information.html" with user=user%} {% include "includes/profile_information.html" with user=user%}
{% endif %} {% endif %}

View file

@ -33,6 +33,8 @@
Your contact information Your contact information
</legend> </legend>
<input type="hidden" name="redirect" value="{{ form.initial.redirect }}">
{% with show_edit_button=True show_readonly=True group_classes="usa-form-editable usa-form-editable--no-border padding-top-2" %} {% with show_edit_button=True show_readonly=True group_classes="usa-form-editable usa-form-editable--no-border padding-top-2" %}
{% input_with_errors form.full_name %} {% input_with_errors form.full_name %}
{% endwith %} {% endwith %}

View file

@ -19,6 +19,9 @@
<form class="usa-form usa-form--large" method="post" novalidate> <form class="usa-form usa-form--large" method="post" novalidate>
{% csrf_token %} {% csrf_token %}
{# Include the hidden 'redirect' field #}
<input type="hidden" name="redirect" value="{{ form.initial.redirect }}">
{% input_with_errors form.first_name %} {% input_with_errors form.first_name %}
{% input_with_errors form.middle_name %} {% input_with_errors form.middle_name %}

View file

@ -25,19 +25,13 @@ Edit your User Profile |
{% include "includes/form_errors.html" with form=form %} {% include "includes/form_errors.html" with form=form %}
{% if show_back_button %} {% if show_back_button %}
<a href="{% if not return_to_request %}{% url 'home' %}{% else %}{% url 'domain-request:' %}{% endif %}" class="breadcrumb__back"> <a href="{% url form.initial.redirect %}" class="breadcrumb__back">
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img"> <svg class="usa-icon" aria-hidden="true" focusable="false" role="img">
<use xlink:href="{% static 'img/sprite.svg' %}#arrow_back"></use> <use xlink:href="{% static 'img/sprite.svg' %}#arrow_back"></use>
</svg> </svg>
{% if not return_to_request %}
<p class="margin-left-05 margin-top-0 margin-bottom-0 line-height-sans-1"> <p class="margin-left-05 margin-top-0 margin-bottom-0 line-height-sans-1">
{{ profile_back_button_text }} {{ profile_back_button_text }}
</p> </p>
{% else %}
<p class="margin-left-05 margin-top-0 margin-bottom-0 line-height-sans-1">
Go back to your domain request
</p>
{% endif %}
</a> </a>
{% endif %} {% endif %}

View file

@ -9,6 +9,7 @@ from urllib.parse import parse_qs, unquote
from urllib.parse import quote from urllib.parse import quote
from django.contrib import messages from django.contrib import messages
from django.http import QueryDict
from django.views.generic.edit import FormMixin from django.views.generic.edit import FormMixin
from registrar.forms.user_profile import UserProfileForm, FinishSetupProfileForm from registrar.forms.user_profile import UserProfileForm, FinishSetupProfileForm
from django.urls import NoReverseMatch, reverse from django.urls import NoReverseMatch, reverse
@ -31,16 +32,48 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
Base View for the User Profile. Handles getting and setting the User Profile Base View for the User Profile. Handles getting and setting the User Profile
""" """
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 this page
- 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"
TO_SPECIFIC_PAGE = "domain_request"
BACK_TO_SELF = "back_to_self"
COMPLETE_SETUP = "complete_setup"
@classmethod
def get_all_redirect_types(cls) -> list[str]:
"""Returns the value of every redirect type defined in this enum."""
return [r.value for r in cls]
model = Contact model = Contact
template_name = "profile.html" template_name = "profile.html"
form_class = UserProfileForm form_class = UserProfileForm
base_view_name = "user-profile"
all_redirect_types = RedirectType.get_all_redirect_types()
redirect_type: RedirectType
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
"""Handle get requests by getting user's contact object and setting object """Handle get requests by getting user's contact object and setting object
and form to context before rendering.""" and form to context before rendering."""
self._refresh_session_and_object(request) #self._refresh_session_and_object(request)
form = self.form_class(instance=self.object) self.object = self.get_object()
context = self.get_context_data(object=self.object, form=form)
# Get the redirect parameter from the query string
redirect = request.GET.get('redirect', 'home')
logger.info(f"redirect value is {redirect}")
form = self.form_class(instance=self.object, initial={'redirect': redirect})
context = self.get_context_data(object=self.object, form=form, redirect=redirect)
if ( if (
hasattr(self.user, "finished_setup") hasattr(self.user, "finished_setup")
@ -63,8 +96,8 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
@waffle_flag("profile_feature") # type: ignore @waffle_flag("profile_feature") # type: ignore
def dispatch(self, request, *args, **kwargs): # type: ignore def dispatch(self, request, *args, **kwargs): # type: ignore
# Store the original queryparams to persist them # Store the original queryparams to persist them
query_params = request.META["QUERY_STRING"] # query_params = request.META["QUERY_STRING"]
request.session["query_params"] = query_params # request.session["query_params"] = query_params
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -73,10 +106,14 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
# This is a django waffle flag which toggles features based off of the "flag" table # This is a django waffle flag which toggles features based off of the "flag" table
context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature") context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature")
# The text for the back button on this page # Set the profile_back_button_text based on the redirect parameter
context["profile_back_button_text"] = "Go to manage your domains" if kwargs.get('redirect') == 'domain-request:':
context["show_back_button"] = False context["profile_back_button_text"] = "Go back to your request"
else:
context["profile_back_button_text"] = "Go to manage your domains"
# Show back button conditional on user having finished setup
context["show_back_button"] = False
if hasattr(self.user, "finished_setup") and self.user.finished_setup: if hasattr(self.user, "finished_setup") and self.user.finished_setup:
context["user_finished_setup"] = True context["user_finished_setup"] = True
context["show_back_button"] = True context["show_back_button"] = True
@ -84,21 +121,30 @@ class UserProfileView(UserProfilePermissionView, FormMixin):
return context return context
def get_success_url(self): def get_success_url(self):
"""Redirect to the user's profile page.""" """Redirect to the user's profile page with updated query parameters."""
query_params = {} # Get the redirect parameter from the form submission
if "query_params" in self.session: redirect_param = self.request.POST.get('redirect', None)
params = unquote(self.session["query_params"])
query_params = parse_qs(params)
# Preserve queryparams and add them back to the url # Initialize QueryDict with existing query parameters from current request
base_url = reverse("user-profile") query_params = QueryDict(mutable=True)
new_redirect = replace_url_queryparams(base_url, query_params, convert_list_to_csv=True) query_params.update(self.request.GET)
return new_redirect
# Update query parameters with the 'redirect' value from form submission
if redirect_param and redirect_param != 'home':
query_params['redirect'] = redirect_param
# Generate the URL with updated query parameters
base_url = reverse(self.base_view_name)
# Generate the full url from the given query params
full_url = replace_url_queryparams(base_url, query_params)
return full_url
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
"""Handle post requests (form submissions)""" """Handle post requests (form submissions)"""
self._refresh_session_and_object(request) #self._refresh_session_and_object(request)
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.object) form = self.form_class(request.POST, instance=self.object)
if form.is_valid(): if form.is_valid():
@ -133,80 +179,75 @@ class FinishProfileSetupView(UserProfileView):
"""This view forces the user into providing additional details that """This view forces the user into providing additional details that
we may have missed from Login.gov""" we may have missed from Login.gov"""
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 this page
- 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"
TO_SPECIFIC_PAGE = "domain_request"
BACK_TO_SELF = "back_to_self"
COMPLETE_SETUP = "complete_setup"
@classmethod
def get_all_redirect_types(cls) -> list[str]:
"""Returns the value of every redirect type defined in this enum."""
return [r.value for r in cls]
template_name = "finish_profile_setup.html" template_name = "finish_profile_setup.html"
form_class = FinishSetupProfileForm form_class = FinishSetupProfileForm
model = Contact model = Contact
all_redirect_types = RedirectType.get_all_redirect_types() base_view_name = "finish-user-profile-setup"
redirect_type: RedirectType
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
"""Extend get_context_data to include has_profile_feature_flag"""
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
# Hide the back button by default # Show back button conditional on user having finished setup
context["show_back_button"] = False context["show_back_button"] = False
if hasattr(self.user, "finished_setup") and self.user.finished_setup:
if self.redirect_type == self.RedirectType.COMPLETE_SETUP:
context["confirm_changes"] = True context["confirm_changes"] = True
if kwargs.get('redirect') == 'home':
if "redirect_viewname" not in self.session: context["profile_back_button_text"] = "Go to manage your domains"
context["show_back_button"] = True context["show_back_button"] = True
else: else:
context["going_to_specific_page"] = True context["going_to_specific_page"] = True
context["redirect_button_text"] = "Continue to your request" context["redirect_button_text"] = "Continue to your request"
return context return context
# def get_context_data(self, **kwargs):
@method_decorator(csrf_protect) # context = super().get_context_data(**kwargs)
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, # # Hide the back button by default
defaulting to BACK_TO_SELF if not provided. # context["show_back_button"] = False
It updates the session with the redirect view name if the redirect type is TO_SPECIFIC_PAGE.
Returns: # logger.info(f"self.redirect_type = {self.redirect_type}")
HttpResponse: The response generated by the parent class's dispatch method. # if self.redirect_type == self.RedirectType.COMPLETE_SETUP:
""" # context["confirm_changes"] = True
# Update redirect type based on the query parameter if present # if "redirect_viewname" not in self.session:
default_redirect_value = self.RedirectType.BACK_TO_SELF.value # context["show_back_button"] = True
redirect_value = request.GET.get("redirect", default_redirect_value) # else:
# context["going_to_specific_page"] = True
# context["redirect_button_text"] = "Continue to your request"
if redirect_value in self.all_redirect_types: # return context
# If the redirect value is a preexisting value in our enum, set it to that.
self.redirect_type = self.RedirectType(redirect_value)
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 # @method_decorator(csrf_protect)
request.session["redirect_viewname"] = str(redirect_value) # def dispatch(self, request, *args, **kwargs):
# """
# Handles dispatching of the view, applying CSRF protection and checking the 'profile_feature' flag.
return super().dispatch(request, *args, **kwargs) # 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
# default_redirect_value = self.RedirectType.BACK_TO_SELF.value
# redirect_value = request.GET.get("redirect", default_redirect_value)
# if redirect_value in self.all_redirect_types:
# # If the redirect value is a preexisting value in our enum, set it to that.
# self.redirect_type = self.RedirectType(redirect_value)
# 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_value)
# return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
"""Form submission posts to this view.""" """Form submission posts to this view."""
@ -217,17 +258,23 @@ class FinishProfileSetupView(UserProfileView):
if form.is_valid(): if form.is_valid():
if "contact_setup_save_button" in request.POST: if "contact_setup_save_button" in request.POST:
# Logic for when the 'Save' button is clicked # Logic for when the 'Save' button is clicked
self.redirect_type = self.RedirectType.COMPLETE_SETUP self.redirect_page = False
#self.redirect_type = self.RedirectType.COMPLETE_SETUP
elif "contact_setup_submit_button" in request.POST: elif "contact_setup_submit_button" in request.POST:
specific_redirect = "redirect_viewname" in self.session self.redirect_page = True
self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE if specific_redirect else self.RedirectType.HOME # specific_redirect = "redirect_viewname" in self.session
# self.redirect_type = self.RedirectType.TO_SPECIFIC_PAGE if specific_redirect else self.RedirectType.HOME
return self.form_valid(form) return self.form_valid(form)
else: else:
return self.form_invalid(form) return self.form_invalid(form)
def get_success_url(self): def get_success_url(self):
"""Redirect to the nameservers page for the domain.""" """Redirect to the nameservers page for the domain."""
return self.get_redirect_url() # Get the redirect parameter from the form submission
redirect_param = self.request.POST.get('redirect', None)
if self.redirect_page and redirect_param:
return reverse(redirect_param)
return super().get_success_url()
def get_redirect_url(self): def get_redirect_url(self):
""" """