Merge pull request #1063 from GSA/1043-move-account-info-into-utility-nav

1043 move account info into utility nav
This commit is contained in:
Carlo Costino
2024-01-09 11:40:29 -05:00
committed by GitHub
15 changed files with 260 additions and 108 deletions

View File

@@ -89,6 +89,7 @@ from app.navigation import (
HeaderNavigation, HeaderNavigation,
MainNavigation, MainNavigation,
OrgNavigation, OrgNavigation,
SecondaryNavigation,
) )
from app.notify_client import InviteTokenError from app.notify_client import InviteTokenError
from app.notify_client.api_key_api_client import api_key_api_client from app.notify_client.api_key_api_client import api_key_api_client
@@ -129,6 +130,7 @@ navigation = {
"main_navigation": MainNavigation(), "main_navigation": MainNavigation(),
"header_navigation": HeaderNavigation(), "header_navigation": HeaderNavigation(),
"org_navigation": OrgNavigation(), "org_navigation": OrgNavigation(),
"secondary_navigation": SecondaryNavigation(),
} }

View File

@@ -22,16 +22,26 @@ i.e.
@use "uswds-core" as *; @use "uswds-core" as *;
.usa-header--extended .usa-logo { .usa-header--extended {
font-family: family("sans"); .usa-logo {
margin: units(4) 0; font-family: family("sans");
@include at-media-max('mobile-lg') { margin: units(4) 0;
margin: units(4) 0 units(4) units(2); @include at-media-max('mobile-lg') {
margin: units(4) 0 units(4) units(2);
}
img {
@include at-media($theme-header-min-width) {
width: 80px;
height: 70px;
}
}
} }
img { .usa-nav__secondary {
@include at-media($theme-header-min-width) { .usa-nav__link {
width: 80px; padding: 0;
height: 70px; &.usa-current {
text-decoration: underline;
}
} }
} }
} }
@@ -44,15 +54,12 @@ i.e.
&> .usa-nav__primary-item > a { &> .usa-nav__primary-item > a {
font-size: size("body", 4); font-size: size("body", 4);
} }
&> .usa-nav__primary-item:last-child { // &> .usa-nav__primary-item:last-child {
margin-left: auto; // margin-left: auto;
@include u-margin-right(-4); // @include u-margin-right(-4);
} // }
} }
.usa-nav__primary
h1 { h1 {
font-weight: bold !important; font-weight: bold !important;
} }
@@ -270,7 +277,7 @@ td.table-empty-message {
} }
.navigation-service.usa-breadcrumb { .navigation-service.usa-breadcrumb {
-bottom: 0; bottom: 0;
} }
// Dashboard // Dashboard

View File

@@ -87,39 +87,7 @@ class HeaderNavigation(Navigation):
"uploads", "uploads",
"view_job", "view_job",
"view_jobs", "view_jobs",
"confirm_edit_user_email",
"confirm_edit_user_mobile_number",
"edit_user_email",
"edit_user_mobile_number",
"edit_user_permissions",
"invite_user",
"manage_users",
"remove_user_from_service",
"usage", "usage",
"link_service_to_organization",
"service_add_email_reply_to",
"service_add_sms_sender",
"service_confirm_delete_email_reply_to",
"service_confirm_delete_sms_sender",
"service_edit_email_reply_to",
"service_edit_sms_sender",
"service_email_reply_to",
"service_name_change",
"service_set_auth_type",
"service_set_channel",
"send_files_by_email_contact_details",
"service_set_inbound_number",
"service_set_inbound_sms",
"service_set_international_sms",
"service_set_reply_to_email",
"service_set_sms_prefix",
"service_verify_reply_to_address",
"service_verify_reply_to_address_updates",
"service_settings",
"service_sms_senders",
"set_free_sms_allowance",
"set_message_limit",
"set_rate_limit",
}, },
"pricing": { "pricing": {
"how_to_pay", "how_to_pay",
@@ -236,6 +204,21 @@ class MainNavigation(Navigation):
"usage": { "usage": {
"usage", "usage",
}, },
"user-profile": {
"user_profile",
"user_profile_confirm_delete_mobile_number",
"user_profile_email",
"user_profile_email_authenticate",
"user_profile_email_confirm",
"user_profile_mobile_number",
"user_profile_mobile_number_authenticate",
"user_profile_mobile_number_confirm",
"user_profile_mobile_number_delete",
"user_profile_name",
"user_profile_password",
"user_profile_preferred_timezone",
"user_profile_disable_platform_admin_view",
},
"settings": { "settings": {
"link_service_to_organization", "link_service_to_organization",
"service_add_email_reply_to", "service_add_email_reply_to",
@@ -297,6 +280,58 @@ class CaseworkNavigation(Navigation):
} }
class SecondaryNavigation(Navigation):
mapping = {
"settings": {
"link_service_to_organization",
"service_add_email_reply_to",
"service_add_sms_sender",
"service_confirm_delete_email_reply_to",
"service_confirm_delete_sms_sender",
"service_edit_email_reply_to",
"service_edit_sms_sender",
"service_email_reply_to",
"service_name_change",
"service_set_auth_type",
"service_set_channel",
"send_files_by_email_contact_details",
"service_set_inbound_number",
"service_set_inbound_sms",
"service_set_international_sms",
"service_set_reply_to_email",
"service_set_sms_prefix",
"service_verify_reply_to_address",
"service_verify_reply_to_address_updates",
"service_settings",
"service_sms_senders",
"set_free_sms_allowance",
"set_message_limit",
"set_rate_limit",
"confirm_edit_user_email",
"confirm_edit_user_mobile_number",
"edit_user_email",
"edit_user_mobile_number",
"edit_user_permissions",
"invite_user",
"manage_users",
"remove_user_from_service",
"user_profile",
"user_profile_confirm_delete_mobile_number",
"user_profile_email",
"user_profile_email_authenticate",
"user_profile_email_confirm",
"user_profile_mobile_number",
"user_profile_mobile_number_authenticate",
"user_profile_mobile_number_confirm",
"user_profile_mobile_number_delete",
"user_profile_name",
"user_profile_password",
"user_profile_preferred_timezone",
"user_profile_disable_platform_admin_view",
},
}
class OrgNavigation(Navigation): class OrgNavigation(Navigation):
mapping = { mapping = {
"dashboard": { "dashboard": {

View File

@@ -58,26 +58,37 @@
"text": "Features", "text": "Features",
"active": header_navigation.is_selected('features') "active": header_navigation.is_selected('features')
}, },
{
"href": url_for('main.user_profile'),
"text": current_user.name,
"active": header_navigation.is_selected('user-profile')
},
{ {
"href": url_for('main.platform_admin_splash_page'), "href": url_for('main.platform_admin_splash_page'),
"text": "Platform admin", "text": "Platform admin",
"active": header_navigation.is_selected('platform-admin') "active": header_navigation.is_selected('platform-admin')
}, },
{
"href": url_for('main.sign_out'),
"text": "Sign out"
},
{ {
"href": url_for('main.support'), "href": url_for('main.support'),
"text": "Contact us", "text": "Contact us",
"active": header_navigation.is_selected('support') "active": header_navigation.is_selected('support')
} }
] %} ] %}
{% if current_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 %} {% else %}
{% set navigation = [ {% set navigation = [
{ {
@@ -104,13 +115,29 @@
"href": url_for('main.user_profile'), "href": url_for('main.user_profile'),
"text": "User profile", "text": "User profile",
"active": header_navigation.is_selected('user-profile') "active": header_navigation.is_selected('user-profile')
},
{
"href": url_for('main.sign_out'),
"text": "Sign out"
} }
] %} ] %}
{% endif %} {% if current_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 %}
{% endif %}
{% else %} {% else %}
<!-- Add navigation back after pilot --> <!-- Add navigation back after pilot -->
{# {% set navigation = [ {# {% set navigation = [
@@ -142,6 +169,7 @@
"productName": "Notify", "productName": "Notify",
"navigation": navigation, "navigation": navigation,
"navigationClasses": "govuk-header__navigation--end", "navigationClasses": "govuk-header__navigation--end",
"secondaryNavigation": secondaryNavigation,
"assetsPath": asset_path + "images" "assetsPath": asset_path + "images"
}) }} }) }}
{% endblock %} {% endblock %}
@@ -236,7 +264,7 @@
<span class="usa-sr-only">Please choose to extend your session or sign out. Your session will expire in 5 minutes or less.</span> <span class="usa-sr-only">Please choose to extend your session or sign out. Your session will expire in 5 minutes or less.</span>
</h2> </h2>
<div class="usa-prose"> <div class="usa-prose">
<p>You have been inactive for too long. <p>You have been inactive for too long.
Your session will expire in <span id="timeLeft" role="timer"></span>. Your session will expire in <span id="timeLeft" role="timer"></span>.
</p> </p>
</div> </div>
@@ -273,5 +301,3 @@
<!--<![endif]--> <!--<![endif]-->
{% endblock %} {% endblock %}

View File

@@ -76,23 +76,18 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</ul> </ul>
<div class="usa-nav__secondary"> <div class="usa-nav__secondary margin-bottom-2">
<ul class="usa-nav__secondary-links"> <ul class="usa-nav__secondary-links">
{% for item in params.secondaryNavigation %} {% for item in params.secondaryNavigation %}
{% if item.href and item.text %} {% if item.href and item.text %}
<li class="usa-nav__secondary-item{{ ' is-current' if item.active }}"> <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 <a class="usa-nav__link {{ ' usa-current' if item.active }}" href="{{ item.href }}" {% for attribute, value in
in item.attributes %} {{attribute}}="{{value}}" {% endfor %}> item.attributes %} {{attribute}}="{{value}}" {% endfor %}>
<span>{{ item.text }}</span> <span>{{ item.text }}</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<!-- <li class="usa-nav__secondary-item">
<a href="javascript:void(0)">
Sign in
</a>
</li> -->
</ul> </ul>
<!-- <section aria-label="Search component"> <!-- <section aria-label="Search component">
<form class="usa-search usa-search--small margin-bottom-2" role="search"> <form class="usa-search usa-search--small margin-bottom-2" role="search">

View File

@@ -13,13 +13,12 @@
{% if not current_user.has_permissions('view_activity') %} {% if not current_user.has_permissions('view_activity') %}
<li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li> <li class="usa-sidenav__item"><a class="{{ casework_navigation.is_selected('sent-messages') }}" href="{{ url_for('.view_notifications', service_id=current_service.id, status='sending,delivered,failed') }}">Sent messages</a></li>
{% endif %} {% endif %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('team-members') }}" href="{{ url_for('.manage_users', service_id=current_service.id) }}">Team members</a></li>
{% if current_user.has_permissions('manage_service', allow_org_user=True) %} {% if current_user.has_permissions('manage_service', allow_org_user=True) %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('usage') }}" href="{{ url_for('.usage', service_id=current_service.id) }}">Usage</a></li> <li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('usage') }}" href="{{ url_for('.usage', service_id=current_service.id) }}">Usage</a></li>
{% endif %} {% endif %}
{% if current_user.has_permissions('manage_api_keys', 'manage_service') %} <!-- {% if current_user.has_permissions('manage_api_keys', 'manage_service') %}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('settings') }}" href="{{ url_for('.service_settings', service_id=current_service.id) }}">Settings</a></li> <li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('settings') }}" href="{{ url_for('.service_settings', service_id=current_service.id) }}">Settings</a></li>
{% endif %} {% endif %} -->
{% if current_user.has_permissions('manage_api_keys') %} {% if current_user.has_permissions('manage_api_keys') %}
<!-- <li><a class="usa-link{{ main_navigation.is_selected('api-integration') }}" href="{{ url_for('.api_integration', service_id=current_service.id) }}">API integration</a></li> --> <!-- <li><a class="usa-link{{ main_navigation.is_selected('api-integration') }}" href="{{ url_for('.api_integration', service_id=current_service.id) }}">API integration</a></li> -->
{% endif %} {% endif %}

View File

@@ -0,0 +1,16 @@
{% if help %}
{% include 'partials/tour.html' %}
{% else %}
<nav class="nav">
<ul class="usa-sidenav">
{# {% if current_user.has_permissions() %} #}
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('settings') }}"
href="{{ url_for('main.service_settings', service_id=current_service.id) }}">General</a></li>
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('user-profile') }}"
href="{{ url_for('main.user_profile', service_id=current_service.id) }}">User profile</a></li>
<li class="usa-sidenav__item"><a class="{{ main_navigation.is_selected('team-members') }}"
href="{{ url_for('main.manage_users', service_id=current_service.id) }}">Team members</a></li>
{# {% endif %} #}
</ul>
</nav>
{% endif %}

View File

@@ -0,0 +1,34 @@
{% extends "admin_template.html" %}
{% block per_page_title %}
{% block service_page_title %}{% endblock %} {{ current_service.name }}
{% endblock %}
{% block main %}
<div class="grid-container">
<div class="grid-row margin-top-5">
{% if help %}
<div class="grid-col-3">
{% else %}
<div class="grid-col-3">
{% endif %}
{% include "settings_nav.html" %}
</div>
{% if help %}
<div class="grid-col-8">
{% else %}
<div class="grid-col-9 padding-left-4">
{% endif %}
{% block beforeContent %}
{% block backLink %}{% endblock %}
{% endblock %}
<main id="main-content" role="main" class="usa-prose site-prose margin-bottom-10">
{% block content %}
{% include 'flash_messages.html' %}
{% block maincolumn_content %}{% endblock %}
{% endblock %}
</main>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends "withnav_template.html" %} {% extends "settings_template.html" %}
{% from "components/tick-cross.html" import tick_cross %} {% from "components/tick-cross.html" import tick_cross %}
{% from "components/live-search.html" import live_search %} {% from "components/live-search.html" import live_search %}
{% from "components/components/button/macro.njk" import usaButton %} {% from "components/components/button/macro.njk" import usaButton %}
@@ -10,9 +10,9 @@
{% block maincolumn_content %} {% block maincolumn_content %}
<div class="button-flex-header"> <div class="button-flex-header">
<h1 class="font-body-xl margin-0"> <h1 class="font-body-2xl margin-0">
Team members Team members
</h1> </h1>
{% if current_user.has_permissions('manage_service') %} {% if current_user.has_permissions('manage_service') %}
{{ usaButton({ {{ usaButton({
"element": "a", "element": "a",

View File

@@ -1,4 +1,4 @@
{% extends "withnav_template.html" %} {% extends "settings_template.html" %}
{% from "components/banner.html" import banner_wrapper %} {% from "components/banner.html" import banner_wrapper %}
{% from "components/table.html" import mapping_table, row, settings_row, text_field, optional_text_field, edit_field, field, boolean_field with context %} {% from "components/table.html" import mapping_table, row, settings_row, text_field, optional_text_field, edit_field, field, boolean_field with context %}

View File

@@ -1,4 +1,4 @@
{% extends "withoutnav_template.html" %} {% extends "settings_template.html" %}
{% from "components/table.html" import list_table, row, field %} {% from "components/table.html" import list_table, row, field %}
{% from "components/table.html" import mapping_table, row, text_field, optional_text_field, edit_field, field, boolean_field with context %} {% from "components/table.html" import mapping_table, row, text_field, optional_text_field, edit_field, field, boolean_field with context %}

View File

@@ -125,7 +125,6 @@ def test_service_navigation_for_org_user(
( (
"Send messages", "Send messages",
"Sent messages", "Sent messages",
"Team members",
), ),
403, 403,
), ),
@@ -134,7 +133,6 @@ def test_service_navigation_for_org_user(
( (
"Send messages", "Send messages",
"Sent messages", "Sent messages",
"Team members",
"Usage", "Usage",
), ),
200, 200,

View File

@@ -363,7 +363,7 @@ def test_should_show_back_to_service_if_user_belongs_to_service(
): ):
mock_get_service.return_value = service_one mock_get_service.return_value = service_one
expected_page_text = ( expected_page_text = (
"Test Service Switch service " "Send messages " "Dashboard " "Team members" "Test Service Switch service " "Send messages " "Dashboard " "Usage"
) # TODO: set sidebar variables in common test module ) # TODO: set sidebar variables in common test module
page = client_request.get( page = client_request.get(

View File

@@ -1020,6 +1020,20 @@ def _test_dashboard_menu(client_request, mocker, usr, service, permissions):
return client_request.get("main.service_dashboard", service_id=service["id"]) return client_request.get("main.service_dashboard", service_id=service["id"])
def _test_settings_menu(client_request, mocker, usr, service, permissions):
usr["permissions"][str(service["id"])] = permissions
usr["services"] = [service["id"]]
mocker.patch("app.user_api_client.check_verify_code", return_value=(True, ""))
mocker.patch(
"app.service_api_client.get_services", return_value={"data": [service]}
)
mocker.patch("app.user_api_client.get_user", return_value=usr)
mocker.patch("app.user_api_client.get_user_by_email", return_value=usr)
mocker.patch("app.service_api_client.get_service", return_value={"data": service})
client_request.login(usr)
return client_request.get("main.service_dashboard", service_id=service["id"])
def test_menu_send_messages( def test_menu_send_messages(
client_request, client_request,
mocker, mocker,
@@ -1051,11 +1065,8 @@ def test_menu_send_messages(
) )
in page in page
) )
# assert url_for('main.uploads', service_id=service_one['id']) in page assert url_for("main.manage_users", service_id=service_one["id"]) not in page
assert url_for("main.manage_users", service_id=service_one["id"]) in page assert url_for("main.service_settings", service_id=service_one["id"]) in page
assert url_for("main.service_settings", service_id=service_one["id"]) not in page
# assert url_for('main.api_keys', service_id=service_one['id']) not in page
def test_menu_manage_service( def test_menu_manage_service(
@@ -1086,10 +1097,39 @@ def test_menu_manage_service(
) )
in page in page
) )
assert url_for("main.manage_users", service_id=service_one["id"]) in page assert url_for(".service_dashboard", service_id=service_one["id"]) in page
assert url_for("main.service_settings", service_id=service_one["id"]) in page assert url_for(".choose_template", service_id=service_one["id"]) in page
# assert url_for('main.api_keys', service_id=service_one['id']) not in page
def test_menu_main_settings(
client_request,
mocker,
api_user_active,
service_one,
mock_get_service_templates,
mock_has_no_jobs,
mock_get_template_statistics,
mock_get_service_statistics,
mock_get_annual_usage_for_service,
mock_get_inbound_sms_summary,
mock_get_free_sms_fragment_limit,
):
page = _test_settings_menu(
client_request,
mocker,
api_user_active,
service_one,
["view_activity", "user_profile", "manage_users", "manage_settings"],
)
page = str(page)
assert (
url_for(
"main.service_settings",
service_id=service_one["id"],
)
in page
)
assert url_for("main.service_settings", service_id=service_one["id"]) in page
def test_menu_manage_api_keys( def test_menu_manage_api_keys(
@@ -1122,8 +1162,8 @@ def test_menu_manage_api_keys(
) )
in page in page
) )
assert url_for("main.manage_users", service_id=service_one["id"]) in page # assert url_for("main.manage_users", service_id=service_one["id"]) not in page
assert url_for("main.service_settings", service_id=service_one["id"]) in page # assert url_for("main.service_settings", service_id=service_one["id"]) not in page
assert url_for("main.api_integration", service_id=service_one["id"]) in page assert url_for("main.api_integration", service_id=service_one["id"]) in page
@@ -1145,8 +1185,8 @@ def test_menu_all_services_for_platform_admin_user(
) )
page = str(page) page = str(page)
assert url_for("main.choose_template", service_id=service_one["id"]) in page assert url_for("main.choose_template", service_id=service_one["id"]) in page
assert url_for("main.manage_users", service_id=service_one["id"]) in page # assert url_for("main.manage_users", service_id=service_one["id"]) in page
assert url_for("main.service_settings", service_id=service_one["id"]) in page # assert url_for("main.service_settings", service_id=service_one["id"]) in page
# assert url_for('main.view_notifications', service_id=service_one['id'], message_type='email') in page # assert url_for('main.view_notifications', service_id=service_one['id'], message_type='email') in page
assert ( assert (
url_for( url_for(

View File

@@ -400,9 +400,9 @@ def test_navigation_urls(
assert [a["href"] for a in page.select(".nav a")] == [ assert [a["href"] for a in page.select(".nav a")] == [
"/services/{}/templates".format(SERVICE_ONE_ID), "/services/{}/templates".format(SERVICE_ONE_ID),
"/services/{}".format(SERVICE_ONE_ID), "/services/{}".format(SERVICE_ONE_ID),
"/services/{}/users".format(SERVICE_ONE_ID),
"/services/{}/usage".format(SERVICE_ONE_ID), "/services/{}/usage".format(SERVICE_ONE_ID),
"/services/{}/service-settings".format(SERVICE_ONE_ID), # "/services/{}/users".format(SERVICE_ONE_ID),
# "/services/{}/service-settings".format(SERVICE_ONE_ID),
# '/services/{}/api'.format(SERVICE_ONE_ID), # '/services/{}/api'.format(SERVICE_ONE_ID),
] ]
@@ -418,7 +418,7 @@ def test_caseworkers_get_caseworking_navigation(
client_request.login(active_caseworking_user) client_request.login(active_caseworking_user)
page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID) page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID)
assert normalize_spaces(page.select_one("header + .grid-container nav").text) == ( assert normalize_spaces(page.select_one("header + .grid-container nav").text) == (
"Send messages Sent messages Team members" "Send messages Sent messages"
) )
@@ -433,5 +433,5 @@ def test_caseworkers_see_jobs_nav_if_jobs_exist(
client_request.login(active_caseworking_user) client_request.login(active_caseworking_user)
page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID) page = client_request.get("main.choose_template", service_id=SERVICE_ONE_ID)
assert normalize_spaces(page.select_one("header + .grid-container nav").text) == ( assert normalize_spaces(page.select_one("header + .grid-container nav").text) == (
"Send messages Sent messages Team members" "Send messages Sent messages"
) )