mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-23 15:57:23 -04:00
Merge branch 'main' of https://github.com/GSA/notifications-admin into notify-871
This commit is contained in:
@@ -1279,6 +1279,23 @@ class ChangeNameForm(StripWhitespaceForm):
|
||||
new_name = GovukTextInputField("Your name")
|
||||
|
||||
|
||||
class ChangePreferredTimezoneForm(StripWhitespaceForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ChangePreferredTimezoneForm, self).__init__(*args, **kwargs)
|
||||
self.new_preferred_timezone.choices = [
|
||||
("US/Eastern", "US/Eastern"),
|
||||
("US/Central", "US/Central"),
|
||||
("US/Mountain", "US/Mountain"),
|
||||
("US/Pacific", "US/Pacific"),
|
||||
("US/Hawaii", "US/Hawaii"),
|
||||
]
|
||||
|
||||
new_preferred_timezone = GovukRadiosField(
|
||||
"What timezone would you like to use?",
|
||||
default="US/Eastern",
|
||||
)
|
||||
|
||||
|
||||
class ChangeEmailForm(StripWhitespaceForm):
|
||||
def __init__(self, validate_email_func, *args, **kwargs):
|
||||
self.validate_email_func = validate_email_func
|
||||
|
||||
@@ -2,6 +2,7 @@ from functools import partial
|
||||
|
||||
from flask import abort, flash, jsonify, redirect, render_template, request, url_for
|
||||
from flask_login import current_user
|
||||
from markupsafe import Markup
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from notifications_utils import SMS_CHAR_COUNT_LIMIT
|
||||
|
||||
@@ -679,8 +680,23 @@ 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>"
|
||||
|
||||
warning = ""
|
||||
try:
|
||||
_is_latin1(template.content)
|
||||
except UnicodeEncodeError:
|
||||
warning = f"{s1}{s2}{s3}"
|
||||
|
||||
if template.is_message_too_long():
|
||||
return True, (
|
||||
f"You have "
|
||||
@@ -689,11 +705,16 @@ def _get_content_count_error_and_message_for_template(template):
|
||||
)
|
||||
if template.placeholders:
|
||||
return False, (
|
||||
f"Will be charged as {message_count(template.fragment_count, template.template_type)} "
|
||||
f"(not including personalization)"
|
||||
Markup(
|
||||
f"Will be charged as {message_count(template.fragment_count, template.template_type)} "
|
||||
f"(not including personalization). {warning}"
|
||||
)
|
||||
)
|
||||
return False, (
|
||||
f"Will be charged as {message_count(template.fragment_count, template.template_type)} "
|
||||
# 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} "
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from app.main.forms import (
|
||||
ChangeMobileNumberForm,
|
||||
ChangeNameForm,
|
||||
ChangePasswordForm,
|
||||
ChangePreferredTimezoneForm,
|
||||
ConfirmPasswordForm,
|
||||
ServiceOnOffSettingForm,
|
||||
TwoFactorForm,
|
||||
@@ -61,6 +62,22 @@ def user_profile_name():
|
||||
)
|
||||
|
||||
|
||||
@main.route("/user-profile/preferred_timezone", methods=["GET", "POST"])
|
||||
@user_is_logged_in
|
||||
def user_profile_preferred_timezone():
|
||||
form = ChangePreferredTimezoneForm(new_name=current_user.preferred_timezone)
|
||||
|
||||
if form.validate_on_submit():
|
||||
current_user.update(preferred_timezone=form.new_preferred_timezone.data)
|
||||
current_user.preferred_timezone = form.new_preferred_timezone.data
|
||||
return redirect(url_for(".user_profile"))
|
||||
return render_template(
|
||||
"views/user-profile/change.html",
|
||||
thing="preferred timezone",
|
||||
form_field=form.new_preferred_timezone,
|
||||
)
|
||||
|
||||
|
||||
@main.route("/user-profile/email", methods=["GET", "POST"])
|
||||
@user_is_logged_in
|
||||
@user_is_gov_user
|
||||
|
||||
@@ -54,7 +54,6 @@ class User(JSONModel, UserMixin):
|
||||
super().__init__(_dict)
|
||||
self.permissions = _dict.get("permissions", {})
|
||||
self._platform_admin = _dict["platform_admin"]
|
||||
self.preferred_timezone = "US/Eastern"
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, user_id):
|
||||
@@ -366,6 +365,7 @@ class User(JSONModel, UserMixin):
|
||||
"permissions": [x for x in self._permissions],
|
||||
"organizations": self.organization_ids,
|
||||
"current_session_id": self.current_session_id,
|
||||
"preferred_timezone": self.preferred_timezone,
|
||||
}
|
||||
if hasattr(self, "_password"):
|
||||
dct["password"] = self._password
|
||||
|
||||
@@ -157,6 +157,7 @@ class HeaderNavigation(Navigation):
|
||||
"user_profile_mobile_number_delete",
|
||||
"user_profile_name",
|
||||
"user_profile_password",
|
||||
"user_profile_preferred_timezone",
|
||||
"user_profile_disable_platform_admin_view",
|
||||
},
|
||||
"platform-admin": {
|
||||
|
||||
@@ -12,6 +12,7 @@ ALLOWED_ATTRIBUTES = {
|
||||
"updated_by",
|
||||
"current_session_id",
|
||||
"email_access_validated_at",
|
||||
"preferred_timezone",
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<div class="grid-row">
|
||||
<div class="grid-col-12">
|
||||
<div class="template-content-count">
|
||||
<div class="template-content-count" bg-color="red">
|
||||
<div data-module="update-status" data-target="template_content"
|
||||
data-updates-url="{{ url_for('.count_content_length', service_id=current_service.id, template_type='sms') }}"
|
||||
aria-live="polite">
|
||||
@@ -69,7 +69,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tablet:grid-col-9 mobile-lg:grid-col-12">
|
||||
<h2 id="help" class="font-body-xl margin-top-2">How to customize your message</h2>
|
||||
<div class="usa-accordion usa-accordion--bordered usa-accordion--multiselectable maxw-mobile-lg" data-allow-multiple>
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
<p>
|
||||
You can send up to
|
||||
{{ "{:,}".format(current_service.message_limit) }} messages
|
||||
per day.
|
||||
per year.
|
||||
</p>
|
||||
<p>
|
||||
Problems or comments?
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% block maincolumn_content %}
|
||||
|
||||
<div class="">
|
||||
<h1 class="font-body-2xl margin-bottom-3">{{ page_title }}</h1>
|
||||
<h1 class="font-body-2xl margin-y-0">{{ page_title }}</h1>
|
||||
{{ copy_folder_path(template_folder_path, current_service.id, from_service, current_user) }}
|
||||
</div>
|
||||
{% if not services_templates_and_folders.templates_to_show %}
|
||||
@@ -28,32 +28,24 @@
|
||||
<nav id="template-list">
|
||||
<ul>
|
||||
{% for item in services_templates_and_folders %}
|
||||
<li class="template-list-item {% if item.ancestors %}template-list-item-hidden-by-default{% endif %} {% if not item.ancestors %}template-list-item-without-ancestors{% endif %}">
|
||||
{% for ancestor in item.ancestors %}
|
||||
{% if ancestor.is_service %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_service=ancestor.service_id) }}" class="usa-link template-list-folder">
|
||||
{% else %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_folder=ancestor.id) }}" class="usa-link template-list-folder">
|
||||
{% endif %}
|
||||
{{ ancestor.name }}
|
||||
</a> <span class="message-name-separator"></span>
|
||||
{% endfor %}
|
||||
|
||||
<li class="template-list-item margin-bottom-2 {% if item.ancestors %}template-list-item-hidden-by-default{% endif %} {% if not item.ancestors %}template-list-item-without-ancestors{% endif %}">
|
||||
{% if item.is_service %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_service=item.service_id) }}" class="usa-link template-list-folder">
|
||||
<span class="live-search-relevant">{{ item.name }}</span>
|
||||
</a>
|
||||
{% elif item.is_folder %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_service=item.service_id, from_folder=item.id) }}" class="usa-link template-list-folder">
|
||||
<span class="live-search-relevant">{{ item.name }}</span>
|
||||
</a>
|
||||
{% else %}
|
||||
{% for ancestor in item.ancestors %}
|
||||
{% if ancestor.is_service %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_service=ancestor.service_id) }}" class="usa-link template-list-folder">
|
||||
{% else %}
|
||||
<a href="{{ url_for('.choose_template_to_copy', service_id=current_service.id, from_folder=ancestor.id) }}" class="usa-link template-list-folder">
|
||||
{% endif %}
|
||||
{{ ancestor.name }}
|
||||
</a> <span class="message-name-separator"></span>
|
||||
{% endfor %}
|
||||
<a class="usa-link template-list-template" href="{{ url_for('.copy_template', service_id=current_service.id, template_id=item.id, from_service=item.service_id) }}">
|
||||
<span class="live-search-relevant">{{ item.name }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
<p class="template-list-item-hint usa-hint usa-checkbox__label-description">
|
||||
{{ item.hint }}
|
||||
</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
@@ -63,6 +63,16 @@
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
{% call row() %}
|
||||
{{ text_field('Preferred Timezone') }}
|
||||
{{ optional_text_field(current_user.preferred_timezone) }}
|
||||
{{ edit_field(
|
||||
'Change',
|
||||
url_for('.user_profile_preferred_timezone'),
|
||||
suffix='preferred timezone'
|
||||
)
|
||||
}}
|
||||
{% endcall %}
|
||||
|
||||
{% if current_user.platform_admin or session.get('disable_platform_admin_view') %}
|
||||
{% call row(id='disable-platform-admin') %}
|
||||
|
||||
Reference in New Issue
Block a user