Compare commits

..

43 Commits

Author SHA1 Message Date
Alex Janousek
f9034511c7 Merge pull request #2113 from GSA/dependabot/npm_and_yarn/uswds/uswds-3.10.0
Bump @uswds/uswds from 3.9.0 to 3.10.0
2024-11-19 08:27:31 -05:00
Alex Janousek
1d2abf0491 Merge pull request #2121 from GSA/dependabot/npm_and_yarn/sass-embedded-1.81.0
Bump sass-embedded from 1.80.6 to 1.81.0
2024-11-19 08:27:20 -05:00
Alex Janousek
b0b2132c67 Merge pull request #2130 from GSA/dependabot/npm_and_yarn/rollup-4.27.3
Bump rollup from 4.24.4 to 4.27.3
2024-11-19 08:26:31 -05:00
Alex Janousek
aae1a0d46c Merge pull request #2131 from GSA/dependabot/npm_and_yarn/playwright-1.49.0
Bump playwright from 1.48.2 to 1.49.0
2024-11-19 08:26:15 -05:00
dependabot[bot]
a740183a76 Bump playwright from 1.48.2 to 1.49.0
Bumps [playwright](https://github.com/microsoft/playwright) from 1.48.2 to 1.49.0.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.48.2...v1.49.0)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-19 00:00:13 +00:00
dependabot[bot]
9faa0ed069 Bump rollup from 4.24.4 to 4.27.3
Bumps [rollup](https://github.com/rollup/rollup) from 4.24.4 to 4.27.3.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.24.4...v4.27.3)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-19 00:00:02 +00:00
Jonathan Bobel
0a50913e62 Merge pull request #2112 from GSA/2101-about-notify
About Notify - About pages
2024-11-18 13:20:39 -05:00
dependabot[bot]
dba031dd23 Bump sass-embedded from 1.80.6 to 1.81.0
Bumps [sass-embedded](https://github.com/sass/embedded-host-node) from 1.80.6 to 1.81.0.
- [Changelog](https://github.com/sass/embedded-host-node/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sass/embedded-host-node/compare/1.80.6...1.81.0)

---
updated-dependencies:
- dependency-name: sass-embedded
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-15 23:18:56 +00:00
Beverly Nguyen
7390b60f2a padding change 2024-11-15 11:45:57 -08:00
alexjanousekGSA
c432e434ae Updated url 2024-11-15 12:12:04 -05:00
alexjanousekGSA
5b48127155 Fixed linting error 2024-11-15 12:00:06 -05:00
alexjanousekGSA
2aa5dd0174 Added back removed code 2024-11-15 11:55:16 -05:00
Carlo Costino
2106f00c08 Merge pull request #2118 from GSA/ADMIN-2086_Update_README_First_User_Docs
ADMIN-2086: Updated documentation.
2024-11-15 11:21:21 -05:00
Cliff Hill
4b50dfc702 Updated documentation.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-15 08:44:32 -05:00
Beverly Nguyen
cd7df2f9d2 flake8 2024-11-14 16:25:37 -08:00
Beverly Nguyen
170e06aba0 merge main 2024-11-14 16:18:35 -08:00
Alex Janousek
63493f28f8 Merge pull request #2078 from GSA/2069-user-story-add-new-link-to-best-practices-page
Added link to new guidance page that enables navigating
2024-11-14 16:52:52 -05:00
Beverly Nguyen
55ae37ad80 note to add youtube video 2024-11-14 11:23:23 -08:00
alexjanousekGSA
70ecf8fa09 Added feature flag for route 2024-11-14 10:53:48 -05:00
dependabot[bot]
c5fa28d42b Bump @uswds/uswds from 3.9.0 to 3.10.0
Bumps [@uswds/uswds](https://github.com/uswds/uswds) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/uswds/uswds/releases)
- [Commits](https://github.com/uswds/uswds/compare/v3.9.0...v3.10.0)

---
updated-dependencies:
- dependency-name: "@uswds/uswds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-13 23:41:55 +00:00
Beverly Nguyen
3a52cba23e add testing 2024-11-13 15:02:35 -08:00
Beverly Nguyen
8d85da8a90 add testing 2024-11-13 15:00:40 -08:00
Carlo Costino
ad50568c10 Merge pull request #2111 from GSA/Disabling_verify_email_for_now
Ok, commenting out the check for emails for now.
2024-11-13 17:35:08 -05:00
Beverly Nguyen
50e7f3d33c first round of about content 2024-11-13 14:32:15 -08:00
Cliff Hill
9796d424b5 Flake8 is dumb.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-13 17:27:52 -05:00
Cliff Hill
d678659cbe Flake8 is annoying.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-13 17:23:57 -05:00
Cliff Hill
49932f6942 Ok, commenting out the check for emails for now.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-13 17:18:51 -05:00
Cliff Hill
0091fd0b31 Merge pull request #2110 from GSA/Fixing_verify_email_again
Re-fixing the verify email step.
2024-11-13 14:48:40 -05:00
Cliff Hill
683bf893c1 fixing things.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-13 14:34:34 -05:00
Steven Reilly
a95138f344 Merge pull request #2108 from GSA/ADMIN-2098_Fix_Login_For_Email_Verify_And_Expire_Redis_Stuff
Fixed email verify, put time limits on redis stuff.
2024-11-13 12:59:26 -05:00
Cliff Hill
cc5c4114e0 Fixed email verify, put time limits on redis stuff.
Signed-off-by: Cliff Hill <clifford.hill@gsa.gov>
2024-11-13 10:58:40 -05:00
alexjanousekGSA
3da5fb406e Added subnav to fix css 2024-11-13 10:30:06 -05:00
alexjanousekGSA
b9ef8ea0c0 Removed unused code 2024-11-13 10:26:06 -05:00
alexjanousekGSA
6ca902acd3 Added back guides because its needed 2024-11-13 10:18:12 -05:00
alexjanousekGSA
b8ea1d812a Fixed error 2024-11-13 10:01:33 -05:00
alexjanousekGSA
c4ee02f038 Removed unused navigation link 2024-11-13 09:52:37 -05:00
alexjanousekGSA
f6fbe1bd8d Fixed linting error 2024-11-12 13:07:57 -05:00
alexjanousekGSA
1a14becc9a Updated link name and route 2024-11-12 12:54:22 -05:00
alexjanousekGSA
13e9b12367 Renamed guides to best practices 2024-11-12 10:32:51 -05:00
alexjanousekGSA
5cbb1f3bef Updated route 2024-11-04 15:04:34 -05:00
alexjanousekGSA
5fa9172901 Fixing linting errors 2024-11-04 11:57:13 -05:00
alexjanousekGSA
e7c82b1fc3 Fixed indent 2024-11-04 11:50:29 -05:00
alexjanousekGSA
12c28682df Added link to new guidance page that enables navigating 2024-11-04 11:44:45 -05:00
20 changed files with 492 additions and 386 deletions

View File

@@ -161,7 +161,7 @@
"filename": "app/config.py",
"hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc",
"is_verified": false,
"line_number": 121,
"line_number": 125,
"is_secret": false
}
],
@@ -684,5 +684,5 @@
}
]
},
"generated_at": "2024-10-29T19:28:03Z"
"generated_at": "2024-11-14T15:53:44Z"
}

View File

@@ -372,15 +372,9 @@ After you have completed all setup steps, you will be unable to log in, because
will not be a user in the database to link to the login.gov account you are using. So
you will need to create that user in your database using the 'create-test-user' command.
Open two terminals pointing to the api project and then run these commands in the
respective terminals.
Open a terminal pointing to the api project and then run this command.
(Server 1)
env ALLOW_EXPIRED_API_TOKEN=1 make run-flask
(Server 2)
poetry run flask command create-admin-jwt | tail -n 1 | pbcopy
poetry run flask command create-test-user --admin=True;
```poetry run flask command create-test-user --admin=True```
Supply your name, email address, mobile number, and password when prompted. Make sure the email address
is the same one you are using in login.gov and make sure your phone number is in the format 5555555555.

View File

@@ -162,6 +162,17 @@ def _csp(config):
def create_app(application):
application.config["FEATURE_BEST_PRACTICES_ENABLED"] = (
os.getenv("FEATURE_BEST_PRACTICES_ENABLED", "false").lower() == "true"
)
@application.context_processor
def inject_feature_flags():
feature_best_practices_enabled = application.config[
"FEATURE_BEST_PRACTICES_ENABLED"
]
return dict(FEATURE_BEST_PRACTICES_ENABLED=feature_best_practices_enabled)
notify_environment = os.environ["NOTIFY_ENVIRONMENT"]
application.config.from_object(configs[notify_environment])

View File

@@ -897,3 +897,22 @@ li.linked-card:hover svg,
.usa-sidenav__item a {
display: block;
}
.about-icon-list {
display: flex;
width: 24px;
height: 24px;
padding: 2px 1px;
justify-content: center;
align-items: center;
margin-right: 4px;
}
.usa-icon-list__content{
padding-left: 0;
}
.indented-paragraph {
margin-left: calc(24px + 4px);
margin-top: 4px;
}

View File

@@ -91,6 +91,10 @@ class Config(object):
getenv("FEATURE_BEST_PRACTICES_ENABLED", "false") == "true"
)
FEATURE_ABOUT_PAGE_ENABLED = (
getenv("FEATURE_ABOUT_PAGE_ENABLED", "false") == "true"
)
def _s3_credentials_from_env(bucket_prefix):
return {

View File

@@ -10,6 +10,7 @@ from app.formatters import apply_html_class, convert_markdown_template
from app.main import main
from app.main.views.pricing import CURRENT_SMS_RATE
from app.main.views.sub_navigation_dictionaries import (
about_notify_nav,
best_practices_nav,
features_nav,
using_notify_nav,
@@ -18,14 +19,18 @@ from app.utils.user import user_is_logged_in
from notifications_utils.url_safe_token import generate_token
# Hook to check for guidance routes
# Hook to check for feature flags
@main.before_request
def check_guidance_feature():
current_app.logger.warning("best practices 1234")
current_app.logger.warning(current_app.config["FEATURE_BEST_PRACTICES_ENABLED"])
def check_feature_flags():
if (
request.path.startswith("/best-practices")
and not current_app.config["FEATURE_BEST_PRACTICES_ENABLED"]
request.path.startswith("/guides/best-practices")
and not current_app.config.get("FEATURE_BEST_PRACTICES_ENABLED", False)
):
abort(404)
if (
request.path.startswith("/about")
and not current_app.config.get("FEATURE_ABOUT_PAGE_ENABLED", False)
):
abort(404)
@@ -35,6 +40,8 @@ def index():
if current_user and current_user.is_authenticated:
return redirect(url_for("main.choose_account"))
ttl = 24 * 60 * 60
# make and store the state
state = generate_token(
str(request.remote_addr),
@@ -42,12 +49,12 @@ def index():
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state)
redis_client.set(state_key, state, ex=ttl)
# make and store the nonce
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce)
redis_client.set(nonce_key, nonce, ex=ttl)
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
if url is not None:
@@ -205,7 +212,7 @@ def trial_mode_new():
)
@main.route("/best-practices")
@main.route("/guides/best-practices")
@user_is_logged_in
def best_practices():
return render_template(
@@ -214,7 +221,7 @@ def best_practices():
)
@main.route("/best-practices/clear-goals")
@main.route("/guides/best-practices/clear-goals")
@user_is_logged_in
def clear_goals():
return render_template(
@@ -223,7 +230,7 @@ def clear_goals():
)
@main.route("/best-practices/rules-and-regulations")
@main.route("/guides/best-practices/rules-and-regulations")
@user_is_logged_in
def rules_and_regulations():
return render_template(
@@ -232,7 +239,7 @@ def rules_and_regulations():
)
@main.route("/best-practices/establish-trust")
@main.route("/guides/best-practices/establish-trust")
@user_is_logged_in
def establish_trust():
return render_template(
@@ -241,7 +248,7 @@ def establish_trust():
)
@main.route("/best-practices/write-for-action")
@main.route("/guides/best-practices/write-for-action")
@user_is_logged_in
def write_for_action():
return render_template(
@@ -250,7 +257,7 @@ def write_for_action():
)
@main.route("/best-practices/multiple-languages")
@main.route("/guides/best-practices/multiple-languages")
@user_is_logged_in
def multiple_languages():
return render_template(
@@ -259,7 +266,7 @@ def multiple_languages():
)
@main.route("/best-practices/benchmark-performance")
@main.route("/guides/best-practices/benchmark-performance")
@user_is_logged_in
def benchmark_performance():
return render_template(
@@ -268,7 +275,7 @@ def benchmark_performance():
)
@main.route("/using-notify/guidance")
@main.route("/guides/using-notify/guidance")
@user_is_logged_in
def guidance_index():
return render_template(
@@ -280,6 +287,14 @@ def guidance_index():
)
@main.route("/about")
def about_notify():
return render_template(
"views/about/about.html",
navigation_links=about_notify_nav(),
)
@main.route("/using-notify/guidance/create-and-send-messages")
@user_is_logged_in
def create_and_send_messages():

View File

@@ -10,12 +10,10 @@ from flask import (
stream_with_context,
url_for,
)
from flask_login import current_user
from app import current_service, job_api_client, notification_api_client
from app.main import main
from app.notify_client.api_key_api_client import KEY_TYPE_TEST
from app.s3_client.s3_csv_client import delete_report, report_upload
from app.utils import (
DELIVERED_STATUSES,
FAILURE_STATUSES,
@@ -146,36 +144,6 @@ def download_notifications_csv(service_id):
file_time = datetime.now().strftime("%Y-%m-%d %I:%M:%S %p")
file_time = f"{file_time} {get_user_preferred_timezone()}"
csv = generate_notifications_csv(
service_id=service_id,
job_id=None,
status=filter_args.get("status"),
page=request.args.get("page", 1),
page_size=10000,
format_for_csv=True,
template_type=filter_args.get("message_type"),
limit_days=service_data_retention_days,
)
# START asynchronous reporting block
csv_file = "".join(csv)
file_location = f"reports/{service_id}/{current_user.id}/{service_data_retention_days}/report.csv"
# TODO these are some capabilities we will probably need when
# report generation becomes asynchronous.
# old_content = report_download(file_location)
# current_app.logger.info(f"OLD CONTENT IS {old_content}")
# reports = get_downloadable_reports(current_user.id, service_id)
# TODO these are to support asynchronous report generation.
# Leaving them commented in so they get exercised.
delete_report(file_location)
report_upload(file_location, csv_file)
# END asynchronous reporting block
# TODO eventually we want to remove this, when reports become fully asynchronous
# The UI should be retrieving the report elsewhere via the download_report() method call
return Response(
stream_with_context(
generate_notifications_csv(

View File

@@ -25,7 +25,8 @@ from app.main.views.verify import activate_user
from app.models.user import User
from app.utils import hide_from_search_engines
from app.utils.login import get_id_token, is_safe_redirect_url
from app.utils.time import is_less_than_days_ago
# from app.utils.time import is_less_than_days_ago
from app.utils.user import is_gov_user
from notifications_utils.url_safe_token import generate_token
@@ -108,11 +109,15 @@ def _do_login_dot_gov(): # $ pragma: no cover
)
raise Exception(f"Could not login with login.gov {login_gov_error}")
elif code and state:
state_key = f"login-state-{unquote(state)}"
stored_state = unquote(redis_client.get(state_key).decode("utf8"))
if state != stored_state:
current_app.logger.error(f"State Error: {state} != {stored_state}")
abort(403)
verify_key = f"login-verify_email-{unquote(state)}"
verify_path = bool(redis_client.get(verify_key))
if not verify_path:
state_key = f"login-state-{unquote(state)}"
stored_state = unquote(redis_client.get(state_key).decode("utf8"))
if state != stored_state:
current_app.logger.error(f"State Error: {state} != {stored_state}")
abort(403)
# activate the user
try:
@@ -130,12 +135,17 @@ def _do_login_dot_gov(): # $ pragma: no cover
f"Retrieved user {user['id']} from db #notify-admin-1505"
)
# Check if the email needs to be revalidated
is_fresh_email = is_less_than_days_ago(
user["email_access_validated_at"], 90
)
if not is_fresh_email:
return verify_email(user, redirect_url)
# Temporary disabling of this until we figure out what is happening.
# # Check if the email needs to be revalidated
# is_fresh_email = is_less_than_days_ago(
# user["email_access_validated_at"], 90
# )
# if not is_fresh_email:
# # send email verify
# ttl = 24 * 60 * 60
# verify_key = f"login-verify_email-{unquote(state)}"
# redis_client.set(verify_key, state, ex=ttl)
# return verify_email(user, redirect_url)
usr = User.from_email_address(user["email_address"])
current_app.logger.info(f"activating user {usr.id} #notify-admin-1505")
@@ -209,17 +219,19 @@ def sign_in(): # pragma: no cover
return redirect(redirect_url)
return redirect(url_for("main.show_accounts_or_dashboard"))
ttl = 24 * 60 * 60
state = generate_token(
str(request.remote_addr),
current_app.config["SECRET_KEY"],
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state)
redis_client.set(state_key, state, ex=ttl)
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce)
redis_client.set(nonce_key, nonce, ex=ttl)
url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL")
# handle unit tests

View File

@@ -27,6 +27,10 @@ def using_notify_nav():
"name": "Get started",
"link": "main.get_started",
},
{
"name": "Guides",
"link": "main.best_practices",
},
{
"name": "Trial mode",
"link": "main.trial_mode_new",
@@ -101,3 +105,12 @@ def best_practices_nav():
"link": "main.benchmark_performance",
},
]
def about_notify_nav():
return [
{
"name": "About notify",
"link": "main.about_notify",
},
]

View File

@@ -46,6 +46,15 @@ class HeaderNavigation(Navigation):
"roadmap",
"security",
},
"best_practices": {
"best_practices",
"clear_goals",
"rules_and_regulations",
"establish_trust",
"write_for_action",
"multiple_languages",
"benchmark_performance"
},
"using_notify": {
"get_started",
"using_notify",

View File

@@ -41,6 +41,8 @@ class InviteApiClient(NotifyAdminAPIClient):
}
data = _attach_current_user(data)
ttl = 24 * 60 * 60
# make and store the state
state = generate_token(
str(request.remote_addr),
@@ -48,12 +50,12 @@ class InviteApiClient(NotifyAdminAPIClient):
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state)
redis_client.set(state_key, state, ex=ttl)
# make and store the nonce
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce) # save the nonce to redis.
redis_client.set(nonce_key, nonce, ex=ttl) # save the nonce to redis.
data["nonce"] = nonce # This is passed to api for the invite url.
data["state"] = state # This is passed to api for the invite url.
@@ -64,7 +66,7 @@ class InviteApiClient(NotifyAdminAPIClient):
invite_data_key = f"invitedata-{unquote(state)}"
redis_invite_data = resp["invite"]
redis_invite_data = json.dumps(redis_invite_data)
redis_client.set(invite_data_key, redis_invite_data)
redis_client.set(invite_data_key, redis_invite_data, ex=ttl)
return resp_data
@@ -97,6 +99,8 @@ class InviteApiClient(NotifyAdminAPIClient):
self.post(url=f"/service/{service_id}/invite/{invited_user_id}", data=data)
def resend_invite(self, service_id, invited_user_id):
ttl = 24 * 60 * 60
# make and store the state
state = generate_token(
str(request.remote_addr),
@@ -104,12 +108,12 @@ class InviteApiClient(NotifyAdminAPIClient):
current_app.config["DANGEROUS_SALT"],
)
state_key = f"login-state-{unquote(state)}"
redis_client.set(state_key, state)
redis_client.set(state_key, state, ex=ttl)
# make and store the nonce
nonce = secrets.token_urlsafe()
nonce_key = f"login-nonce-{unquote(nonce)}"
redis_client.set(nonce_key, nonce)
redis_client.set(nonce_key, nonce, ex=ttl)
data = {
"nonce": nonce,
@@ -122,7 +126,7 @@ class InviteApiClient(NotifyAdminAPIClient):
invite_data_key = f"invitedata-{unquote(state)}"
redis_invite_data = resp["invite"]
redis_invite_data = json.dumps(redis_invite_data)
redis_client.set(invite_data_key, redis_invite_data)
redis_client.set(invite_data_key, redis_invite_data, ex=ttl)
@cache.delete("service-{service_id}")
@cache.delete("user-{invited_user_id}")

View File

@@ -116,7 +116,7 @@ class UserApiClient(NotifyAdminAPIClient):
data["next"] = next_string
if code_type == "email":
data["email_auth_link_host"] = self.admin_url
endpoint = "/user/{0}/{1}-code".format(user_id, code_type)
endpoint = f"/user/{user_id}/{code_type}-code"
current_app.logger.warn(hilite(f"Sending verify_code {code_type} to {user_id}"))
self.post(endpoint, data=data)

View File

@@ -1,11 +1,9 @@
import os
import uuid
import boto3
from flask import current_app
from app.s3_client import (
AWS_CLIENT_CONFIG,
get_s3_contents,
get_s3_metadata,
get_s3_object,
@@ -65,70 +63,3 @@ def set_metadata_on_csv_upload(service_id, upload_id, **kwargs):
def get_csv_metadata(service_id, upload_id):
return get_s3_metadata(get_csv_upload(service_id, upload_id))
def report_upload(file_location, report_content):
bucket_name = current_app.config["CSV_UPLOAD_BUCKET"]["bucket"]
access_key = current_app.config["CSV_UPLOAD_BUCKET"]["access_key_id"]
secret_key = current_app.config["CSV_UPLOAD_BUCKET"]["secret_access_key"]
region = current_app.config["CSV_UPLOAD_BUCKET"]["region"]
utils_s3upload(
filedata=report_content,
region=region,
bucket_name=bucket_name,
file_location=file_location,
access_key=access_key,
secret_key=secret_key,
)
current_app.logger.info(f"Succcessfully uploaded report to {file_location}")
def report_download(file_location):
current_app.logger.info(f"Downloading report from {file_location}")
bucket_name = current_app.config["CSV_UPLOAD_BUCKET"]["bucket"]
access_key = current_app.config["CSV_UPLOAD_BUCKET"]["access_key_id"]
secret_key = current_app.config["CSV_UPLOAD_BUCKET"]["secret_access_key"]
region = current_app.config["CSV_UPLOAD_BUCKET"]["region"]
return get_s3_contents(
get_s3_object(bucket_name, file_location, access_key, secret_key, region)
)
def delete_report(file_location):
current_app.logger.info(f"Deleting report from {file_location}")
bucket_name = current_app.config["CSV_UPLOAD_BUCKET"]["bucket"]
access_key = current_app.config["CSV_UPLOAD_BUCKET"]["access_key_id"]
secret_key = current_app.config["CSV_UPLOAD_BUCKET"]["secret_access_key"]
region = current_app.config["CSV_UPLOAD_BUCKET"]["region"]
obj = get_s3_object(bucket_name, file_location, access_key, secret_key, region)
if obj is None:
return None
return obj.delete()
def get_downloadable_reports(user_id, service_id):
prefix = f"reports/{service_id}/{user_id}/"
bucket_name = current_app.config["CSV_UPLOAD_BUCKET"]["bucket"]
access_key = current_app.config["CSV_UPLOAD_BUCKET"]["access_key_id"]
secret_key = current_app.config["CSV_UPLOAD_BUCKET"]["secret_access_key"]
region = current_app.config["CSV_UPLOAD_BUCKET"]["region"]
session = boto3.Session(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
region_name=region,
)
s3 = session.client(
"s3",
config=AWS_CLIENT_CONFIG,
)
response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
object_keys = []
if "Contents" in response:
for obj in response["Contents"]:
object_keys.append(obj["Key"])
return object_keys

View File

@@ -1,32 +1,43 @@
{% if current_user.is_authenticated %}
{% set navigation = [
{"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active": header_navigation.is_selected('accounts-or-dashboard')},
{"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')},
{"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')},
{"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')}
] %}
{% set navigation = [
{"href": url_for("main.show_accounts_or_dashboard"), "text": "Current service", "active":
header_navigation.is_selected('accounts-or-dashboard')},
{"href": url_for('main.get_started'), "text": "Using Notify", "active": header_navigation.is_selected('using_notify')}
] %}
{% if current_user.platform_admin %}
{% set navigation = navigation + [{"href": url_for('main.platform_admin_splash_page'), "text": "Platform admin", "active": header_navigation.is_selected('platform-admin')}] %}
{% else %}
{% set navigation = navigation + [{"href": url_for('main.user_profile'), "text": "User profile", "active": header_navigation.is_selected('user-profile')}] %}
{% endif %}
{% if FEATURE_BEST_PRACTICES_ENABLED %}
{% set navigation = navigation + [{"href": url_for('main.best_practices'), "text": "Guides", "active":
header_navigation.is_selected('best_practices')}] %}
{% endif %}
{% if current_service %}
{% if current_user.has_permissions('manage_service') %}
{% set secondaryNavigation = [
{"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active": secondary_navigation.is_selected('settings')},
{"href": url_for('main.sign_out'), "text": "Sign out"}
] %}
{% else %}
{% set secondaryNavigation = [
{"href": url_for('main.sign_out'), "text": "Sign out"}
] %}
{% set navigation = navigation + [
{"href": url_for('main.features'), "text": "Features", "active": header_navigation.is_selected('features')},
{"href": url_for('main.support'), "text": "Contact us", "active": header_navigation.is_selected('support')}
] %}
{% endif %}
{% else %}
{% set secondaryNavigation = [{"href": url_for('main.sign_out'), "text": "Sign out"}] %}
{% endif %}
{% if current_user.platform_admin %}
{% set navigation = navigation + [{"href": url_for('main.platform_admin_splash_page'), "text": "Platform admin",
"active": header_navigation.is_selected('platform-admin')}] %}
{% else %}
{% set navigation = navigation + [{"href": url_for('main.user_profile'), "text": "User profile", "active":
header_navigation.is_selected('user-profile')}] %}
{% endif %}
{% if current_service %}
{% if current_user.has_permissions('manage_service') %}
{% set secondaryNavigation = [
{"href": url_for('main.service_settings', service_id=current_service.id), "text": "Settings", "active":
secondary_navigation.is_selected('settings')},
{"href": url_for('main.sign_out'), "text": "Sign out"}
] %}
{% else %}
{% set secondaryNavigation = [
{"href": url_for('main.sign_out'), "text": "Sign out"}
] %}
{% endif %}
{% else %}
{% set secondaryNavigation = [{"href": url_for('main.sign_out'), "text": "Sign out"}] %}
{% endif %}
{% endif %}
<header class="usa-header usa-header--extended">
@@ -36,12 +47,12 @@
<div class="logo-img display-flex">
<a href="/">
<span class="usa-sr-only">Notify.gov logo</span>
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo" class="usa-flag-logo margin-right-1">
<img src="{{ (asset_path | default('/static')) + 'images/notify-logo.svg' }}" alt="Notify.gov logo"
class="usa-flag-logo margin-right-1">
</a>
</div>
{% if navigation %}
<button type="button" class="usa-menu-btn">Menu</button>
<button type="button" class="usa-menu-btn">Menu</button>
{% endif %}
</div>
</div>
@@ -52,29 +63,29 @@
</button>
<ul class="usa-nav__primary usa-accordion margin-right-1">
{% for item in navigation %}
{% if item.href and item.text %}
<li class="usa-nav__primary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% if item.href and item.text %}
<li class="usa-nav__primary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value
in item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
</ul>
<div class="usa-nav__secondary margin-bottom-6">
<ul class="usa-nav__secondary-links">
{% if secondaryNavigation %}
{% for item in secondaryNavigation %}
{% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
{% for item in secondaryNavigation %}
{% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}">
<a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute,
value in item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span>
</a>
</li>
{% endif %}
{% endfor %}
{% endif %}
</ul>
</div>

View File

@@ -0,0 +1,77 @@
{% extends "base.html" %}
{% set page_title = "About notify" %}
{% block per_page_title %}
{{page_title}}
{% endblock %}
{% block content_column_content %}
<!-- {% with title=page_title %}{% include "components/best-practices/nav_breadcrumb.html" %}{% endwith %} -->
<section class="usa-prose">
<h1>{{page_title}}</h1>
<p>Notify.gov is a text messaging service built by and for the government. We help agencies communicate more
effectively with the people they serve. With Notify.gov, federal and federally-funded programs can send customized
text messages that make it possible to:</p>
<ul>
<li>Meet people where they are</li>
<li>More effectively deliver program outcomes</li>
<li>Save administrative costs</li>
<li>Implement <a href="https://digital.gov/resources/delivering-digital-first-public-experience/"
target="_blank">21st Century IDEA</a> and other directives</li>
</ul>
<p>Notify.gov is an easy-to-use, web-based platform. It requires no technical expertise or system integration — users
can create an account and get started within minutes. We take the security and privacy of messaging data seriously
by minimizing data retention and using modern encryption methods.</p>
<!-- add youtube video component here -->
<h2 class="padding-bottom-3">Product Highlights</h2>
{% set product_highlights = [
{
"svg_src": "#send",
"card_heading": "Send customized one-way customized messages",
"p_text": "Upload a file with recipient phone numbers and Notify.gov sends customized messages",
},
{
"svg_src": "#translate",
"card_heading": "Send in recipients preferred language",
"p_text": "Notify.gov supports more than 30 character sets to send messages in almost any language",
},
{
"svg_src": "#trending_up",
"card_heading": "See how messages perform",
"p_text": "Track how many messages youve sent and monitor delivery rates",
},
{
"svg_src": "#add",
"card_heading": "Create and manage multiple services within a single organization",
"p_text": "Set up individual workspaces for different texting services, allowing multiple teams or programs to manage
day-to-day texting operations across an organization",
},
{
"svg_src": "#people",
"card_heading": "Manage team member and permissions on each service",
"p_text": "Administrators can add users and control what they can do in Notify.gov",
}
] %}
<ul class="usa-icon-list">
{% for item in product_highlights %}
<li class="usa-icon-list__item">
<div class="usa-icon-list__content">
<div class="usa-icon-list__icon display-flex flex-align-start">
<svg aria-hidden="true" focusable="false" role="img" class="about-icon-list">
<use xlink:href="{{ asset_url('img/sprite.svg') }}{{ item.svg_src }}"></use>
</svg>
<b>{{item.card_heading}}</b>
</div>
<p class="indented-paragraph">{{item.p_text}}</p>
</div>
</li>
{% endfor %}
</ul>
<p><a href="/join-notify">See if Notify is right for you</a></p>
<p>Notify.gov is a product of the <a href="#" target="_blank">Public Benefits Studio</a>, a product accelerator inside
the federal government. </p>
</section>
{% endblock %}

View File

@@ -23,37 +23,37 @@ Best Practices
"svg_src": "goal",
"card_heading": "Establish clear goals",
"p_text": "Start with a singular purpose. Make explicit what you want to achieve.",
"link": "/best-practices/clear-goals"
"link": "/guides/best-practices/clear-goals"
},
{
"svg_src": "compliant",
"card_heading": "Follow rules & regulations",
"p_text": "Understand what is required when texting the public.",
"link": "/best-practices/rules-and-regulations"
"link": "/guides/best-practices/rules-and-regulations"
},
{
"svg_src": "trust",
"card_heading": "Establish trust",
"p_text": "Help your audience anticipate and welcome your texts.",
"link": "/best-practices/establish-trust"
"link": "/guides/best-practices/establish-trust"
},
{
"svg_src": "runner",
"card_heading": "Write texts that provoke action",
"p_text": "Help your audience know what to do with the information you send.",
"link": "/best-practices/write-for-action"
"link": "/guides/best-practices/write-for-action"
},
{
"svg_src": "language",
"card_heading": "Send texts in multiple languages",
"p_text": "What to know as you plan translated texts.",
"link": "/best-practices/multiple-languages"
"link": "/guides/best-practices/multiple-languages"
},
{
"svg_src": "chart",
"card_heading": "Measure performance with benchmarking",
"p_text": "Learn how effective your texting program can be.",
"link": "/best-practices/benchmark-performance"
"link": "/guides/best-practices/benchmark-performance"
}
] %}

375
package-lock.json generated
View File

@@ -12,7 +12,7 @@
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/stream": "^3.0.1",
"@uswds/uswds": "^3.9.0",
"@uswds/uswds": "^3.10.0",
"cbor-js": "0.1.0",
"d3": "^7.9.0",
"govuk_frontend_toolkit": "^9.0.1",
@@ -21,10 +21,10 @@
"hogan": "1.0.2",
"jquery": "3.7.1",
"morphdom": "^2.7.4",
"playwright": "^1.48.2",
"playwright": "^1.49.0",
"python": "^0.0.4",
"query-command-supported": "1.0.0",
"sass-embedded": "^1.80.6",
"sass-embedded": "^1.81.0",
"textarea-caret": "3.1.0",
"timeago": "1.6.7",
"vinyl-buffer": "^1.0.1",
@@ -50,7 +50,7 @@
"jest-environment-jsdom": "^29.2.2",
"jshint": "2.13.6",
"jshint-stylish": "2.2.1",
"rollup": "^4.24.4",
"rollup": "^4.27.3",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-node-resolve": "5.2.0"
},
@@ -2667,9 +2667,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz",
"integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz",
"integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==",
"cpu": [
"arm"
],
@@ -2679,9 +2679,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz",
"integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz",
"integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==",
"cpu": [
"arm64"
],
@@ -2691,9 +2691,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz",
"integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz",
"integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==",
"cpu": [
"arm64"
],
@@ -2703,9 +2703,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz",
"integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz",
"integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==",
"cpu": [
"x64"
],
@@ -2715,9 +2715,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz",
"integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz",
"integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==",
"cpu": [
"arm64"
],
@@ -2727,9 +2727,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz",
"integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz",
"integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==",
"cpu": [
"x64"
],
@@ -2739,9 +2739,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz",
"integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz",
"integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==",
"cpu": [
"arm"
],
@@ -2751,9 +2751,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz",
"integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz",
"integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==",
"cpu": [
"arm"
],
@@ -2763,9 +2763,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz",
"integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz",
"integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==",
"cpu": [
"arm64"
],
@@ -2775,9 +2775,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz",
"integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz",
"integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==",
"cpu": [
"arm64"
],
@@ -2787,9 +2787,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz",
"integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz",
"integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==",
"cpu": [
"ppc64"
],
@@ -2799,9 +2799,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz",
"integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz",
"integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==",
"cpu": [
"riscv64"
],
@@ -2811,9 +2811,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz",
"integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz",
"integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==",
"cpu": [
"s390x"
],
@@ -2823,9 +2823,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz",
"integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz",
"integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==",
"cpu": [
"x64"
],
@@ -2835,9 +2835,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz",
"integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz",
"integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==",
"cpu": [
"x64"
],
@@ -2847,9 +2847,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz",
"integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz",
"integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==",
"cpu": [
"arm64"
],
@@ -2859,9 +2859,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz",
"integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz",
"integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==",
"cpu": [
"ia32"
],
@@ -2871,9 +2871,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz",
"integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz",
"integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==",
"cpu": [
"x64"
],
@@ -3485,11 +3485,10 @@
}
},
"node_modules/@uswds/uswds": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.9.0.tgz",
"integrity": "sha512-8THm36j7iLjrDiI1D0C6b3hHsmM/Sy5Iiz+IjE+i/gYzVUMG9XVthxAZYonhU97Q1b079n6nYwlUmDSYowJecQ==",
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/@uswds/uswds/-/uswds-3.10.0.tgz",
"integrity": "sha512-LWFTQzp4e3kqtnD/Wsyfx9uGTkn5GEpzhscNWJMIsdWBGKtiu96QT99oRJUmcsB6HbGhR0Th0FtlK/Zzx2WghA==",
"dependencies": {
"object-assign": "4.1.1",
"receptor": "1.0.0",
"resolve-id-refs": "0.1.0"
},
@@ -8314,7 +8313,8 @@
"node_modules/immutable": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz",
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ=="
"integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==",
"dev": true
},
"node_modules/import-fresh": {
"version": "3.3.0",
@@ -12011,11 +12011,11 @@
}
},
"node_modules/playwright": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz",
"integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==",
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.0.tgz",
"integrity": "sha512-eKpmys0UFDnfNb3vfsf8Vx2LEOtflgRebl0Im2eQQnYMA4Aqd+Zw8bEOB+7ZKvN76901mRnqdsiOGKxzVTbi7A==",
"dependencies": {
"playwright-core": "1.48.2"
"playwright-core": "1.49.0"
},
"bin": {
"playwright": "cli.js"
@@ -12028,9 +12028,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.48.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz",
"integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==",
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.0.tgz",
"integrity": "sha512-R+3KKTQF3npy5GTiKH/T+kdhoJfJojjHESR1YEWhYuEKRVfVaxH3+4+GvXE5xyCngCxhxnykk0Vlah9v8fs3jA==",
"bin": {
"playwright-core": "cli.js"
},
@@ -12951,9 +12951,9 @@
"license": "Unlicense"
},
"node_modules/rollup": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz",
"integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==",
"version": "4.27.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz",
"integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==",
"dependencies": {
"@types/estree": "1.0.6"
},
@@ -12965,24 +12965,24 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.24.4",
"@rollup/rollup-android-arm64": "4.24.4",
"@rollup/rollup-darwin-arm64": "4.24.4",
"@rollup/rollup-darwin-x64": "4.24.4",
"@rollup/rollup-freebsd-arm64": "4.24.4",
"@rollup/rollup-freebsd-x64": "4.24.4",
"@rollup/rollup-linux-arm-gnueabihf": "4.24.4",
"@rollup/rollup-linux-arm-musleabihf": "4.24.4",
"@rollup/rollup-linux-arm64-gnu": "4.24.4",
"@rollup/rollup-linux-arm64-musl": "4.24.4",
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.4",
"@rollup/rollup-linux-riscv64-gnu": "4.24.4",
"@rollup/rollup-linux-s390x-gnu": "4.24.4",
"@rollup/rollup-linux-x64-gnu": "4.24.4",
"@rollup/rollup-linux-x64-musl": "4.24.4",
"@rollup/rollup-win32-arm64-msvc": "4.24.4",
"@rollup/rollup-win32-ia32-msvc": "4.24.4",
"@rollup/rollup-win32-x64-msvc": "4.24.4",
"@rollup/rollup-android-arm-eabi": "4.27.3",
"@rollup/rollup-android-arm64": "4.27.3",
"@rollup/rollup-darwin-arm64": "4.27.3",
"@rollup/rollup-darwin-x64": "4.27.3",
"@rollup/rollup-freebsd-arm64": "4.27.3",
"@rollup/rollup-freebsd-x64": "4.27.3",
"@rollup/rollup-linux-arm-gnueabihf": "4.27.3",
"@rollup/rollup-linux-arm-musleabihf": "4.27.3",
"@rollup/rollup-linux-arm64-gnu": "4.27.3",
"@rollup/rollup-linux-arm64-musl": "4.27.3",
"@rollup/rollup-linux-powerpc64le-gnu": "4.27.3",
"@rollup/rollup-linux-riscv64-gnu": "4.27.3",
"@rollup/rollup-linux-s390x-gnu": "4.27.3",
"@rollup/rollup-linux-x64-gnu": "4.27.3",
"@rollup/rollup-linux-x64-musl": "4.27.3",
"@rollup/rollup-win32-arm64-msvc": "4.27.3",
"@rollup/rollup-win32-ia32-msvc": "4.27.3",
"@rollup/rollup-win32-x64-msvc": "4.27.3",
"fsevents": "~2.3.2"
}
},
@@ -13091,16 +13091,17 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sass-embedded": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.80.6.tgz",
"integrity": "sha512-Og4aqBnaA3oJfIpHaLuNATAqzBRgUJDYJy2X15V59cot2wYOtiT/ciPnyuq1o7vpDEeOkHhEd+mSviSlXoETug==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.81.0.tgz",
"integrity": "sha512-uZQ2Faxb1oWBHpeSSzjxnhClbMb3QadN0ql0ZFNuqWOLUxwaVhrMlMhPq6TDPbbfDUjihuwrMCuy695Bgna5RA==",
"dependencies": {
"@bufbuild/protobuf": "^2.0.0",
"buffer-builder": "^0.2.0",
"colorjs.io": "^0.5.0",
"immutable": "^4.0.0",
"immutable": "^5.0.2",
"rxjs": "^7.4.0",
"supports-color": "^8.1.1",
"sync-child-process": "^1.0.2",
"varint": "^6.0.0"
},
"bin": {
@@ -13110,32 +13111,32 @@
"node": ">=16.0.0"
},
"optionalDependencies": {
"sass-embedded-android-arm": "1.80.6",
"sass-embedded-android-arm64": "1.80.6",
"sass-embedded-android-ia32": "1.80.6",
"sass-embedded-android-riscv64": "1.80.6",
"sass-embedded-android-x64": "1.80.6",
"sass-embedded-darwin-arm64": "1.80.6",
"sass-embedded-darwin-x64": "1.80.6",
"sass-embedded-linux-arm": "1.80.6",
"sass-embedded-linux-arm64": "1.80.6",
"sass-embedded-linux-ia32": "1.80.6",
"sass-embedded-linux-musl-arm": "1.80.6",
"sass-embedded-linux-musl-arm64": "1.80.6",
"sass-embedded-linux-musl-ia32": "1.80.6",
"sass-embedded-linux-musl-riscv64": "1.80.6",
"sass-embedded-linux-musl-x64": "1.80.6",
"sass-embedded-linux-riscv64": "1.80.6",
"sass-embedded-linux-x64": "1.80.6",
"sass-embedded-win32-arm64": "1.80.6",
"sass-embedded-win32-ia32": "1.80.6",
"sass-embedded-win32-x64": "1.80.6"
"sass-embedded-android-arm": "1.81.0",
"sass-embedded-android-arm64": "1.81.0",
"sass-embedded-android-ia32": "1.81.0",
"sass-embedded-android-riscv64": "1.81.0",
"sass-embedded-android-x64": "1.81.0",
"sass-embedded-darwin-arm64": "1.81.0",
"sass-embedded-darwin-x64": "1.81.0",
"sass-embedded-linux-arm": "1.81.0",
"sass-embedded-linux-arm64": "1.81.0",
"sass-embedded-linux-ia32": "1.81.0",
"sass-embedded-linux-musl-arm": "1.81.0",
"sass-embedded-linux-musl-arm64": "1.81.0",
"sass-embedded-linux-musl-ia32": "1.81.0",
"sass-embedded-linux-musl-riscv64": "1.81.0",
"sass-embedded-linux-musl-x64": "1.81.0",
"sass-embedded-linux-riscv64": "1.81.0",
"sass-embedded-linux-x64": "1.81.0",
"sass-embedded-win32-arm64": "1.81.0",
"sass-embedded-win32-ia32": "1.81.0",
"sass-embedded-win32-x64": "1.81.0"
}
},
"node_modules/sass-embedded-android-arm": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.80.6.tgz",
"integrity": "sha512-UeUKMTRsnz4/dh7IzvhjONxa4/jmVp539CHDd8VZOsqg9M3HcNJNIkUzQWbuwZ+nSlWrTuo7Tvn3XlypopCBzw==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.81.0.tgz",
"integrity": "sha512-NWEmIuaIEsGFNsIRa+5JpIpPJyZ32H15E85CNZqEIhhwWlk9UNw7vlOCmTH8MtabtnACwC/2NG8VyNa3nxKzUQ==",
"cpu": [
"arm"
],
@@ -13148,9 +13149,9 @@
}
},
"node_modules/sass-embedded-android-arm64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.80.6.tgz",
"integrity": "sha512-4rC4ZGM/k4ENVjLXnK3JTst8e8FI9MHSol2Fl7dCdYyJ3KLnlt4qL4AEYfU8zq1tcBb7CBOSZVR+CzCKubnXdg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.81.0.tgz",
"integrity": "sha512-I36P77/PKAHx6sqOmexO2iEY5kpsmQ1VxcgITZSOxPMQhdB6m4t3bTabfDuWQQmCrqqiNFtLQHeytB65bUqwiw==",
"cpu": [
"arm64"
],
@@ -13163,9 +13164,9 @@
}
},
"node_modules/sass-embedded-android-ia32": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.80.6.tgz",
"integrity": "sha512-Lxz2SXE2KdHnynuHF+D6flDvrd55/zaEAWUeka9MxEr6FmR66d8UBOIy5ETwCSUd//S/SE5Jl6oTnHppgD1zNA==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.81.0.tgz",
"integrity": "sha512-k8V1usXw30w1GVxvrteG1RzgYJzYQ9PfL2aeOqGdroBN7zYTD9VGJXTGcxA4IeeRxmRd7szVW2mKXXS472fh8g==",
"cpu": [
"ia32"
],
@@ -13178,9 +13179,9 @@
}
},
"node_modules/sass-embedded-android-riscv64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.80.6.tgz",
"integrity": "sha512-hKdxY/oOqB+JJhSoBTDM5DJO1j/xtxQgayh2cLCCUx37IQQe3SEdc3V2JFf/4mIo5peaS4cjqwwSATF+l2zaXg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.81.0.tgz",
"integrity": "sha512-RXlanyLXEpN/DEehXgLuKPsqT//GYlsGFxKXgRiCc8hIPAueFLQXKJmLWlL3BEtHgmFdbsStIu4aZCcb1hOFlQ==",
"cpu": [
"riscv64"
],
@@ -13193,9 +13194,9 @@
}
},
"node_modules/sass-embedded-android-x64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.80.6.tgz",
"integrity": "sha512-Eap2Fi3kTx/rVLBsOnOp5RYPr5+lFjTZ652zR24dmYFe9/sDgasakJIOPjOvD2bRuL9z0uWEY1AXVeeOPeZKrg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.81.0.tgz",
"integrity": "sha512-RQG0FxGQ1DERNyUDED8+BDVaLIjI+BNg8lVcyqlLZUrWY6NhzjwYEeiN/DNZmMmHtqDucAPNDcsdVUNQqsBy2A==",
"cpu": [
"x64"
],
@@ -13208,9 +13209,9 @@
}
},
"node_modules/sass-embedded-darwin-arm64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.80.6.tgz",
"integrity": "sha512-0mnAx8Vq6Gxj3PQt3imgITfK33hhqrSKpyHSuab71gZZni5opsdtoggq2JawW+1taRFTEZwbZJLKZ0MBDbwCCA==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.81.0.tgz",
"integrity": "sha512-gLKbsfII9Ppua76N41ODFnKGutla9qv0OGAas8gxe0jYBeAQFi/1iKQYdNtQtKi4mA9n5TQTqz+HHCKszZCoyA==",
"cpu": [
"arm64"
],
@@ -13223,9 +13224,9 @@
}
},
"node_modules/sass-embedded-darwin-x64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.80.6.tgz",
"integrity": "sha512-Ib20yNZFOrJ7YVT+ltoe+JQNKPcRclM3iLAK69XZZYcSeFM/72SCoQBAaVGIpT23dxDp7FXiE4lO602c3xTRwQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.81.0.tgz",
"integrity": "sha512-7uMOlT9hD2KUJCbTN2XcfghDxt/rc50ujjfSjSHjX1SYj7mGplkINUXvVbbvvaV2wt6t9vkGkCo5qNbeBhfwBg==",
"cpu": [
"x64"
],
@@ -13238,9 +13239,9 @@
}
},
"node_modules/sass-embedded-linux-arm": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.80.6.tgz",
"integrity": "sha512-QR0Q6TZox/ThuU2r9c0s3fKCgU2rXAEocpitdgxFp6tta+GsQlMFV3oON2unAa8Bwnuxkmf0YOaK0Oy/TwzkXw==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.81.0.tgz",
"integrity": "sha512-REqR9qM4RchCE3cKqzRy9Q4zigIV82SbSpCi/O4O3oK3pg2I1z7vkb3TiJsivusG/li7aqKZGmYOtAXjruGQDA==",
"cpu": [
"arm"
],
@@ -13253,9 +13254,9 @@
}
},
"node_modules/sass-embedded-linux-arm64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.80.6.tgz",
"integrity": "sha512-n5r98pBXawrQQKaxIYCMM1zDpnngsqxTkOrmvsYLFiAMCSbR0lWf/7sBB33k/Pm0D6dsbp3jpHilCoQNKI3jIw==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.81.0.tgz",
"integrity": "sha512-jy4bvhdUmqbyw1jv1f3Uxl+MF8EU/Y/GDx4w6XPJm4Ds+mwH/TwnyAwsxxoBhWfnBnW8q2ADy039DlS5p+9csQ==",
"cpu": [
"arm64"
],
@@ -13268,9 +13269,9 @@
}
},
"node_modules/sass-embedded-linux-ia32": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.80.6.tgz",
"integrity": "sha512-O6dWZdcOkryRdDCxVMGOeVowgblpDgVcAuRtZ1F1X7XfbpDriTQm64D+9vVZIrywYSPoJfQMJJ662cr0wUs9IQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.81.0.tgz",
"integrity": "sha512-ga/Jk4q5Bn1aC+iHJteDZuLSKnmBUiS3dEg1fnl/Z7GaHIChceKDJOw0zNaILRXI0qT2E1at9MwzoRaRA5Nn/g==",
"cpu": [
"ia32"
],
@@ -13283,9 +13284,9 @@
}
},
"node_modules/sass-embedded-linux-musl-arm": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.80.6.tgz",
"integrity": "sha512-X9FC8s8fvQGRiXc+eATlZ57N44Iq3nNa0M0ugi3ysdJwkaNYvOeS4QzBHKQAaw3QiTqdxTnLUHHVBkyzdCi9pw==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.81.0.tgz",
"integrity": "sha512-oWVUvQ4d5Kx1Md75YXZl5z1WBjc+uOhfRRqzkJ3nWc8tjszxJN+y/5EOJavhsNI3/2yoTt6eMXRTqDD9b0tWSQ==",
"cpu": [
"arm"
],
@@ -13298,9 +13299,9 @@
}
},
"node_modules/sass-embedded-linux-musl-arm64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.80.6.tgz",
"integrity": "sha512-VeUSHUi3MAsvOlg9QI4X/2j04h1659aE+7qKP/282CYBTrGkjFGSXZhIki9WKWDgIpDiSInRYXfQQRWhPhjCDg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.81.0.tgz",
"integrity": "sha512-hpntWf5kjkoxncA1Vh8vhsUOquZ8AROZKx0rQh7ZjSRs4JrYZASz1cfevPKaEM3wIim/nYa6TJqm0VqWsrERlA==",
"cpu": [
"arm64"
],
@@ -13313,9 +13314,9 @@
}
},
"node_modules/sass-embedded-linux-musl-ia32": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.80.6.tgz",
"integrity": "sha512-GqitS2Nab8ah0+wfCqaxW1hnI1piC08FimL6+lM9YWK5DbCOOF82IapbvJOy0feUmd/wNnHmyNTgE9h0zVMFdQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.81.0.tgz",
"integrity": "sha512-UEXUYkBuqTSwg5JNWiNlfMZ1Jx6SJkaEdx+fsL3Tk099L8cKSoJWH2EPz4ZJjNbyIMymrSdVfymheTeZ8u24xA==",
"cpu": [
"ia32"
],
@@ -13328,9 +13329,9 @@
}
},
"node_modules/sass-embedded-linux-musl-riscv64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.80.6.tgz",
"integrity": "sha512-ySs15z7QSRRQK/aByEEqaJLYW/sTpfynefNPZCtsVNVEzNRwy+DRpxNChtxo+QjKq97ocXETbdG5KLik7QOTJg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.81.0.tgz",
"integrity": "sha512-1D7OznytbIhx2XDHWi1nuQ8d/uCVR7FGGzELgaU//T8A9DapVTUgPKvB70AF1k4GzChR9IXU/WvFZs2hDTbaJg==",
"cpu": [
"riscv64"
],
@@ -13343,9 +13344,9 @@
}
},
"node_modules/sass-embedded-linux-musl-x64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.80.6.tgz",
"integrity": "sha512-DzeNqU/SN0mWFznoOH4RtVGcrg3Eoa41pUQhKMtrhNbCmIE1zNDunUiAEVTNpdHJF4nxf7ELUPXWmStM31CbUQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.81.0.tgz",
"integrity": "sha512-ia6VCTeVDQtBSMktXRFza1AZCt8/6aUoujot6Ugf4KmdytQqPJIHxkHaGftm5xwi9WdrMGYS7zgolToPijR11A==",
"cpu": [
"x64"
],
@@ -13358,9 +13359,9 @@
}
},
"node_modules/sass-embedded-linux-riscv64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.80.6.tgz",
"integrity": "sha512-AyoHJ3icV9xuJjq1YzJqpEj2XfiC/KBkVYTUrCELKiXP0DN1gi/BpUwZNCAgCM3CyEdMef4LQM/ztCYJxYzdyg==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.81.0.tgz",
"integrity": "sha512-KbxSsqu4tT1XbhZfJV/5NfW0VtJIGlD58RjqJqJBi8Rnjrx29/upBsuwoDWtsPV/LhoGwwU1XkSa9Q1ifCz4fQ==",
"cpu": [
"riscv64"
],
@@ -13373,9 +13374,9 @@
}
},
"node_modules/sass-embedded-linux-x64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.80.6.tgz",
"integrity": "sha512-EohsE9CEqx0ycylnsEj/0DNPG99Tb0qAVZspiAs5xHFCJjXOFfp3cRQu0BRf+lZ1b72IhPFXymzVtojvzUHb7g==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.81.0.tgz",
"integrity": "sha512-AMDeVY2T9WAnSFkuQcsOn5c29GRs/TuqnCiblKeXfxCSKym5uKdBl/N7GnTV6OjzoxiJBbkYKdVIaS5By7Gj4g==",
"cpu": [
"x64"
],
@@ -13388,9 +13389,9 @@
}
},
"node_modules/sass-embedded-win32-arm64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.80.6.tgz",
"integrity": "sha512-29wETQi1ykeVvpd4zMVokpQKFSOZskGJzZawuuNCdo7BHjHKIRDsqbz8YT1CewHPBshI0hfD21fenmjxYjGXPQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.81.0.tgz",
"integrity": "sha512-YOmBRYnygwWUmCoH14QbMRHjcvCJufeJBAp0m61tOJXIQh64ziwV4mjdqjS/Rx3zhTT4T+nulDUw4d3kLiMncA==",
"cpu": [
"arm64"
],
@@ -13403,9 +13404,9 @@
}
},
"node_modules/sass-embedded-win32-ia32": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.80.6.tgz",
"integrity": "sha512-1s3OpK2iTIfIL/a91QhAQnffsbuWfnsM8Lx4Fxt0f7ErnxjCV6q8MUFTV/UhcLtLyTFnPCA62DLjp2KGCjMI9A==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.81.0.tgz",
"integrity": "sha512-HFfr/C+uLJGGTENdnssuNTmXI/xnIasUuEHEKqI+2J0FHCWT5cpz3PGAOHymPyJcZVYGUG/7gIxIx/d7t0LFYw==",
"cpu": [
"ia32"
],
@@ -13418,9 +13419,9 @@
}
},
"node_modules/sass-embedded-win32-x64": {
"version": "1.80.6",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.80.6.tgz",
"integrity": "sha512-0pH4Zr9silHkcmLPC0ghnD3DI0vMsjA7dKvGR32/RbbjOSvHV5cDQRLiuVJAPp34dfMA7kJd1ysSchRdH0igAQ==",
"version": "1.81.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.81.0.tgz",
"integrity": "sha512-wxj52jDcIAwWcXb7ShZ7vQYKcVUkJ+04YM9l46jDY+qwHzliGuorAUyujLyKTE9heGD3gShJ3wPPC1lXzq6v9A==",
"cpu": [
"x64"
],
@@ -13445,6 +13446,11 @@
"node": ">=8"
}
},
"node_modules/sass-embedded/node_modules/immutable": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz",
"integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw=="
},
"node_modules/sass-embedded/node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
@@ -13994,6 +14000,25 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
"node_modules/sync-child-process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz",
"integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==",
"dependencies": {
"sync-message-port": "^1.0.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/sync-message-port": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz",
"integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/table": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",

View File

@@ -28,7 +28,7 @@
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/stream": "^3.0.1",
"@uswds/uswds": "^3.9.0",
"@uswds/uswds": "^3.10.0",
"cbor-js": "0.1.0",
"d3": "^7.9.0",
"govuk_frontend_toolkit": "^9.0.1",
@@ -37,10 +37,10 @@
"hogan": "1.0.2",
"jquery": "3.7.1",
"morphdom": "^2.7.4",
"playwright": "^1.48.2",
"playwright": "^1.49.0",
"python": "^0.0.4",
"query-command-supported": "1.0.0",
"sass-embedded": "^1.80.6",
"sass-embedded": "^1.81.0",
"textarea-caret": "3.1.0",
"timeago": "1.6.7",
"vinyl-buffer": "^1.0.1",
@@ -66,7 +66,7 @@
"jest-environment-jsdom": "^29.2.2",
"jshint": "2.13.6",
"jshint-stylish": "2.2.1",
"rollup": "^4.24.4",
"rollup": "^4.27.3",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-node-resolve": "5.2.0"
}

View File

@@ -17,6 +17,7 @@ EXCLUDED_ENDPOINTS = tuple(
map(
Navigation.get_endpoint_with_blueprint,
{
"about_notify",
"accept_invite",
"accept_org_invite",
"accessibility_statement",

26
urls.js
View File

@@ -13,13 +13,25 @@ const sublinks = [
{ label: 'Roadmap', path: '/features/roadmap' },
{ label: 'Security', path: '/features/security' },
{ label: 'Support', path: '/support' },
{ label: 'Best Practices', path: '/best-practices' },
{ label: 'Clear Goals', path: '/best-practices/clear-goals' },
{ label: 'Rules And Regulations', path: '/best-practices/rules-and-regulations' },
{ label: 'Establish Trust', path: '/best-practices/establish-trust' },
{ label: 'Write For Action', path: '/best-practices/write-for-action' },
{ label: 'Multiple Languages', path: '/best-practices/multiple-languages' },
{ label: 'Benchmark Performance', path: '/best-practices/benchmark-performance' },
{ label: 'Best Practices', path: '/guides/best-practices' },
{ label: 'Clear Goals', path: '/guides/best-practices/clear-goals' },
{
label: 'Rules And Regulations',
path: '/guides/best-practices/rules-and-regulations',
},
{ label: 'Establish Trust', path: '/guides/best-practices/establish-trust' },
{
label: 'Write For Action',
path: '/guides/best-practices/write-for-action',
},
{
label: 'Multiple Languages',
path: '/guides/best-practices/multiple-languages',
},
{
label: 'Benchmark Performance',
path: '/guides/best-practices/benchmark-performance',
},
// Add more links here as needed
];