Skip to content

Commit

Permalink
Implement delete for template categories (#1890)
Browse files Browse the repository at this point in the history
* Initial TemplateCategory client

* Hook the api client up to the admin front end

- Implemented add and update a category
- Tweaks to the api client
- Added tests for the API client
- Renamed desc_en/desc_fr to description_en/fr for consistency

* Implement category delete

- Added template category to cache clear list

* fix

* formatting

* Add confirmation message when adding and updating a category

* Add error message

- Add an error message banner when attempting to delete a template category that is already associated with template(s)

* Small fixes

* Formatting

* Fix tests

* Add translations

- Add an additional unit test for the api client
- Make sure page elements are properly translated

* Add support for sms sending vehicle

- Added sms sending vehicle radio buttons to the template-category page
- Updated the API client to include the sms sending vehicle param
- updated a few translation strings

* Translation fixes

* Add Cypress tests

- Fixed an issue where  was displaying 'Update Category' when creating a category
- Added some data-testid's
- Corrected some translations
- Fixed tests

* Fix missing translations

- Updated the flash messages

* formatting...

* Remove unused import

* formatting...........

* Update app/main/forms.py

Co-authored-by: Andrew <[email protected]>

* Improve DB state management between tests

* Remove unnecessary variable

* Formatting

* Rearrange test execution order

- Rearrange the test order and added an after() to the suite as a reference for properly cleaning up the DB post test suite

---------

Co-authored-by: Andrew <[email protected]>
  • Loading branch information
whabanks and andrewleith authored Jul 23, 2024
1 parent 63b3cdb commit cb3affc
Show file tree
Hide file tree
Showing 15 changed files with 509 additions and 51 deletions.
16 changes: 10 additions & 6 deletions app/main/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1916,13 +1916,17 @@ class BrandingRequestForm(StripWhitespaceForm):


class TemplateCategoryForm(StripWhitespaceForm):
name_en = StringField("Name EN", validators=[DataRequired(message=_l("This cannot be empty"))])
name_fr = StringField("Name FR", validators=[DataRequired(message=_l("This cannot be empty"))])
description_en = StringField("Desc EN")
description_fr = StringField("Desc FR")
hidden = RadioField(_l("Hide category"), choices=[("True", _l("Hide")), ("False", _l("Show"))])
name_en = StringField("EN", validators=[DataRequired(message=_l("This cannot be empty"))])
name_fr = StringField("FR", validators=[DataRequired(message=_l("This cannot be empty"))])
description_en = StringField("EN")
description_fr = StringField("FR")
hidden = RadioField(_l("Category visibility"), choices=[("True", _l("Hide")), ("False", _l("Show"))])
sms_sending_vehicle = RadioField(
_l("Sending method for text messages"), choices=[("long_code", _l("Long code")), ("short_code", _l("Short code"))]
)

email_process_type = RadioField(
_l("Email Priority"),
_l("Email priority"),
choices=[
("priority", _l("High")),
("normal", _l("Medium")),
Expand Down
1 change: 1 addition & 0 deletions app/main/views/platform_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ def clear_cache():
"template-????????-????-????-????-????????????-versions",
],
),
("template_category", ["template_categories", "template_category-????????-????-????-????-????????????"]),
(
"email_branding",
[
Expand Down
76 changes: 66 additions & 10 deletions app/main/views/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@

# Todo: Remove this once the process_types in the backend are updated to use low/med/high
category_mapping = {
"bulk": "low",
"normal": "medium",
"priority": "high",
"bulk": "Low",
"normal": "Medium",
"priority": "High",
}

form_objects_with_category = {
Expand Down Expand Up @@ -1293,7 +1293,8 @@ def add_recipients(service_id, template_id):
)


@main.route("/template-categories", methods=["GET", "POST"])
@main.route("/template-categories", methods=["GET"])
@main.route("/template-categories/<template_category_id>", methods=["POST"])
@user_is_platform_admin
def template_categories():
template_category_list = template_category_api_client.get_all_template_categories()
Expand All @@ -1312,7 +1313,51 @@ def template_categories():
)


@main.route("/template-categories/add", methods=["GET", "POST"])
@main.route("/template-category/<template_category_id>/delete", methods=["GET", "POST"])
@user_is_platform_admin
def delete_template_category(template_category_id):
template_category = template_category_api_client.get_template_category(template_category_id)

if request.method == "POST":
try:
template_category_api_client.delete_template_category(template_category_id)
except HTTPError:
flash(
[
_l("Cannot delete template category, ‘{}’, is associated with templates").format(
(template_category["name_en"] if session["userlang"] == "en" else template_category["name_fr"])
)
]
)
return redirect(url_for(".template_categories"))

flash(
[
"{} ‘{}’?".format(
_l("Are you sure you want to delete"),
(template_category["name_en"] if session["userlang"] == "en" else template_category["name_fr"]),
),
],
"delete",
)

form = TemplateCategoryForm(
name_en=template_category["name_en"],
name_fr=template_category["name_fr"],
description_en=template_category["description_en"],
description_fr=template_category["description_fr"],
hidden=template_category["hidden"],
email_process_type=template_category["email_process_type"],
sms_process_type=template_category["sms_process_type"],
)

return render_template(
"views/templates/template_category.html", search_form=SearchByNameForm(), template_category=template_category, form=form
)


@main.route("/template-categories")
@main.route("/template-category/add", methods=["GET", "POST"])
@user_is_platform_admin
def add_template_category():
form = TemplateCategoryForm()
Expand All @@ -1326,15 +1371,20 @@ def add_template_category():
hidden=form.data["hidden"],
email_process_type=form.data["email_process_type"],
sms_process_type=form.data["sms_process_type"],
sms_sending_vehicle=form.data["sms_sending_vehicle"],
)
flash(
_("Template category '{}' added.").format(
form.data["name_en"] if session["userlang"] == "en" else form.data["name_fr"]
),
"default_with_tick",
)

flash(_("Template category added."), "default_with_tick")
return redirect(url_for(".template_categories"))

return render_template("views/templates/template_category.html", search_form=SearchByNameForm(), form=form)


@main.route("/template-categories/<template_category_id>", methods=["GET", "POST"])
@main.route("/template-category/<template_category_id>", methods=["GET", "POST"])
@user_is_platform_admin
def template_category(template_category_id):
template_category = template_category_api_client.get_template_category(template_category_id)
Expand All @@ -1346,6 +1396,7 @@ def template_category(template_category_id):
hidden=template_category["hidden"],
email_process_type=template_category["email_process_type"],
sms_process_type=template_category["sms_process_type"],
sms_sending_vehicle=template_category["sms_sending_vehicle"],
)

if form.validate_on_submit():
Expand All @@ -1358,9 +1409,14 @@ def template_category(template_category_id):
hidden=form.data["hidden"],
email_process_type=form.data["email_process_type"],
sms_process_type=form.data["sms_process_type"],
sms_sending_vehicle=form.data["sms_sending_vehicle"],
)
flash(
_("Template category '{}' saved.").format(
form.data["name_en"] if session["userlang"] == "en" else form.data["name_fr"]
),
"default_with_tick",
)

flash("Template category saved.", "default_with_tick")
return redirect(url_for(".template_categories"))

return render_template(
Expand Down
23 changes: 20 additions & 3 deletions app/notify_client/template_category_api_client.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from requests import HTTPError

from app.notify_client import NotifyAdminAPIClient, cache


class TemplateCategoryClient(NotifyAdminAPIClient):
@cache.delete("template_categories")
def create_template_category(
self, name_en, name_fr, description_en, description_fr, sms_process_type, email_process_type, hidden
self, name_en, name_fr, description_en, description_fr, sms_process_type, email_process_type, hidden, sms_sending_vehicle
):
data = {
"name_en": name_en,
Expand All @@ -14,6 +16,7 @@ def create_template_category(
"sms_process_type": sms_process_type,
"email_process_type": email_process_type,
"hidden": True if hidden == "True" else False,
"sms_sending_vehicle": sms_sending_vehicle,
}
return self.post(url="/template-category", data=data)

Expand All @@ -35,7 +38,16 @@ def get_all_template_categories(self, template_type=None, hidden=None, sort_key=
@cache.delete("template_category-{template_category_id}")
@cache.delete("template_categories")
def update_template_category(
self, template_category_id, name_en, name_fr, description_en, description_fr, sms_process_type, email_process_type, hidden
self,
template_category_id,
name_en,
name_fr,
description_en,
description_fr,
sms_process_type,
email_process_type,
hidden,
sms_sending_vehicle,
):
data = {
"name_en": name_en,
Expand All @@ -45,13 +57,18 @@ def update_template_category(
"sms_process_type": sms_process_type,
"email_process_type": email_process_type,
"hidden": hidden,
"sms_sending_vehicle": sms_sending_vehicle,
}
return self.post(url="/template-category/{}".format(template_category_id), data=data)

@cache.delete("template_category-{template_category_id}")
@cache.delete("template_categories")
def delete_template_category(self, template_category_id, cascade=False):
return self.delete(url="/template-category/{}".format(template_category_id), data=cascade)
try:
self.delete(url="/template-category/{}".format(template_category_id), data=cascade)
except HTTPError as e:
if e.response.status_code == 400:
raise e


template_category_api_client = TemplateCategoryClient()
6 changes: 2 additions & 4 deletions app/templates/components/textbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ <h1><label class="form-label heading-large" for="{{ field.name }}" >

{% macro textbox_localized(
name,
fields,
fields,
legend,
hint=None,
describedby=""
Expand All @@ -166,13 +166,11 @@ <h1><label class="form-label heading-large" for="{{ field.name }}" >
{% endif %}
<div class="localized-field-fields flex w-full">
{% for lang, localized_field in fields.items() %}

{% set error_msg = "" %}
{% if localized_field.validators | length > 0 %}
{% set error_msg = localized_field.validators[0].message %}
{% endif %}

{{ textbox(localized_field, localized_field.label.text, width='w-full', data_error_msg=error_msg, lang=lang) }}
{{ textbox(localized_field, localized_field.label.text, width='w-full', data_error_msg=error_msg, lang=lang, testid=name + "-" + lang) }}
{% endfor %}
</div>
</fieldset>
Expand Down
33 changes: 19 additions & 14 deletions app/templates/views/templates/template_categories.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,38 @@
{% call(item, row_number) list_table(
template_categories,
caption=_('Template categories'),
field_headings=['Category name', 'Email Priority', 'SMS Priority', 'Hidden?'],
field_headings=[_('Category name'), _('Email priority'), _('Text message priority'), _('Visibility')],
field_headings_visible=True,
caption_visible=False,
testid="template-categories-table"
) %}
{% set name = _(item.name_en) if session['userlang'] == 'en' else _(item.name_fr) %}
{% set email_process_type = _(item.email_process_type) %}
{% set sms_process_type = _(item.sms_process_type) %}

{% call field() %}
<a class="template-cat" href="{{ url_for('main.template_category', template_category_id=item.id)}}">
{% if current_lang == "en" %}
{{ item.name_en }}
{% else %}
{{ item.name_fr }}
{% endif %}
<a class="template-cat" data-testid="edit-category-{{item.id}}" href="{{ url_for('main.template_category', template_category_id=item.id)}}">
{{ name }}
</a>
{% endcall %}
{% call field() %}
{{ item.email_process_type }}
{% endcall %}
{% call field() %}
{{ item.sms_process_type }}
{{ email_process_type }}
{% endcall %}
{% call field() %}
{{ item.hidden }}
{{ sms_process_type }}
{% endcall %}
{% if item.hidden %}
{% call field(status='error') %}
{{ _("Hide") }}
{% endcall %}
{% else %}
{% call field() %}
{{ _("Visible") }}
{% endcall %}
{% endif %}
{% endcall %}

<div class="js-stick-at-bottom-when-scrolling">
<a href="{{url_for('.add_template_category')}}" class="mt-gutter button button">{{ _('New category') }}</a>
<a href="{{url_for('.add_template_category')}}" data-testid="add-template-category-button" class="mt-gutter button button">{{ _('New category') }}</a>
</div>
</div>

Expand Down
6 changes: 4 additions & 2 deletions app/templates/views/templates/template_category.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</div>
</div>

{{ page_header(_('Update category'), id_text='template_cats') }}
{{ page_header(_('Update category') if template_category else _('Create category'), id_text='template_cats') }}
{% call form_wrapper() %}
<div class="form-group contain-floats box-border mb-gutterHalf md:mb-gutter">

Expand All @@ -33,12 +33,14 @@
{{ radios(form.hidden) }}
{{ radios(form.email_process_type) }}
{{ radios(form.sms_process_type) }}
{{ radios(form.sms_sending_vehicle)}}

<div class="js-stick-at-bottom-when-scrolling">
{{ page_footer(
_('Save'),
button_name='operation',
button_value='email-branding-details'
button_value='email-branding-details',
delete_link=url_for('.delete_template_category', template_category_id=template_category.id) if template_category else None,
) }}
</div>
</div>
Expand Down
32 changes: 23 additions & 9 deletions app/translations/csv/fr.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1911,15 +1911,29 @@
"Read and agree to the terms of use","Lisez et acceptez les conditions d’utilisation"
"Read and agree to continue","Lire et accepter pour continuer"
"Agree follows terms of use","Accepter suite aux conditions d'utilisation"
"High","FR: High"
"Medium","FR: Medium"
"Low","PR: Low"
"Text message priority","FR: Text message priority"
"Hide category","FR: Hide category"
"Email Priority","FR: Email Priority"
"Hide","FR: Hide"
"Category label","FR: Category label"
"High","Élevée"
"Medium","Moyenne"
"Low","Faible"
"Text message priority","Niveau de priorité des messages texte"
"Hide category","Visibilité de la catégorie"
"Email priority","Niveau de priorité des courriels"
"Hide","Invisible"
"Visible","Visible"
"Category label","Étiquette de la catégorie"
"Category description","Description de la catégorie"
"Select category","Sélectionnez une catégorie"
"Template categories","Catégories de gabarits"
"New category","Nouvelle catégorie"
"Update category","Mettre à jour la catégorie"
"Template category '{}' saved.","Catégorie de gabarit enregistré."
"Cannot delete template category, ‘{}’, is associated with templates",""
"Long code","Code long"
"Short code","Code abrégé"
"Category visibility","Visibilité de la catégorie"
"You cannot delete a template category that is associated with a template","Impossible de supprimer la catégorie de gabarit ‘{}’, elle est associée à des gabarits."
"Category name","Nom de la catégorie"
"Visibility","Visibilité"
"Sending method for text messages","Méthode d’envoi pour les messages texte"
"Privacy notice","avis de confidentialité"
"For CDS responsibilities, read GC Notify’s ","Pour connaître les responsabilités du SNC, veuillez lire "
"We may suspend your account or service if you break these terms or misuse GC Notify. Misuse includes creating duplicate services or services incompatible with your original purpose.","Il se pourrait que nous suspendions votre compte ou les services auxquels vous avez accès si vous ne respectez pas ces conditions ou si vous faites une utilisation abusive de Notification GC. La création de copies de services ou la création de services ne correspondant pas à votre intention originale constituent des utilisations abusives de cet outil."
Expand Down Expand Up @@ -1956,7 +1970,7 @@
"Describe category","Décrivez la catégorie"
"Use template category","Selon la catégorie"
"Change category","Changer de catégorie"
"Template category added.","Catégorie de gabarit ajoutée."
"Template category '{}' added.","Catégorie de gabarit '{}' ajoutée."
"Name of parent organisation","Nom de l'organisme parent"
"Alternative text","Texte de remplacement"
"Provide an accessible description of your logo","Fournissez une description accessible de votre logo"
8 changes: 5 additions & 3 deletions tests/app/main/views/test_platform_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,9 +995,10 @@ def test_clear_cache_shows_form(client_request, platform_admin_user, mocker):
assert page.select("input[type=radio]")[0]["value"] == "user"
assert page.select("input[type=radio]")[1]["value"] == "service"
assert page.select("input[type=radio]")[2]["value"] == "template"
assert page.select("input[type=radio]")[3]["value"] == "email_branding"
assert page.select("input[type=radio]")[4]["value"] == "letter_branding"
assert page.select("input[type=radio]")[5]["value"] == "organisation"
assert page.select("input[type=radio]")[3]["value"] == "template_category"
assert page.select("input[type=radio]")[4]["value"] == "email_branding"
assert page.select("input[type=radio]")[5]["value"] == "letter_branding"
assert page.select("input[type=radio]")[6]["value"] == "organisation"
assert not redis.delete_cache_keys_by_pattern.called


Expand Down Expand Up @@ -1427,6 +1428,7 @@ class TestTemplateCategory:
"email_process_type": "email_priority-123",
"sms_process_type": "sms_priority-123",
"hidden": "hidden-123",
"sms_sending_vehicle": "long_code",
}

def test_item_displays_in_admin_menu(self, platform_admin_client, platform_admin_user, mocker):
Expand Down
Loading

0 comments on commit cb3affc

Please sign in to comment.