mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-23 19:20:47 +02:00
portfolio org view
This commit is contained in:
parent
e8d93bcb8c
commit
203c01843a
5 changed files with 248 additions and 10 deletions
|
@ -10,3 +10,6 @@ from .domain import (
|
||||||
DomainDsdataFormset,
|
DomainDsdataFormset,
|
||||||
DomainDsdataForm,
|
DomainDsdataForm,
|
||||||
)
|
)
|
||||||
|
from .portfolio import (
|
||||||
|
PortfolioOrgAddressForm,
|
||||||
|
)
|
||||||
|
|
105
src/registrar/forms/portfolio.py
Normal file
105
src/registrar/forms/portfolio.py
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
"""Forms for portfolio."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from django import forms
|
||||||
|
from django.core.validators import RegexValidator
|
||||||
|
|
||||||
|
from ..models import DomainInformation, Portfolio
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PortfolioOrgAddressForm(forms.ModelForm):
|
||||||
|
"""Form for updating the portfolio org mailing address."""
|
||||||
|
|
||||||
|
zipcode = forms.CharField(
|
||||||
|
label="Zip code",
|
||||||
|
validators=[
|
||||||
|
RegexValidator(
|
||||||
|
"^[0-9]{5}(?:-[0-9]{4})?$|^$",
|
||||||
|
message="Enter a zip code in the required format, like 12345 or 12345-6789.",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Portfolio
|
||||||
|
fields = [
|
||||||
|
"address_line1",
|
||||||
|
"address_line2",
|
||||||
|
"city",
|
||||||
|
"state_territory",
|
||||||
|
"zipcode",
|
||||||
|
# "urbanization",
|
||||||
|
]
|
||||||
|
error_messages = {
|
||||||
|
"address_line1": {"required": "Enter the street address of your organization."},
|
||||||
|
"city": {"required": "Enter the city where your organization is located."},
|
||||||
|
"state_territory": {
|
||||||
|
"required": "Select the state, territory, or military post where your organization is located."
|
||||||
|
},
|
||||||
|
}
|
||||||
|
widgets = {
|
||||||
|
# We need to set the required attributed for State/territory
|
||||||
|
# because for this fields we are creating an individual
|
||||||
|
# instance of the Select. For the other fields we use the for loop to set
|
||||||
|
# the class's required attribute to true.
|
||||||
|
"address_line1": forms.TextInput,
|
||||||
|
"address_line2": forms.TextInput,
|
||||||
|
"city": forms.TextInput,
|
||||||
|
"state_territory": forms.Select(
|
||||||
|
attrs={
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
choices=DomainInformation.StateTerritoryChoices.choices,
|
||||||
|
),
|
||||||
|
# "urbanization": forms.TextInput,
|
||||||
|
}
|
||||||
|
|
||||||
|
# the database fields have blank=True so ModelForm doesn't create
|
||||||
|
# required fields by default. Use this list in __init__ to mark each
|
||||||
|
# of these fields as required
|
||||||
|
required = ["address_line1", "city", "state_territory", "zipcode"]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
for field_name in self.required:
|
||||||
|
self.fields[field_name].required = True
|
||||||
|
self.fields["state_territory"].widget.attrs.pop("maxlength", None)
|
||||||
|
self.fields["zipcode"].widget.attrs.pop("maxlength", None)
|
||||||
|
|
||||||
|
# self.is_federal = self.instance.generic_org_type == DomainRequest.OrganizationChoices.FEDERAL
|
||||||
|
# self.is_tribal = self.instance.generic_org_type == DomainRequest.OrganizationChoices.TRIBAL
|
||||||
|
|
||||||
|
# field_to_disable = None
|
||||||
|
# if self.is_federal:
|
||||||
|
# field_to_disable = "federal_agency"
|
||||||
|
# elif self.is_tribal:
|
||||||
|
# field_to_disable = "organization_name"
|
||||||
|
|
||||||
|
# if field_to_disable is not None:
|
||||||
|
# DomainHelper.disable_field(self.fields[field_to_disable], disable_required=True)
|
||||||
|
|
||||||
|
# def save(self, commit=True):
|
||||||
|
# """Override the save() method of the BaseModelForm."""
|
||||||
|
# if self.has_changed():
|
||||||
|
|
||||||
|
# if self.is_federal and not self._field_unchanged("federal_agency"):
|
||||||
|
# raise ValueError("federal_agency cannot be modified when the generic_org_type is federal")
|
||||||
|
# elif self.is_tribal and not self._field_unchanged("organization_name"):
|
||||||
|
# raise ValueError("organization_name cannot be modified when the generic_org_type is tribal")
|
||||||
|
|
||||||
|
# else:
|
||||||
|
# super().save()
|
||||||
|
|
||||||
|
# def _field_unchanged(self, field_name) -> bool:
|
||||||
|
# """
|
||||||
|
# Checks if a specified field has not changed between the old value
|
||||||
|
# and the new value.
|
||||||
|
|
||||||
|
# The old value is grabbed from self.initial.
|
||||||
|
# The new value is grabbed from self.cleaned_data.
|
||||||
|
# """
|
||||||
|
# old_value = self.initial.get(field_name, None)
|
||||||
|
# new_value = self.cleaned_data.get(field_name, None)
|
||||||
|
# return old_value == new_value
|
|
@ -1,8 +1,64 @@
|
||||||
{% extends 'portfolio_base.html' %}
|
{% extends 'portfolio_base.html' %}
|
||||||
|
{% load static field_helpers%}
|
||||||
|
|
||||||
|
{% block title %}Organization mailing address | {{ portfolio.name }} | {% endblock %}
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
{% block portfolio_content %}
|
{% block portfolio_content %}
|
||||||
<h1>Organization</h1>
|
<div class="grid-row grid-gap">
|
||||||
|
<div class="tablet:grid-col-3">
|
||||||
|
<p class="font-body-md margin-top-0 margin-bottom-2
|
||||||
|
text-primary-darker text-semibold"
|
||||||
|
>
|
||||||
|
<span class="usa-sr-only"> Portfolio name:</span> {{ portfolio }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% include 'portfolio_organization_sidebar.html' %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tablet:grid-col-9">
|
||||||
|
|
||||||
|
<h1>Organization</h1>
|
||||||
|
|
||||||
|
<p>The name of your federal agency will be publicly listed as the domain registrant.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The federal agency for your organization can’t be updated here.
|
||||||
|
To suggest an update, email <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% include "includes/form_errors.html" with form=form %}
|
||||||
|
|
||||||
|
{% include "includes/required_fields.html" %}
|
||||||
|
|
||||||
|
<form class="usa-form usa-form--large" method="post" novalidate id="form-container">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong class="text-primary display-block margin-bottom-1">Federal agency</strong>
|
||||||
|
{{ portfolio }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% input_with_errors form.address_line1 %}
|
||||||
|
|
||||||
|
{% input_with_errors form.address_line2 %}
|
||||||
|
|
||||||
|
{% input_with_errors form.city %}
|
||||||
|
|
||||||
|
{% input_with_errors form.state_territory %}
|
||||||
|
|
||||||
|
{% with add_class="usa-input--small" %}
|
||||||
|
{% input_with_errors form.zipcode %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="usa-button"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
23
src/registrar/templates/portfolio_organization_sidebar.html
Normal file
23
src/registrar/templates/portfolio_organization_sidebar.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{% load static url_helpers %}
|
||||||
|
|
||||||
|
<div class="margin-bottom-4 tablet:margin-bottom-0">
|
||||||
|
<nav aria-label="Domain sections">
|
||||||
|
<ul class="usa-sidenav">
|
||||||
|
<li class="usa-sidenav__item">
|
||||||
|
{% url 'portfolio-organization' portfolio_id=portfolio.id as url %}
|
||||||
|
<a href="{{ url }}"
|
||||||
|
{% if request.path == url %}class="usa-current"{% endif %}
|
||||||
|
>
|
||||||
|
Organization
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="usa-sidenav__item">
|
||||||
|
<a href="#"
|
||||||
|
>
|
||||||
|
Senior official
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
|
@ -1,4 +1,8 @@
|
||||||
|
import logging
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.contrib import messages
|
||||||
|
from registrar.forms.portfolio import PortfolioOrgAddressForm
|
||||||
from registrar.models.portfolio import Portfolio
|
from registrar.models.portfolio import Portfolio
|
||||||
from registrar.views.utility.permission_views import (
|
from registrar.views.utility.permission_views import (
|
||||||
PortfolioDomainRequestsPermissionView,
|
PortfolioDomainRequestsPermissionView,
|
||||||
|
@ -7,6 +11,10 @@ from registrar.views.utility.permission_views import (
|
||||||
)
|
)
|
||||||
from waffle.decorators import flag_is_active
|
from waffle.decorators import flag_is_active
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
from django.views.generic.edit import FormMixin
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
||||||
|
@ -42,17 +50,60 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
||||||
return render(request, "portfolio_requests.html", context)
|
return render(request, "portfolio_requests.html", context)
|
||||||
|
|
||||||
|
|
||||||
class PortfolioOrganizationView(PortfolioBasePermissionView, View):
|
class PortfolioOrganizationView(PortfolioBasePermissionView, FormMixin):
|
||||||
|
"""
|
||||||
|
View to handle displaying and updating the portfolio's organization details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
model = Portfolio
|
||||||
template_name = "portfolio_organization.html"
|
template_name = "portfolio_organization.html"
|
||||||
|
form_class = PortfolioOrgAddressForm
|
||||||
|
context_object_name = "portfolio"
|
||||||
|
|
||||||
def get(self, request, portfolio_id):
|
def get_context_data(self, **kwargs):
|
||||||
context = {}
|
"""Add additional context data to the template."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["has_profile_feature_flag"] = flag_is_active(self.request, "profile_feature")
|
||||||
|
context["has_organization_feature_flag"] = flag_is_active(self.request, "organization_feature")
|
||||||
|
return context
|
||||||
|
|
||||||
if self.request.user.is_authenticated:
|
def get_object(self, queryset=None):
|
||||||
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
"""Get the portfolio object based on the URL parameter."""
|
||||||
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
return get_object_or_404(Portfolio, id=self.kwargs.get("portfolio_id"))
|
||||||
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
|
||||||
context["portfolio"] = portfolio
|
def get_form_kwargs(self):
|
||||||
|
"""Include the instance in the form kwargs."""
|
||||||
|
kwargs = super().get_form_kwargs()
|
||||||
|
kwargs['instance'] = self.get_object()
|
||||||
|
return kwargs
|
||||||
|
|
||||||
return render(request, "portfolio_organization.html", context)
|
def get(self, request, *args, **kwargs):
|
||||||
|
"""Handle GET requests to display the form."""
|
||||||
|
self.object = self.get_object()
|
||||||
|
form = self.get_form()
|
||||||
|
return self.render_to_response(self.get_context_data(form=form))
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""Handle POST requests to process form submission."""
|
||||||
|
self.object = self.get_object()
|
||||||
|
form = self.get_form()
|
||||||
|
if form.is_valid():
|
||||||
|
return self.form_valid(form)
|
||||||
|
else:
|
||||||
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
"""Handle the case when the form is valid."""
|
||||||
|
self.object = form.save(commit=False)
|
||||||
|
self.object.creator = self.request.user
|
||||||
|
self.object.save()
|
||||||
|
messages.success(self.request, "The organization information for this portfolio has been updated.")
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def form_invalid(self, form):
|
||||||
|
"""Handle the case when the form is invalid."""
|
||||||
|
return self.render_to_response(self.get_context_data(form=form))
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
"""Redirect to the overview page for the portfolio."""
|
||||||
|
return reverse("portfolio-organization", kwargs={"portfolio_id": self.object.pk})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue