Merge pull request #3527 from alphagov/broadcast-end-time

Let users choose when to end a broadcast
This commit is contained in:
Chris Hill-Scott
2020-07-17 10:43:10 +01:00
committed by GitHub
9 changed files with 241 additions and 74 deletions

View File

@@ -7,12 +7,14 @@
let states = {
'initial': Hogan.compile(`
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label class="block-label js-block-label" for="{{name}}-0">Now</label>
{{#showNowAsDefault}}
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label class="block-label js-block-label" for="{{name}}-0">Now</label>
</div>
</div>
</div>
{{/showNowAsDefault}}
<div class="radio-select__column">
{{#categories}}
<input type='button' class='govuk-button govuk-button--secondary radio-select__button--category' value='{{.}}' />
@@ -20,12 +22,14 @@
</div>
`),
'choose': Hogan.compile(`
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice js-initial-option">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
{{#showNowAsDefault}}
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice js-initial-option">
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
</div>
</div>
</div>
{{/showNowAsDefault}}
<div class="radio-select__column">
{{#choices}}
<div class="multiple-choice js-multiple-choice js-option">
@@ -37,12 +41,14 @@
</div>
`),
'chosen': Hogan.compile(`
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice js-initial-option">
<input id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
{{#showNowAsDefault}}
<div class="radio-select__column">
<div class="multiple-choice js-multiple-choice js-initial-option">
<input id="{{name}}-0" name="{{name}}" type="radio" value="">
<label for="{{name}}-0">Now</label>
</div>
</div>
</div>
{{/showNowAsDefault}}
<div class="radio-select__column">
{{#choices}}
<div class="multiple-choice js-multiple-choice">
@@ -80,10 +86,15 @@
let categories = $component.data('categories').split(',');
let name = $component.find('input').eq(0).attr('name');
let mousedownOption = null;
let showNowAsDefault = (
$component.data('show-now-as-default').toString() === 'true' ?
{'name': name} : false
);
const reset = () => {
render('initial', {
'categories': categories,
'name': name
'name': name,
'showNowAsDefault': showNowAsDefault
});
};
const selectOption = (value) => {
@@ -91,7 +102,8 @@
'choices': choices.filter(
element => element.value == value
),
'name': name
'name': name,
'showNowAsDefault': showNowAsDefault
});
focusSelected(component);
};
@@ -119,7 +131,8 @@
'choices': choices.filter(
element => element.label.toLowerCase().indexOf(day) > -1
),
'name': name
'name': name,
'showNowAsDefault': showNowAsDefault
});
focusSelected(component);
@@ -153,7 +166,8 @@
'choices': choices.filter(
element => element.value == $selection.eq(0).attr('value')
),
'name': name
'name': name,
'showNowAsDefault': showNowAsDefault
});
} else {
@@ -174,7 +188,8 @@
render('initial', {
'categories': categories,
'name': name
'name': name,
'showNowAsDefault': showNowAsDefault
});
$component.css({'height': 'auto'});

View File

@@ -100,7 +100,7 @@ def get_next_hours_until(until):
now = datetime.utcnow()
hours = int((until - now).total_seconds() / (60 * 60))
return [
(now + timedelta(hours=i)).replace(minute=0, second=0).replace(tzinfo=pytz.utc)
(now + timedelta(hours=i)).replace(minute=0, second=0, microsecond=0).replace(tzinfo=pytz.utc)
for i in range(1, hours + 1)
]
@@ -979,6 +979,24 @@ class ChooseTimeForm(StripWhitespaceForm):
)
class ChooseBroadcastDurationForm(StripWhitespaceForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.finishes_at.choices = [
get_time_value_and_label(hour) for hour in get_next_hours_until(
get_furthest_possible_scheduled_time()
)
]
self.finishes_at.categories = get_next_days_until(
get_furthest_possible_scheduled_time()
)
finishes_at = RadioField(
'When should this broadcast end?',
)
class CreateKeyForm(StripWhitespaceForm):
def __init__(self, existing_keys, *args, **kwargs):
self.existing_key_names = [

View File

@@ -1,8 +1,12 @@
from flask import abort, jsonify, redirect, render_template, request, url_for
from flask import abort, jsonify, redirect, render_template, url_for
from app import current_service
from app.main import main
from app.main.forms import BroadcastAreaForm, SearchByNameForm
from app.main.forms import (
BroadcastAreaForm,
ChooseBroadcastDurationForm,
SearchByNameForm,
)
from app.models.broadcast_message import BroadcastMessage, BroadcastMessages
from app.utils import service_has_permission, user_has_permissions
@@ -141,15 +145,19 @@ def preview_broadcast_message(service_id, broadcast_message_id):
broadcast_message_id,
service_id=current_service.id,
)
if request.method == 'POST':
broadcast_message.request_approval()
form = ChooseBroadcastDurationForm()
if form.validate_on_submit():
broadcast_message.request_approval(until=form.finishes_at.data)
return redirect(url_for(
'.broadcast_dashboard',
service_id=current_service.id,
))
return render_template(
'views/broadcast/preview-message.html',
broadcast_message=broadcast_message,
form=form,
)

View File

@@ -1,4 +1,4 @@
from datetime import datetime, timedelta
from datetime import datetime
from notifications_utils.broadcast_areas import broadcast_area_libraries
from notifications_utils.template import BroadcastPreviewTemplate
@@ -33,7 +33,6 @@ class BroadcastMessage(JSONModel):
'approved_by_id',
'cancelled_by_id',
}
DEFAULT_TTL = timedelta(hours=72)
libraries = broadcast_area_libraries
@@ -132,9 +131,9 @@ class BroadcastMessage(JSONModel):
data=kwargs,
)
def request_approval(self):
def request_approval(self, until):
self._update(
finishes_at=(datetime.utcnow() + self.DEFAULT_TTL).isoformat(),
finishes_at=until,
)
self._set_status_to('pending-approval')

View File

@@ -23,7 +23,8 @@
{% macro radio_select(
field,
hint=None,
wrapping_class='form-group'
wrapping_class='form-group',
show_now_as_default=True
) %}
<div class="{{ wrapping_class }} {% if field.errors %} form-group-error{% endif %}">
<fieldset>
@@ -35,7 +36,7 @@
</span>
{% endif %}
</legend>
<div class="radio-select" data-module="radio-select" data-categories="{{ field.categories|join(',') }}">
<div class="radio-select" data-module="radio-select" data-categories="{{ field.categories|join(',') }}" data-show-now-as-default="{{ show_now_as_default|string|lower }}">
<div class="radio-select-column">
{% for option in field %}
<div class="multiple-choice">

View File

@@ -1,7 +1,8 @@
{% from "components/button/macro.njk" import govukButton %}
{% from "components/form.html" import form_wrapper %}
{% from "components/page-header.html" import page_header %}
{% from "components/page-footer.html" import sticky_page_footer %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/radios.html" import radio_select %}
{% extends "withnav_template.html" %}
@@ -28,7 +29,11 @@
{{ broadcast_message.template|string }}
{% call form_wrapper() %}
{{ sticky_page_footer('Submit for approval') }}
{{ radio_select(
form.finishes_at,
show_now_as_default=False
) }}
{{ page_footer('Submit for approval') }}
{% endcall %}
{% endblock %}