Merge branch 'main' into 2410-bug-radio-buttons-cannot-be-selected

This commit is contained in:
Beverly Nguyen
2025-03-19 14:04:56 -07:00
14 changed files with 400 additions and 413 deletions

View File

@@ -682,4 +682,4 @@ def slugify(text):
"""
Converts text to lowercase, replaces spaces with hyphens, and removes invalid characters.
"""
return re.sub(r'[^a-z0-9-]', '', re.sub(r'\s+', '-', text.lower()))
return re.sub(r"[^a-z0-9-]", "", re.sub(r"\s+", "-", text.lower()))

View File

@@ -220,7 +220,7 @@
var url = type === 'service'
? `/services/${currentServiceId}/daily-stats.json?timezone=${encodeURIComponent(userTimezone)}`
: `/services/${currentServiceId}/daily-stats-by-user.json`;
: `/services/${currentServiceId}/daily-stats-by-user.json?timezone=${encodeURIComponent(userTimezone)}`;
return fetch(url)

View File

@@ -108,33 +108,17 @@ class OnlySMSCharacters:
)
if non_sms_characters:
raise ValidationError(
"You cannot use {} in {}. {} will not show up properly on everyones phones.".format(
"Please remove the unaccepted character {} in your message, then save again".format(
formatted_list(
non_sms_characters,
conjunction="or",
conjunction="and",
before_each="",
after_each="",
),
{
"sms": "text messages",
}.get(self._template_type),
("It" if len(non_sms_characters) == 1 else "They"),
)
)
# class NoPlaceholders:
# def __init__(self, message=None):
# self.message = message or (
# 'You cant use ((double brackets)) to personalize this message'
# )
# def __call__(self, form, field):
# if Field(field.data).placeholders:
# raise ValidationError(self.message)
class LettersNumbersSingleQuotesFullStopsAndUnderscoresOnly:
regex = re.compile(r"^[a-zA-Z0-9\s\._']+$")

View File

@@ -132,13 +132,18 @@ def get_local_daily_stats_for_last_x_days(stats_utc, user_timezone, days):
@user_has_permissions()
def get_daily_stats_by_user(service_id):
date_range = get_stats_date_range()
stats = service_api_client.get_user_service_notification_statistics_by_day(
days = date_range["days"]
user_timezone = request.args.get("timezone", "UTC")
stats_utc = service_api_client.get_user_service_notification_statistics_by_day(
service_id,
user_id=current_user.id,
start_date=date_range["start_date"],
days=date_range["days"],
days=days,
)
return jsonify(stats)
local_stats = get_local_daily_stats_for_last_x_days(stats_utc, user_timezone, days)
return jsonify(local_stats)
@main.route("/services/<uuid:service_id>/template-usage")

View File

@@ -680,41 +680,43 @@ def count_content_length(service_id, template_type):
)
def _is_latin1(s):
return bool(s.encode(encoding="latin-1", errors="strict"))
def _get_content_count_error_and_message_for_template(template):
url = "https://en.wikipedia.org/wiki/ISO/IEC_8859-1"
if template.template_type == "sms":
s1 = f"<html><body>Use of characters outside the <a href='{url}'>IEC_8859-1</a> character set may increase "
s2 = "the message fragment count, resulting in additional charges, and these IEC_8859-1 "
s3 = "characters may not display properly on some older mobile devices.</body></html>"
s1 = (
"<html><body>Looks like your template may have one of these characters "
"• ™ ∞ ≤ or ≥ or emoji, which won't save."
)
s2 = "<br>Please remove any unaccepted characters or emojis and try again.</body></html>"
warning = ""
try:
_is_latin1(template.content)
except UnicodeEncodeError:
warning = f"{s1}{s2}{s3}"
# Define characters that should be blocked
BLOCKED_CHARACTERS = {"", "", "", "", ""}
def contains_blocked_characters(content):
"""Check if the content contains explicitly blocked characters."""
return any(c in BLOCKED_CHARACTERS for c in content)
# Check for blocked characters
if contains_blocked_characters(template.content):
warning = f"{s1}{s2}"
return False, Markup(warning) # 🚨 ONLY show the warning, hiding "Will be charged..."
# If message is too long, return the length error
if template.is_message_too_long():
return True, (
f"You have "
f"{character_count(template.content_count_without_prefix - SMS_CHAR_COUNT_LIMIT)} "
f"too many"
)
# Show charge message as usual if no warning
if template.placeholders:
return False, (
Markup(
f"Will be charged as {message_count(template.fragment_count, template.template_type)} "
f"(not including personalization). {warning}"
)
)
return False, (
# Markup marks html contents safe so that they render properly. Don't use it if there is user input.
Markup(
f"Will be charged as {message_count(template.fragment_count, template.template_type)}. {warning} "
return False, Markup(
f"Will be charged as {message_count(template.fragment_count, template.template_type)} "
f"(not including personalization)."
)
return False, Markup(
f"Will be charged as {message_count(template.fragment_count, template.template_type)}."
)

View File

@@ -28,7 +28,7 @@
{% endif %}
{% call form_wrapper() %}
<div class="grid-row">
<div class="grid-container padding-0">
<div class="tablet:grid-col-9 mobile-lg:grid-col-12">
{{ form.name(param_extensions={
"extra_form_group_classes": "margin-bottom-2",
@@ -61,12 +61,12 @@
</div>
</div>
</div>
<div class="grid-row width-full">
<div class="grid-row width-mobile-lg">
<div class="tablet:grid-col-2 mobile-lg:grid-col-12">
{{ page_footer('Save') }}
</div>
<div class="tablet:grid-col-10 mobile-lg:grid-col-12">
<p class="usa-hint margin-top-5 tablet:margin-left-neg-2">
<p class="usa-hint margin-top-5 tablet:margin-left-2">
After saving, you'll have the option to send.
</p>
</div>