mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-12 01:14:11 -04:00
Merge pull request #3547 from alphagov/broadcast-tour
Add a tour for users new to broadcast services
This commit is contained in:
BIN
app/assets/images/broadcast-tour/1.png
Normal file
BIN
app/assets/images/broadcast-tour/1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
app/assets/images/broadcast-tour/2.png
Normal file
BIN
app/assets/images/broadcast-tour/2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
BIN
app/assets/images/broadcast-tour/3.png
Normal file
BIN
app/assets/images/broadcast-tour/3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
3214
app/assets/images/broadcast-tour/artwork.ai
Normal file
3214
app/assets/images/broadcast-tour/artwork.ai
Normal file
File diff suppressed because one or more lines are too long
@@ -78,6 +78,11 @@
|
||||
box-shadow: inset 0 -1em 1.6em 0 rgba(0, 0, 0, 0.05);
|
||||
border: 0;
|
||||
|
||||
&-no-fixed-height {
|
||||
height: auto;
|
||||
min-height: 425px;
|
||||
}
|
||||
|
||||
.heading-medium {
|
||||
@include core-24;
|
||||
}
|
||||
@@ -98,6 +103,18 @@
|
||||
|
||||
}
|
||||
|
||||
ul {
|
||||
@include core-24;
|
||||
color: $white;
|
||||
margin-bottom: govuk-spacing(5);
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: govuk-spacing(3);
|
||||
list-style-type: disc;
|
||||
margin-left: govuk-spacing(6);
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
font-weight: bold;
|
||||
@@ -123,6 +140,10 @@
|
||||
}
|
||||
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.greyed-out-step {
|
||||
opacity: 0.6;
|
||||
|
||||
@@ -19,6 +19,17 @@ from app.models.broadcast_message import BroadcastMessage, BroadcastMessages
|
||||
from app.utils import service_has_permission, user_has_permissions
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast-tour/<int:step_index>')
|
||||
@user_has_permissions()
|
||||
@service_has_permission('broadcast')
|
||||
def broadcast_tour(service_id, step_index):
|
||||
if step_index not in (1, 2, 3):
|
||||
abort(404)
|
||||
return render_template(
|
||||
f'views/broadcast/tour/{step_index}.html'
|
||||
)
|
||||
|
||||
|
||||
@main.route('/services/<uuid:service_id>/broadcast-dashboard')
|
||||
@user_has_permissions()
|
||||
@service_has_permission('broadcast')
|
||||
|
||||
@@ -40,6 +40,9 @@ def accept_invite(token):
|
||||
|
||||
if invited_user.status == 'accepted':
|
||||
session.pop('invited_user', None)
|
||||
service = Service.from_id(invited_user.service)
|
||||
if service.has_permission('broadcast'):
|
||||
return redirect(url_for('main.broadcast_tour', service_id=service.id, step_index=1))
|
||||
return redirect(url_for('main.service_dashboard', service_id=invited_user.service))
|
||||
|
||||
session['invited_user'] = invited_user.serialize()
|
||||
@@ -66,6 +69,8 @@ def accept_invite(token):
|
||||
permissions=invited_user.permissions,
|
||||
folder_permissions=invited_user.folder_permissions,
|
||||
)
|
||||
if service.has_permission('broadcast'):
|
||||
return redirect(url_for('main.broadcast_tour', service_id=service.id, step_index=1))
|
||||
return redirect(url_for('main.service_dashboard', service_id=service.id))
|
||||
else:
|
||||
return redirect(url_for('main.register_from_invite'))
|
||||
|
||||
@@ -15,6 +15,7 @@ from notifications_utils.url_safe_token import check_token
|
||||
from app import user_api_client
|
||||
from app.main import main
|
||||
from app.main.forms import TwoFactorForm
|
||||
from app.models.service import Service
|
||||
from app.models.user import InvitedUser, User
|
||||
from app.utils import redirect_to_sign_in
|
||||
|
||||
@@ -77,6 +78,9 @@ def activate_user(user_id):
|
||||
invited_user = session.get('invited_user')
|
||||
if invited_user:
|
||||
service_id = _add_invited_user_to_service(invited_user)
|
||||
service = Service.from_id(service_id)
|
||||
if service.has_permission('broadcast'):
|
||||
return redirect(url_for('main.broadcast_tour', service_id=service.id, step_index=1))
|
||||
return redirect(url_for('main.service_dashboard', service_id=service_id))
|
||||
|
||||
invited_org_user = session.get('invited_org_user')
|
||||
|
||||
@@ -352,6 +352,7 @@ class HeaderNavigation(Navigation):
|
||||
'old_guest_list',
|
||||
'who_can_use_notify',
|
||||
'who_its_for',
|
||||
'broadcast_tour',
|
||||
'broadcast_dashboard',
|
||||
'broadcast_dashboard_updates',
|
||||
'broadcast',
|
||||
@@ -375,6 +376,7 @@ class MainNavigation(Navigation):
|
||||
|
||||
mapping = {
|
||||
'dashboard': {
|
||||
'broadcast_tour',
|
||||
'broadcast_dashboard',
|
||||
'broadcast_dashboard_updates',
|
||||
'conversation',
|
||||
@@ -702,6 +704,7 @@ class CaseworkNavigation(Navigation):
|
||||
|
||||
mapping = {
|
||||
'dashboard': {
|
||||
'broadcast_tour',
|
||||
'broadcast_dashboard',
|
||||
'broadcast_dashboard_updates',
|
||||
},
|
||||
@@ -1330,6 +1333,7 @@ class OrgNavigation(Navigation):
|
||||
'old_guest_list',
|
||||
'who_can_use_notify',
|
||||
'who_its_for',
|
||||
'broadcast_tour',
|
||||
'broadcast_dashboard',
|
||||
'broadcast_dashboard_updates',
|
||||
'broadcast',
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
|
||||
<h1 class="govuk-visually-hidden">Dashboard</h1>
|
||||
|
||||
{% if current_user.has_permissions('manage_templates') and not current_service.all_templates %}
|
||||
<nav class="govuk-!-margin-top-2 govuk-!-margin-bottom-6">
|
||||
<a class="govuk-link govuk-link--no-visited-state pill-separate-item govuk-!-padding-top-4 govuk-!-padding-bottom-4 govuk-!-font-weight-bold" href="{{ url_for('.choose_template', service_id=current_service.id) }}">
|
||||
Start by creating a template
|
||||
</a>
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<h2 class="heading-medium govuk-!-margin-bottom-2">Live broadcasts</h2>
|
||||
|
||||
{{ ajax_block(
|
||||
|
||||
41
app/templates/views/broadcast/tour/1.html
Normal file
41
app/templates/views/broadcast/tour/1.html
Normal file
@@ -0,0 +1,41 @@
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
|
||||
{% extends "admin_template.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Step 1
|
||||
{% endblock %}
|
||||
|
||||
{% set mainClasses = "govuk-!-padding-top-0 govuk-!-padding-bottom-0" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="banner-tour banner-tour-no-fixed-height govuk-!-margin-top-0">
|
||||
<div class="govuk-grid-row">
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<h1 class="heading-medium">
|
||||
You’ve been invited to use GOV.UK Notify to broadcast alerts
|
||||
</h1>
|
||||
<ul>
|
||||
<li>
|
||||
Broadcasting is a new technology for alerting members of the
|
||||
public
|
||||
</li>
|
||||
<li>
|
||||
It should be used when there’s an imminent risk to life
|
||||
</li>
|
||||
</ul>
|
||||
<p class="govuk-body heading-medium">
|
||||
<a class="govuk-link govuk-link--no-visited-state" href='{{ url_for(".broadcast_tour", service_id=current_service.id, step_index=2) }}'>
|
||||
Find out how it works
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<img src="{{ asset_url('images/broadcast-tour/1.png') }}" alt="">
|
||||
<link rel="preload" href="{{ asset_url('images/broadcast-tour/2.png') }}" as="image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
44
app/templates/views/broadcast/tour/2.html
Normal file
44
app/templates/views/broadcast/tour/2.html
Normal file
@@ -0,0 +1,44 @@
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
|
||||
{% extends "admin_template.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Step 2
|
||||
{% endblock %}
|
||||
|
||||
{% set mainClasses = "govuk-!-padding-top-0 govuk-!-padding-bottom-0" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="banner-tour banner-tour-no-fixed-height govuk-!-margin-top-0">
|
||||
<div class="govuk-grid-row">
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<h1 class="heading-medium">
|
||||
A broadcast will alert every phone in an area
|
||||
</h1>
|
||||
<ul>
|
||||
<li>
|
||||
The alert will appear even if the phone’s screen is locked
|
||||
</li>
|
||||
<li>
|
||||
The phone will play an alarm sound even if it’s set to silent
|
||||
</li>
|
||||
<li>
|
||||
Any phone that enters the area while the broadcast is live will
|
||||
get the alert
|
||||
</li>
|
||||
</ul>
|
||||
<p class="govuk-body heading-medium govuk-!-margin-bottom-6">
|
||||
<a class="govuk-link govuk-link--no-visited-state" href='{{ url_for(".broadcast_tour", service_id=current_service.id, step_index=3) }}'>
|
||||
How to try it out
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<img src="{{ asset_url('images/broadcast-tour/2.png') }}" alt="">
|
||||
<link rel="preload" href="{{ asset_url('images/broadcast-tour/3.png') }}" as="image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
43
app/templates/views/broadcast/tour/3.html
Normal file
43
app/templates/views/broadcast/tour/3.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{% from "components/banner.html" import banner_wrapper %}
|
||||
|
||||
{% extends "admin_template.html" %}
|
||||
|
||||
{% block per_page_title %}
|
||||
Step 3
|
||||
{% endblock %}
|
||||
|
||||
{% set mainClasses = "govuk-!-padding-top-0 govuk-!-padding-bottom-0" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="banner-tour banner-tour-no-fixed-height govuk-!-margin-top-0">
|
||||
<div class="govuk-grid-row">
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<h1 class="heading-medium">
|
||||
You have a trial account
|
||||
</h1>
|
||||
<ul>
|
||||
<li>
|
||||
There’s no risk of triggering a real, live broadcast
|
||||
</li>
|
||||
<li>
|
||||
Get familiar with the system now, so you’re ready to use it if
|
||||
there’s an emergency
|
||||
</li>
|
||||
<li>
|
||||
When you’re ready, apply for a live account
|
||||
</li>
|
||||
</ul>
|
||||
<p class="govuk-body heading-medium">
|
||||
<a class="govuk-link govuk-link--no-visited-state" href='{{ url_for(".service_dashboard", service_id=current_service.id) }}'>
|
||||
Continue to dashboard
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="govuk-grid-column-one-half">
|
||||
<img src="{{ asset_url('images/broadcast-tour/3.png') }}" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -94,6 +94,7 @@ def test_empty_broadcast_dashboard(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_get_no_broadcast_messages,
|
||||
mock_get_service_templates_when_no_templates_exist,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
page = client_request.get(
|
||||
@@ -114,6 +115,7 @@ def test_broadcast_dashboard(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_get_broadcast_messages,
|
||||
mock_get_service_templates,
|
||||
):
|
||||
service_one['permissions'] += ['broadcast']
|
||||
page = client_request.get(
|
||||
|
||||
@@ -319,6 +319,7 @@ def test_register_from_email_auth_invite(
|
||||
mock_accept_invite,
|
||||
mock_create_event,
|
||||
mock_add_user_to_service,
|
||||
mock_get_service,
|
||||
invite_email_address,
|
||||
):
|
||||
sample_invite['auth_type'] = 'email_auth'
|
||||
@@ -372,6 +373,7 @@ def test_can_register_email_auth_without_phone_number(
|
||||
mock_accept_invite,
|
||||
mock_create_event,
|
||||
mock_add_user_to_service,
|
||||
mock_get_service,
|
||||
):
|
||||
sample_invite['auth_type'] = 'email_auth'
|
||||
with client.session_transaction() as session:
|
||||
|
||||
@@ -178,6 +178,7 @@ def test_activate_user_redirects_to_service_dashboard_if_user_already_belongs_to
|
||||
sample_invite,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_service,
|
||||
):
|
||||
mocker.patch('app.user_api_client.add_user_to_service', side_effect=HTTPError(
|
||||
response=Mock(
|
||||
|
||||
Reference in New Issue
Block a user