Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add daily usage widget #1658

Merged
merged 23 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ff5fb92
chore: add missing tailwind colors
andrewleith Sep 7, 2023
3e3a32e
style(daily limits widget): add new css rules for component
andrewleith Sep 7, 2023
3c66b85
feat(daily limits widget): add new component
andrewleith Sep 7, 2023
796a3d4
feat(daily limits widget): add new components to dashboard
andrewleith Sep 7, 2023
a4e2c7e
chore: formatting
andrewleith Sep 7, 2023
8ed11f0
tests(daily limits widget): add tests for under 80%, at 80% and at 10…
andrewleith Sep 7, 2023
b64e9b5
chore(tests): fix a test whose purpose is unclear
andrewleith Sep 7, 2023
fb85240
fix(daily limits widget): re-work a11y message a bit to make it read …
andrewleith Sep 11, 2023
8844802
fix(daily limits widget): remove testing content; update translations
andrewleith Sep 11, 2023
fb13cb7
test(daily limits widget): fix up a11y part of the test due to re-factor
andrewleith Sep 11, 2023
266a757
Merge branch 'main' into feat/add-daily-usage-widget
andrewleith Sep 11, 2023
ca61e92
fix(daily limits widget): update heading content
andrewleith Sep 12, 2023
7f58628
fix: comment out widget for now
andrewleith Sep 12, 2023
c378ba4
feat(daily limits): add french translations
andrewleith Sep 13, 2023
576f1e8
feat(daily limits/sms): update SMS over character limit error
andrewleith Sep 13, 2023
96e1cc9
fat(daily limit/sms): update sms template content textarea hint
andrewleith Sep 13, 2023
145f0c6
Merge branch 'main' into feat/add-daily-usage-widget
andrewleith Sep 13, 2023
ea0cb7d
feat(daily limits): unhide new widgets
andrewleith Sep 13, 2023
51003d5
test(daily limits): fix tests since FF was removed in main
andrewleith Sep 13, 2023
018ab39
chore: formatting / refactor
andrewleith Sep 14, 2023
a4fe676
test(sms error message): update test with new message
andrewleith Sep 14, 2023
9ba8c98
fix(a11y): fix unrelated html validation issue where uuids are used a…
andrewleith Sep 14, 2023
cb24831
a11y(templates): span cannot contain a div
andrewleith Sep 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/assets/stylesheets/index.css

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions app/assets/stylesheets/tailwind/components/remaining-messages.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@layer components {
/*! purgecss start ignore */

.remaining-messages {
@apply bg-blue text-white p-gutterHalf;
}

.rm-header {
@apply text-smaller inline-block;
}

.rm-used {
@apply .text-titlelarge pb-4 font-bold leading-none;
}

.rm-total {
float: right;
}

.rm-bar {
box-shadow: inset 0 -10px #cfd5dd;
display: flex;
align-items: flex-end;
}

.rm-bar-usage {
width: max(var(--usage), 4px);
height: 30px;
background: currentColor;
}

/*! purgecss end ignore */
}
1 change: 1 addition & 0 deletions app/assets/stylesheets/tailwind/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
@import "./components/task-list.css";
@import "./components/back-link.css";
@import "./components/preview-fullpage-border.css";
@import "./components/remaining-messages.css";

/* views */
@import "./views/dashboard.css";
Expand Down
18 changes: 18 additions & 0 deletions app/templates/components/remaining-messages.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% macro remaining_messages(header, total, used) %}
{% set near_limit = ((used/total) >= 0.8) %}
<div class="remaining-messages">
<div class="rm-header mb-2">{{ header }}</div>
andrewleith marked this conversation as resolved.
Show resolved Hide resolved
<div class="mb-2">
<span class="rm-used">{{ "{:,}".format(used) if session['userlang'] == 'en' else "{:,}".format(used).replace(',', ' ') }}</span>
<span class="rm-total">{{ _('of') }} {{ "{:,}".format(total) if session['userlang'] == 'en' else "{:,}".format(total).replace(',', ' ') }}</span>
</div>

<div class="rm-bar">
<div class="rm-bar-usage {{ 'text-red-300' if near_limit else 'text-green-300' }}" style="--usage: {{ (used/total)*100 }}%;">
{% if near_limit %}
<span class="visually-hidden">{{ _('Near daily limit') }}</span>
{% endif %}
</div>
</div>
</div>
{% endmacro %}
40 changes: 16 additions & 24 deletions app/templates/views/dashboard/_totals_daily.html
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
{% from "components/big-number.html" import big_number %}
{% from "components/message-count-label.html" import message_count_label %}

{% set suffix = _("left today") %}
{% if current_lang == "fr" %}
{% set suffix_plural = _("many left today") %}
{% else %}
{% set suffix_plural = _("left today") %}
{% endif %}
{% set email_remaining = current_service.message_limit - statistics['email']['requested'] %}
{% set sms_parts_remaining = current_service.sms_daily_limit - statistics['sms']['requested'] %}
{% from 'components/remaining-messages.html' import remaining_messages %}

<div class="ajax-block-container">
<div class="grid-row contain-floats">
<div id="total-email" class="{{column_width}}">
{{ big_number(
email_remaining,
message_count_label(email_remaining, 'email', suffix=suffix, suffix_plural=suffix_plural),
status=True,
) }}
</div>
<div id="total-sms" class="{{column_width}}">
{{ big_number(
sms_parts_remaining,
message_count_label(sms_parts_remaining, 'sms', suffix=suffix, suffix_plural=suffix_plural),
status=True,
) }}
<h2 class="heading-medium mt-8">
<!-- {{ _('Daily usage') }}
<br />
<small class="text-gray-600 text-small font-normal" style="color: #5E6975">
{{ _('<b>Note:</b> Message limits reset each night at 7pm EST') }}
</small> -->
{{ _('Sent since 7 pm Eastern Time') }}
</h2>
<div class="grid-row contain-floats">
<div class="{{column_width}}">
{{ remaining_messages(header=_('emails'), total=current_service.message_limit, used= statistics['email']['requested']) }}
</div>
<div class="{{column_width}}">
{{ remaining_messages(header=_('text messages'), total=current_service.sms_daily_limit, used=statistics['sms']['requested']) }}
</div>
</div>
</div>
</div>
3 changes: 3 additions & 0 deletions app/templates/views/dashboard/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ <h2 class="heading-medium mt-8">{{ _("Scheduled sends") }}</h2>
{% endif %}

{{ ajax_block(partials, updates_url, 'weekly_totals', interval=5) }}
{{ ajax_block(partials, updates_url, 'daily_totals', interval=5) }}
andrewleith marked this conversation as resolved.
Show resolved Hide resolved

<hr />

{% if not config["FF_BOUNCE_RATE_V15"] %}
{{ show_more(
Expand Down
2 changes: 2 additions & 0 deletions app/translations/csv/fr.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1753,3 +1753,5 @@
"You cannot send this text message today","Vous ne pouvez pas envoyer ce message texte aujourd’hui."
"You cannot send all these email messages today","Vous ne pouvez pas envoyer tous ces courriels aujourd’hui."
"You cannot send all these text messages today","Vous ne pouvez pas envoyer tous ces messages texte aujourd’hui."
"of","de"
"Sent since 7 pm Eastern Time","Envoyé depuis 19 h, heure de l'Est"
2 changes: 2 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ module.exports = {
hover: "#990c1a",
border: "#6a0812",
mellow: "#df3034",
300: "#D74D42",
},
white: {
default: "#FFF",
Expand Down Expand Up @@ -100,6 +101,7 @@ module.exports = {
hover: "#00692f",
border: "#003618",
green: "#006435",
300: "#29A35A",
},
black: {
default: "#000",
Expand Down
128 changes: 124 additions & 4 deletions tests/app/main/views/test_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,8 @@ def test_should_show_upcoming_jobs_on_dashboard(
@pytest.mark.parametrize(
"permissions, column_name, expected_column_count",
[
(["email", "sms"], ".w-1\\/2", 4),
(["email", "sms"], ".w-1\\/2", 4),
(["email", "sms"], ".w-1\\/2", 6),
(["email", "sms"], ".w-1\\/2", 6),
],
)
def test_correct_columns_display_on_dashboard_v15(
Expand All @@ -434,8 +434,8 @@ def test_correct_columns_display_on_dashboard_v15(
@pytest.mark.parametrize(
"permissions, column_name, expected_column_count",
[
(["email", "sms"], ".w-1\\/2", 2),
(["email", "sms"], ".w-1\\/2", 2),
(["email", "sms"], ".w-1\\/2", 4),
(["email", "sms"], ".w-1\\/2", 4),
],
)
def test_correct_columns_display_on_dashboard(
Expand Down Expand Up @@ -1426,3 +1426,123 @@ def test_a11y_template_usage_should_not_contain_duplicate_ids(
list.append(element["id"])

assert len(list) == len(set(list)) # check for duplicates


@pytest.mark.parametrize(
"totals, notification_type, expected_color, expected_sent, expected_limit, expect_accessible_message",
[
# With a service email limit of 1000, and 100 emails sent in the past 24 hours
(
{
"email": {"requested": 100, "delivered": 0, "failed": 0},
"sms": {"requested": 0, "delivered": 0, "failed": 0},
},
"email",
"text-green-300",
"100",
"1,000",
False,
),
# With a service SMS limit of 1000, and 10 sms sent in the past 24 hours
(
{
"email": {"requested": 0, "delivered": 0, "failed": 0},
"sms": {"requested": 10, "delivered": 0, "failed": 0},
},
"sms",
"text-green-300",
"10",
"1,000",
False,
),
# With a service email limit of 1000, and 800 emails sent in the past 24 hours
(
{
"email": {"requested": 800, "delivered": 0, "failed": 0},
"sms": {"requested": 0, "delivered": 0, "failed": 0},
},
"email",
"text-red-300",
"800",
"1,000",
True,
),
# With a service SMS limit of 1000, and 900 sms sent in the past 24 hours
(
{
"email": {"requested": 0, "delivered": 0, "failed": 0},
"sms": {"requested": 900, "delivered": 0, "failed": 0},
},
"sms",
"text-red-300",
"900",
"1,000",
True,
),
# With a service email limit of 1000, and 1000 emails sent in the past 24 hours
(
{
"email": {"requested": 1000, "delivered": 0, "failed": 0},
"sms": {"requested": 0, "delivered": 0, "failed": 0},
},
"email",
"text-red-300",
"1,000",
"1,000",
True,
),
# With a service SMS limit of 1000, and 1000 sms sent in the past 24 hours
(
{
"email": {"requested": 0, "delivered": 0, "failed": 0},
"sms": {"requested": 1000, "delivered": 0, "failed": 0},
},
"sms",
"text-red-300",
"1,000",
"1,000",
True,
),
],
)
def test_dashboard_daily_limits(
client_request,
mocker,
mock_get_service_templates,
mock_get_template_statistics,
mock_get_service_statistics,
mock_get_jobs,
service_one,
totals,
notification_type,
expected_color,
expected_sent,
expected_limit,
expect_accessible_message,
app_,
):
with set_config(app_, "FF_BOUNCE_RATE_V15", True):
service_one["permissions"] = (["email", "sms"],)

mocker.patch("app.main.views.dashboard.get_dashboard_totals", return_value=totals)

page = client_request.get("main.service_dashboard", service_id=service_one["id"])

component_index = 0 if notification_type == "email" else 1

assert page.find_all(class_="remaining-messages")[component_index].find(class_="rm-used").text == expected_sent
assert page.find_all(class_="remaining-messages")[component_index].find(class_="rm-total").text[3:] == expected_limit
assert (
expected_color
in page.find_all(class_="remaining-messages")[component_index].find(class_="rm-bar-usage").attrs["class"]
)

if expect_accessible_message:
assert (
len(
page.find_all(class_="remaining-messages")[component_index]
.find(class_="rm-bar-usage")
.find(class_="visually-hidden")
)
== 1
)