Merge branch 'main' into sspj/domain-validation

This commit is contained in:
Seamus Johnston 2023-02-03 15:46:07 -06:00
commit 070f85c58e
No known key found for this signature in database
GPG key ID: 2F21225985069105
16 changed files with 881 additions and 554 deletions

932
src/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@uswds/uswds": "^3.1.0",
"@uswds/uswds": "^3.3.0",
"pa11y-ci": "^3.0.1",
"sass": "^1.54.8"
},

View file

@ -19,8 +19,9 @@ i.e.
@include u-padding-right('05');
----------------------------------------
*/
// USWDS tokens are a bit too coarse in their letter-spacing steps
$letter-space--xs: .0125em;
// Finer grained letterspacing adjustments
$letter-space--xs: .0125em;
@use "uswds-core" as *;
@ -29,35 +30,72 @@ $letter-space--xs: .0125em;
@include sr-only;
}
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.usa-logo {
margin-top: units(2);
}
.usa-logo__text {
@include typeset('sans', 'xl', 2);
color: color('primary-darker');
}
.usa-nav__primary {
margin-top: units(1);
}
h1 {
@include typeset('sans', '2xl', 2);
margin: 0 0 units(1);
margin: 0 0 units(2);
color: color('primary-darker');
}
h2 {
font-weight: font-weight('semibold');
line-height: line-height('heading', 3);
margin: units(4) 0 units(1);
&:first-of-type {
margin-top: units(2);
}
}
.register-form-step > h1 {
//align to top of sidebar on first page of the form
margin-top: units(-1);
}
//Tighter spacing when H2 is immediatly after H1
.register-form-step .usa-fieldset:first-of-type h2:first-of-type,
.register-form-step h1 + h2 {
margin-top: units(1);
}
.register-form-step h3 {
color: color('primary-dark');
letter-spacing: $letter-space--xs;
margin-top: units(3);
margin-bottom: 0;
+ p {
margin-top: units(0.5);
}
}
.register-form-step p {
.register-form-step h4 {
margin-bottom: 0;
+ p {
margin-top: units(0.5);
}
}
.register-form-step p,
.register-form-step .usa-list li,
.dashboard p
{
@include typeset('sans', 'sm', 5);
max-width: measure(5);
&:last-of-type {
margin-bottom: 0;
}
}
.register-form-step a {
@ -68,6 +106,10 @@ $letter-space--xs: .0125em;
}
}
.register-form-step .usa-label:first-of-type {
margin-top: units(1);
}
/* Make "placeholder" links visually obvious */
a[href$="todo"]::after {
background-color: yellow;
@ -99,9 +141,9 @@ a.breadcrumb__back {
.usa-icon {
flex-shrink: 0;
//align lock body to x-height
margin: units('2px') units(1) 0 0;
margin: units('2px') units(1) 0 0;
}
}
}
}
.stepnav {
@ -112,15 +154,169 @@ a.breadcrumb__back {
margin-top: units(1);
}
.review__step__name {
font-weight: font-weight('semibold');
.domain_example {
p {
margin-bottom: 0;
}
.usa-list {
margin-top: units(0.5);
}
}
footer {
//Workaround because USWDS units jump from 10 to 15
margin-top: units(10) + units(2);
.review__step {
margin-top: units(3);
&:first-of-type {
margin-top: units(4);
}
}
.review__step hr {
border: none; //reset
border-top: 1px solid color('primary-dark');
margin-top: 0;
margin-bottom: units(0.5);
}
.review__step__title a:visited {
color: color('primary');
}
.review__step__name {
color: color('primary-dark');
font-weight: font-weight('semibold');
margin-bottom: units(0.5);
}
/** ---- DASHBOARD ---- */
#wrapper.dashboard {
background-color: color('primary-lightest');
padding-top: units(5);
}
section.dashboard {
background-color: color('white');
border: 1px solid color('base-lighter');
border-radius: 4px;
padding: 0 units(2) units(3);
margin-top: units(3);
h2 {
margin-bottom: units(2);
}
p {
margin-bottom: 0;
}
.usa-table {
width: 100%;
a {
display: flex;
align-items: flex-start;
color: color('primary');
&:visited {
color: color('primary');
}
.usa-icon {
// align icon with x height
margin-top: units(0.5);
margin-right: units(0.5);
}
}
}
// Table on small mobile
.usa-table--stacked {
td, th {
padding: units(1) units(2) units(2px) 0;
border: none;
}
tr:first-child th:first-child {
border-top: none;
}
tr {
border-bottom: none;
border-top: 2px solid color('base-light');
margin-top: units(2);
&:first-child {
margin-top: 0;
}
}
td[data-label]:before,
th[data-label]:before {
color: color('primary-darker');
padding-bottom: units(2px);
}
}
@include at-media(mobile-lg) {
margin-top: units(5);
h2 {
margin-bottom: units(3);
}
.usa-table tr {
border: none;
}
.usa-table {
td, th {
border-bottom: 1px solid color('base-light');
}
thead th {
color: color('primary-darker');
border-bottom: 2px solid color('base-light');
}
tbody tr:last-of-type {
td, th {
border-bottom: 0;
}
}
td, th {
padding: units(2);
}
th:first-of-type {
padding-left: 0;
}
thead tr:first-child th:first-child {
border-top: none;
}
}
}
}
#wrapper {
padding-top: units(3);
padding-bottom: units(6) * 2 ; //Workaround because USWDS units jump from 10 to 15
}
footer {
border-top: 1px solid color('primary-darker');
}
.usa-footer__secondary-section {
background-color: color('primary-lightest');
}
abbr[title] {
// workaround for underlining abbr element
border-bottom: none;

View file

@ -26,8 +26,15 @@ in the form $setting: value,
/*----------------------------
# Banner Settings
-----------------------------*/
$theme-banner-background-color: "primary-darker",
$theme-banner-link-color: "primary-lighter",
$theme-banner-background-color: "primary-dark",
$theme-banner-link-color: default,
/*
# Footer Settings
*/
$theme-identifier-background-color: 'primary-darker',
$theme-identifier-identity-domain-color: 'base-lighter',
$theme-identifier-secondary-link-color: 'base-lighter',
/*----------------------------
@ -87,6 +94,8 @@ in the form $setting: value,
$theme-color-accent-cool: $dhs-light-blue-60,
$theme-color-accent-cool-dark: $dhs-light-blue-70,
$theme-color-accent-cool-light: $dhs-light-blue-40,
$theme-color-accent-cool-lighter: $dhs-light-blue-30,
$theme-color-accent-cool-lightest: $dhs-light-blue-15,
/*---------------------------
## Error state
@ -112,4 +121,14 @@ in the form $setting: value,
----------------------------*/
$theme-input-line-height: 5,
/*---------------------------
# Component settings
-----------------------------
## Sorted Table
----------------------------*/
$theme-table-sorted-header-background-color: "accent-cool-lighter",
$theme-table-sorted-background-color: "accent-cool-lightest",
$theme-table-sorted-icon-color: "primary-darker",
$theme-table-unsorted-icon-color: "primary",
);

View file

@ -3,7 +3,7 @@
{% block title %}Thank you for your domain request{% endblock %}
{% block content %}
<h1>Thank you!</h1>
<h1>Thank you</h1>
<p>
Thank you for your domain request. We'll email a copy of your request to you,
@ -14,9 +14,11 @@ your authorizing official, and any contacts you added.</p>
<ul>
<li> We'll review your request. This could take up to two weeks. During
this review we'll verify that your organization is eligible for a .gov domain, that
your authorizing official approves your request, and that your domain
meets our naming requirements.
this review we'll verify that your <ul>
<li>Organization is eligible for a .gov domain</li>
<li>Authorizing official approves your request</li>
<li>Domain meets our naming requirements</li>
</ul>
</li>
<li> You can <a href="{% url 'todo' %}"><del>check the
@ -27,14 +29,4 @@ your authorizing official, and any contacts you added.</p>
review.</li>
</ul>
<h2>Option to enter domain name server information</h2>
<p>Before your domain can be used we'll need information about your
domain name servers. If you have this information you can enter it now.
If you don't have it, that's okay. You can enter it later on the
<a href="{% url 'todo' %}"><del>manage your domains page</del></a>.
</p>
<p><a href="{% url 'todo' %}" class="usa-button">Enter DNS name servers</a></p>
{% endblock %}

View file

@ -21,7 +21,7 @@
organization.</p>
<p>Here are a few domain examples for your type of organization.</p>
<div class="domain-example">
<div class="domain_example">
{% include "includes/domain_example.html" %}
</div>
{% endblock %}

View file

@ -3,7 +3,7 @@
{% block form_fields %}
{% for step in steps.all|slice:":-1" %}
<section class="review__step margin-top-205">
<section class="review__step">
<hr />
<div class="review__step__title display-flex flex-justify">
<div class="review__step__value">

View file

@ -128,11 +128,9 @@
<div class="usa-navbar">
{% block logo %}
<div class="usa-logo" id="extended-logo">
<em class="usa-logo__text">
<a href="{% url 'home' %}" title="Home" aria-label="Home">
{% block site_name %}Home{% endblock %}
</a>
</em>
<a href="{% url 'home' %}">
<strong class="usa-logo__text" >.gov </strong>
</a>
</div>
{% endblock %}
<button type="button" class="usa-menu-btn">Menu</button>
@ -162,6 +160,8 @@
</div>
</header>
{% endblock banner %}
{% block wrapper %}
<div id="wrapper">
{% block messages %}
{% if messages %}
@ -184,6 +184,7 @@
{% block content_bottom %}{% endblock %}
</div>
{% endblock wrapper%}
{% include "includes/footer.html" %}
</div> <!-- /#wrapper -->

View file

@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block wrapper %}
<div id="wrapper" class="dashboard">
{% block messages %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}" {% endif %}>
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}
{% block section_nav %}{% endblock %}
{% block hero %}{% endblock %}
{% block content %}{% endblock %}
<div role="complementary">{% block complementary %}{% endblock %}</div>
{% block content_bottom %}{% endblock %}
</div>
{% endblock wrapper %}

View file

@ -1,59 +1,98 @@
{% extends 'base.html' %}
{% extends 'dashboard_base.html' %}
{% load static %}
{% block title %} Hello {% endblock %}
{% block hero %}
<section class="usa-hero">
<div class="usa-grid">
<div class="usa-hero-callout usa-section-dark">
<h1>
<span class="usa-hero-callout-alt">Welcome to the .gov registrar</span>
</h1>
</div>
</section>
{% endblock %}
{% block content %}
<main id="main-content" class="grid-container">
<p>This is the .gov registrar.</p>
{% if user.is_authenticated %}
{# the entire logged in page goes here #}
{% if domain_applications %}
<h2>Your domain applications</h2>
<table class="usa-table usa-table--borderless">
<caption class="sr-only">Your domain applications</caption>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for application in domain_applications %}
<tr>
<th>
<a href="{% url 'edit-application' application.pk %}">
<div class="tablet:grid-offset-1 desktop:grid-offset-2">
<h1>Manage your domains</h2>
<p><a href="{% url 'application:' %}" class="usa-button">Start a new domain request</a></p>
<section class="dashboard tablet:grid-col-11 desktop:grid-col-10">
<h2>Registered domains</h2>
<p>You don't have any registered domains yet</p>
</section>
<section class="dashboard tablet:grid-col-11 desktop:grid-col-10">
<h2>Active domain requests</h2>
{% if domain_applications %}
<table class="usa-table usa-table--borderless usa-table--stacked">
<caption class="sr-only">Your domain applications</caption>
<thead>
<tr>
<th data-sortable scope="col" role="columnheader">Domain name</th>
<th data-sortable scope="col" role="columnheader">Date created</th>
<th data-sortable scope="col" role="columnheader">Status</th>
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
</tr>
</thead>
<tbody>
{% for application in domain_applications %}
<tr>
<th th scope="row" role="rowheader" data-label="Domain name">
{{ application.requested_domain.name|default:"New domain request" }}
</a>
</th>
<td>{{ application.status }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</th>
<td data-sort-value="{{ application.created_at|date:"U" }}" data-label="Date created">{{ application.created_at|date }}</td>
<td data-label="Status">{{ application.status|title }}</td>
<td>
<a href="{% url 'edit-application' application.pk %}">
{% if application.status == "started" %}
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="{%static 'img/sprite.svg'%}#edit"></use>
</svg>
Edit <span class="usa-sr-only">{{ application.requested_domain.name|default:"New domain request" }} </span>
{% else %}
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
<use xlink:href="{%static 'img/sprite.svg'%}#settings"></use>
</svg>
Manage <span class="usa-sr-only">{{application.requested_domain.name}} </span>
{% endif %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div
class="usa-sr-only usa-table__announcement-region"
aria-live="polite"
></div>
{% else %}
<p>You don't have any active domain requests right now</p>
{% endif %}
<p><a href="{% url 'application:' %}" class="usa-button">Start a new domain request</a></p>
</section>
<section class="dashboard tablet:grid-col-11 desktop:grid-col-10">
<h2>Archived domains</h2>
<p>You don't have any archived domains</p>
</section>
<section class="tablet:grid-col-11 desktop:grid-col-10">
<h2 class="padding-top-1 mobile-lg:padding-top-3"> Export domains</h2>
<p>If you would like to analyze your list of domains further, you can download the list of domains and their statuses as csv file</p>
<a href="{% url 'todo' %}" class="usa-button usa-button--outline">
Export domains as csv
</a>
</section>
</div>
{% else %} {# not user.is_authenticated #}
{# the entire logged out page goes here #}
<p><a class="usa-button" href="{% url 'login' %}">
Sign in
</a></p>
{% endif %}
<p><a href="{% url 'application:' %}" class="usa-button">Apply</a></p>
<p><a href="{% url 'edit-profile' %}">Edit profile</a></p>
{% if user.is_staff %}
<p><a href="{% url 'admin:index' %}">CISA admin panel</a></p>
{% endif %}
<p><a href="{% url 'logout' %}">Click here to log out.</a></p>
{% else %}
<p><a href="{% url 'login' %}">Click here to log in.</a></p>
{% endif %}
</main>
{% endblock %}

View file

@ -44,6 +44,7 @@
<p>Domain requests from state legislatures and courts must be authorized by an agencys <strong>Chief Information Officer</strong> or <strong>highest-ranking executive</strong>.</p>
{% elif organization_type == 'tribal' %}
<p>Domain requests from federally-recognized tribal governments must be authorized by <strong>the leader of the tribe</strong>, as recognized by the as noted by the <a href="https://www.bia.gov/service/tribal-leaders-directory" class="usa-link"> Bureau of Indian Affairs.</a></p>
<p>Domain requests from federally-recognized tribal governments must be authorized by the leader of the tribe, as recognized by the <a href="https://www.bia.gov/service/tribal-leaders-directory" class="usa-link">Bureau of Indian Affairs.</a></p>
<p>Domain requests from state-recognized tribal governments must be authorized by the leader of the tribe, as determined by the states tribal recognition initiative.</p>
{% endif %}

View file

@ -8,12 +8,10 @@
{% elif federal_type == 'judicial' %}
<p><strong>Examples:</strong></p>
<p>
<ul class="usa-list">
<li> usprobation.gov </li>
<li> ustaxcourt.gov </li>
</ul>
</p>
{% elif federal_type == 'legislative' %}
<p><strong>Examples:</strong></p>

View file

@ -16,7 +16,7 @@
class="usa-footer__logo-img"
src="{% static 'img/dottedgov-round.svg' %}"
alt="dot gov registrar logo"
width="50px"
width="56px"
/>
</div>
</div>

View file

@ -25,7 +25,7 @@ class TestViews(TestCase):
"""Home page should be available without a login."""
response = self.client.get("/")
self.assertContains(response, "registrar", status_code=200)
self.assertContains(response, "log in")
self.assertContains(response, "Sign in")
def test_whoami_page_no_user(self):
"""Whoami page not accessible without a logged-in user."""
@ -69,7 +69,8 @@ class LoggedInTests(TestWithUser):
creator=self.user, requested_domain=site
)
response = self.client.get("/")
self.assertContains(response, "igorville.gov", count=1)
# count = 2 because it is also in screenreader content
self.assertContains(response, "igorville.gov", count=2)
# clean up
application.delete()

View file

@ -70,10 +70,10 @@ class ApplicationWizard(LoginRequiredMixin, TemplateView):
TITLES = {
Step.ORGANIZATION_TYPE: _("Type of organization"),
Step.TRIBAL_GOVERNMENT: _("Tribal government"),
Step.ORGANIZATION_FEDERAL: _("Type of organization Federal"),
Step.ORGANIZATION_ELECTION: _("Type of organization — Election board"),
Step.ORGANIZATION_FEDERAL: _("Type of organization: Federal"),
Step.ORGANIZATION_ELECTION: _("Type of organization: Election office"),
Step.ORGANIZATION_CONTACT: _("Organization name and mailing address"),
Step.TYPE_OF_WORK: _("Type of Work"),
Step.TYPE_OF_WORK: _("Type of work"),
Step.AUTHORIZING_OFFICIAL: _("Authorizing official"),
Step.CURRENT_SITES: _("Organization website"),
Step.DOTGOV_DOMAIN: _(".gov domain"),