This commit is contained in:
Rachid Mrad 2024-06-18 19:14:32 -04:00
parent 91a92ae11e
commit dde2b6830c
No known key found for this signature in database
10 changed files with 324 additions and 178 deletions

View file

@ -189,6 +189,7 @@ MIDDLEWARE = [
# Used for waffle feature flags
"waffle.middleware.WaffleMiddleware",
"registrar.registrar_middleware.CheckUserProfileMiddleware",
"registrar.registrar_middleware.CheckOrganizationMiddleware",
]
# application object used by Djangos built-in servers (e.g. `runserver`)

View file

@ -25,6 +25,7 @@ from registrar.views.domain_request import Step
from registrar.views.domain_requests_json import get_domain_requests_json
from registrar.views.domains_json import get_domains_json
from registrar.views.utility import always_404
from registrar.views.index_organizations import index_organizations
from api.views import available, get_current_federal, get_current_full
@ -58,6 +59,11 @@ for step, view in [
urlpatterns = [
path("", views.index, name="home"),
path(
"organization",
index_organizations,
name="home-organization",
),
path(
"admin/logout/",
RedirectView.as_view(pattern_name="logout", permanent=False),

View file

@ -2,6 +2,7 @@
Contains middleware used in settings.py
"""
import logging
from urllib.parse import parse_qs
from django.urls import reverse
from django.http import HttpResponseRedirect
@ -10,6 +11,7 @@ from waffle.decorators import flag_is_active
from registrar.models.utility.generic_helper import replace_url_queryparams
logger = logging.getLogger(__name__)
class NoCacheMiddleware:
"""
@ -119,3 +121,36 @@ class CheckUserProfileMiddleware:
else:
# Process the view as normal
return None
class CheckOrganizationMiddleware:
"""
"""
def __init__(self, get_response):
self.get_response = get_response
self.home_organization = reverse("home-organization")
self.home = reverse("home")
self.json1 = reverse("get_domains_json")
self.json2 = reverse("get_domain_requests_json")
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
current_path = request.path
logger.debug(f"Current path: {current_path}")
# Avoid infinite loop by skipping the redirect check on the home-organization URL
if current_path == self.home_organization or current_path == self.json1 or current_path == self.json2:
logger.debug("Skipping middleware check for home-organization URL")
return None
has_organization_feature_flag = flag_is_active(request, "organization_feature")
logger.debug(f"Flag is active: {has_organization_feature_flag}")
if has_organization_feature_flag:
logger.debug(f"Redirecting to {self.home_organization}")
return HttpResponseRedirect(self.home_organization)
return None

View file

@ -9,11 +9,13 @@
{% if user.is_authenticated %}
{# the entire logged in page goes here #}
{% block homepage_content %}
<div class="tablet:grid-col-11 desktop:grid-col-10 tablet:grid-offset-1">
{% block messages %}
{% include "includes/form_messages.html" %}
{% endblock %}
<h1>Manage your domains</h2>
<h1>Manage your domains</h1>
{% comment %}
IMPORTANT:
@ -27,153 +29,8 @@
</a>
</p>
<section class="section--outlined domains">
<div class="grid-row">
<div class="mobile:grid-col-12 desktop:grid-col-6">
<h2 id="domains-header" class="flex-6">Domains</h2>
</div>
<div class="mobile:grid-col-12 desktop:grid-col-6">
<section aria-label="Domains search component" class="flex-6 margin-y-2">
<form class="usa-search usa-search--small" method="POST" role="search">
{% csrf_token %}
<button class="usa-button usa-button--unstyled margin-right-2 domains__reset-button display-none" type="button">
Reset
</button>
<label class="usa-sr-only" for="domains__search-field">Search</label>
<input
class="usa-input"
id="domains__search-field"
type="search"
name="search"
placeholder="Search by domain name"
/>
<button class="usa-button" type="submit" id="domains__search-field-submit">
<img
src="{% static 'img/usa-icons-bg/search--white.svg' %}"
class="usa-search__submit-icon"
alt="Search"
/>
</button>
</form>
</section>
</div>
</div>
<div class="domains__table-wrapper display-none">
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked domains__table">
<caption class="sr-only">Your registered domains</caption>
<thead>
<tr>
<th data-sortable="name" scope="col" role="columnheader">Domain name</th>
<th data-sortable="expiration_date" scope="col" role="columnheader">Expires</th>
<th data-sortable="state_display" scope="col" role="columnheader">Status</th>
<th
scope="col"
role="columnheader"
>
<span class="usa-sr-only">Action</span>
</th>
</tr>
</thead>
<tbody>
<!-- AJAX will populate this tbody -->
</tbody>
</table>
<div
class="usa-sr-only usa-table__announcement-region"
aria-live="polite"
></div>
</div>
<div class="domains__no-data display-none">
<p>You don't have any registered domains.</p>
<p class="maxw-none clearfix">
<a href="https://get.gov/help/faq/#do-not-see-my-domain" class="float-right-tablet display-flex flex-align-start usa-link" target="_blank">
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="{%static 'img/sprite.svg'%}#help_outline"></use>
</svg>
Why don't I see my domain when I sign in to the registrar?
</a>
</p>
</div>
<div class="domains__no-search-results display-none">
<p>No results found for "<span class="domains__search-term"></span>"</p>
</div>
</section>
<nav aria-label="Pagination" class="usa-pagination flex-justify" id="domains-pagination">
<span class="usa-pagination__counter text-base-dark padding-left-2 margin-bottom-1">
<!-- Count will be dynamically populated by JS -->
</span>
<ul class="usa-pagination__list">
<!-- Pagination links will be dynamically populated by JS -->
</ul>
</nav>
<section class="section--outlined domain-requests">
<div class="grid-row">
<div class="mobile:grid-col-12 desktop:grid-col-6">
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
</div>
<div class="mobile:grid-col-12 desktop:grid-col-6">
<section aria-label="Domain requests search component" class="flex-6 margin-y-2">
<form class="usa-search usa-search--small" method="POST" role="search">
{% csrf_token %}
<button class="usa-button usa-button--unstyled margin-right-2 domain-requests__reset-button display-none" type="button">
Reset
</button>
<label class="usa-sr-only" for="domain-requests__search-field">Search</label>
<input
class="usa-input"
id="domain-requests__search-field"
type="search"
name="search"
placeholder="Search by domain name"
/>
<button class="usa-button" type="submit" id="domain-requests__search-field-submit">
<img
src="{% static 'img/usa-icons-bg/search--white.svg' %}"
class="usa-search__submit-icon"
alt="Search"
/>
</button>
</form>
</section>
</div>
</div>
<div class="domain-requests__table-wrapper display-none">
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked domain-requests__table">
<caption class="sr-only">Your domain requests</caption>
<thead>
<tr>
<th data-sortable="requested_domain__name" scope="col" role="columnheader">Domain name</th>
<th data-sortable="submission_date" scope="col" role="columnheader">Date submitted</th>
<th data-sortable="status" scope="col" role="columnheader">Status</th>
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
<!-- AJAX will conditionally add a th for delete actions -->
</tr>
</thead>
<tbody id="domain-requests-tbody">
<!-- AJAX will populate this tbody -->
</tbody>
</table>
<div
class="usa-sr-only usa-table__announcement-region"
aria-live="polite"
></div>
</div>
<div class="domain-requests__no-data display-none">
<p>You haven't requested any domains.</p>
</div>
<div class="domain-requests__no-search-results display-none">
<p>No results found for "<span class="domain-requests__search-term"></span>"</p>
</div>
</section>
<nav aria-label="Pagination" class="usa-pagination flex-justify" id="domain-requests-pagination">
<span class="usa-pagination__counter text-base-dark padding-left-2 margin-bottom-1">
<!-- Count will be dynamically populated by JS -->
</span>
<ul class="usa-pagination__list">
<!-- Pagination links will be dynamically populated by JS -->
</ul>
</nav>
{% include "includes/domains_table.html" %}
{% include "includes/domain_requests_table.html" %}
{# Note: Reimplement this after MVP #}
<!--
@ -192,6 +49,8 @@
</a>
</section>
-->
{% endblock %}
</div>
{% else %} {# not user.is_authenticated #}

View file

@ -0,0 +1,55 @@
{% extends 'home.html' %}
{% load static %}
{% block homepage_content %}
<div class="tablet:grid-col-12">
<div class="grid-row grid-gap">
<div class="tablet:grid-col-3">
{% include "organization_sidebar.html" %}
</div>
<div class="tablet:grid-col-9">
{% block messages %}
{% include "includes/form_messages.html" %}
{% endblock %}
<h1>Manage your domains</h1>
{% comment %}
IMPORTANT:
If this button is added on any other page, make sure to update the
relevant view to reset request.session["new_request"] = True
{% endcomment %}
<p class="margin-top-4">
<a href="{% url 'domain-request:' %}" class="usa-button"
>
Start a new domain request
</a>
</p>
{% include "includes/domains_table.html" %}
{% include "includes/domain_requests_table.html" %}
{# Note: Reimplement this after MVP #}
<!--
<section class="section--outlined tablet:grid-col-11 desktop:grid-col-10">
<h2>Archived domains</h2>
<p>You don't have any archived domains</p>
</section>
-->
<!-- Note: Uncomment below when this is being implemented post-MVP -->
<!-- <section class="tablet:grid-col-11 desktop:grid-col-10">
<h2 class="padding-top-1 mobile-lg:padding-top-3"> Export domains</h2>
<p>Download a list of your domains and their statuses as a csv file.</p>
<a href="{% url 'todo' %}" class="usa-button usa-button--outline">
Export domains as csv
</a>
</section>
-->
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,69 @@
{% load static %}
<section class="section--outlined domain-requests">
<div class="grid-row">
<div class="mobile:grid-col-12 desktop:grid-col-6">
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
</div>
<div class="mobile:grid-col-12 desktop:grid-col-6">
<section aria-label="Domain requests search component" class="flex-6 margin-y-2">
<form class="usa-search usa-search--small" method="POST" role="search">
{% csrf_token %}
<button class="usa-button usa-button--unstyled margin-right-2 domain-requests__reset-button display-none" type="button">
Reset
</button>
<label class="usa-sr-only" for="domain-requests__search-field">Search</label>
<input
class="usa-input"
id="domain-requests__search-field"
type="search"
name="search"
placeholder="Search by domain name"
/>
<button class="usa-button" type="submit" id="domain-requests__search-field-submit">
<img
src="{% static 'img/usa-icons-bg/search--white.svg' %}"
class="usa-search__submit-icon"
alt="Search"
/>
</button>
</form>
</section>
</div>
</div>
<div class="domain-requests__table-wrapper display-none">
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked domain-requests__table">
<caption class="sr-only">Your domain requests</caption>
<thead>
<tr>
<th data-sortable="requested_domain__name" scope="col" role="columnheader">Domain name</th>
<th data-sortable="submission_date" scope="col" role="columnheader">Date submitted</th>
<th data-sortable="status" scope="col" role="columnheader">Status</th>
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
<!-- AJAX will conditionally add a th for delete actions -->
</tr>
</thead>
<tbody id="domain-requests-tbody">
<!-- AJAX will populate this tbody -->
</tbody>
</table>
<div
class="usa-sr-only usa-table__announcement-region"
aria-live="polite"
></div>
</div>
<div class="domain-requests__no-data display-none">
<p>You haven't requested any domains.</p>
</div>
<div class="domain-requests__no-search-results display-none">
<p>No results found for "<span class="domain-requests__search-term"></span>"</p>
</div>
</section>
<nav aria-label="Pagination" class="usa-pagination flex-justify" id="domain-requests-pagination">
<span class="usa-pagination__counter text-base-dark padding-left-2 margin-bottom-1">
<!-- Count will be dynamically populated by JS -->
</span>
<ul class="usa-pagination__list">
<!-- Pagination links will be dynamically populated by JS -->
</ul>
</nav>

View file

@ -0,0 +1,81 @@
{% load static %}
<section class="section--outlined domains">
<div class="grid-row">
<div class="mobile:grid-col-12 desktop:grid-col-6">
<h2 id="domains-header" class="flex-6">Domains</h2>
</div>
<div class="mobile:grid-col-12 desktop:grid-col-6">
<section aria-label="Domains search component" class="flex-6 margin-y-2">
<form class="usa-search usa-search--small" method="POST" role="search">
{% csrf_token %}
<button class="usa-button usa-button--unstyled margin-right-2 domains__reset-button display-none" type="button">
Reset
</button>
<label class="usa-sr-only" for="domains__search-field">Search</label>
<input
class="usa-input"
id="domains__search-field"
type="search"
name="search"
placeholder="Search by domain name"
/>
<button class="usa-button" type="submit" id="domains__search-field-submit">
<img
src="{% static 'img/usa-icons-bg/search--white.svg' %}"
class="usa-search__submit-icon"
alt="Search"
/>
</button>
</form>
</section>
</div>
</div>
<div class="domains__table-wrapper display-none">
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked domains__table">
<caption class="sr-only">Your registered domains</caption>
<thead>
<tr>
<th data-sortable="name" scope="col" role="columnheader">Domain name</th>
<th data-sortable="expiration_date" scope="col" role="columnheader">Expires</th>
<th data-sortable="state_display" scope="col" role="columnheader">Status</th>
<th
scope="col"
role="columnheader"
>
<span class="usa-sr-only">Action</span>
</th>
</tr>
</thead>
<tbody>
<!-- AJAX will populate this tbody -->
</tbody>
</table>
<div
class="usa-sr-only usa-table__announcement-region"
aria-live="polite"
></div>
</div>
<div class="domains__no-data display-none">
<p>You don't have any registered domains.</p>
<p class="maxw-none clearfix">
<a href="https://get.gov/help/faq/#do-not-see-my-domain" class="float-right-tablet display-flex flex-align-start usa-link" target="_blank">
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="{%static 'img/sprite.svg'%}#help_outline"></use>
</svg>
Why don't I see my domain when I sign in to the registrar?
</a>
</p>
</div>
<div class="domains__no-search-results display-none">
<p>No results found for "<span class="domains__search-term"></span>"</p>
</div>
</section>
<nav aria-label="Pagination" class="usa-pagination flex-justify" id="domains-pagination">
<span class="usa-pagination__counter text-base-dark padding-left-2 margin-bottom-1">
<!-- Count will be dynamically populated by JS -->
</span>
<ul class="usa-pagination__list">
<!-- Pagination links will be dynamically populated by JS -->
</ul>
</nav>

View file

@ -0,0 +1,18 @@
{% load static url_helpers %}
<div class="margin-bottom-4 tablet:margin-bottom-0">
<nav aria-label="">
<ul class="usa-sidenav">
<li class="usa-sidenav__item">
<a href="#">
link 1
</a>
</li>
<li class="usa-sidenav__item">
<a href="#">
link 2
</a>
</li>
</ul>
</nav>
</div>

View file

@ -9,8 +9,11 @@ def index(request):
if request.user.is_authenticated:
# This is a django waffle flag which toggles features based off of the "flag" table
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
# This controls the creation of a new domain request in the wizard
request.session["new_request"] = True
print('homepage view')
return render(request, "home.html", context)

View file

@ -0,0 +1,19 @@
from django.shortcuts import render
from waffle.decorators import flag_is_active
def index_organizations(request):
"""This page is available to anyone without logging in."""
context = {}
if request.user.is_authenticated:
# This is a django waffle flag which toggles features based off of the "flag" table
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
# This controls the creation of a new domain request in the wizard
request.session["new_request"] = True
print('homepage organizations view')
return render(request, "home_organizations.html", context)