Merge pull request #2663 from GSA/2253-bug-on-template-page

Fixes for several bugs on the templates page related to form submission issues
This commit is contained in:
ccostino
2025-06-11 17:52:32 -04:00
committed by GitHub
7 changed files with 68 additions and 20 deletions

View File

@@ -20,7 +20,6 @@
$targets.each(function() { $targets.each(function() {
let content = $('.live-search-relevant', this).text() || $(this).text(); let content = $('.live-search-relevant', this).text() || $(this).text();
let isMatch = normalize(content).indexOf(normalize(query)) > -1;
if ($(this).has(':checked').length) { if ($(this).has(':checked').length) {
$(this).show(); $(this).show();
@@ -29,21 +28,25 @@
} }
if (query == '') { if (query == '') {
$(this).css('display', ''); $(this).removeClass('js-hidden');
results++; results++;
return; return;
} }
$(this).toggle(isMatch); let isMatch = normalize(content).includes(normalize(query));
if (isMatch) { results++; }
if (isMatch) {
$(this).removeClass('js-hidden');
results++;
} else {
$(this).addClass('js-hidden');
}
}); });
if (query !== '' && results === 0) { if (query !== '' && results === 0) {
$noResultsMessage.show(); $noResultsMessage.removeClass('js-hidden');
} else { } else {
$noResultsMessage.hide(); $noResultsMessage.addClass('js-hidden');
} }
if (state === 'loaded') { if (state === 'loaded') {

View File

@@ -197,6 +197,11 @@
if (event.currentTarget.value === 'add-new-template' && this.$singleNotificationChannel) { if (event.currentTarget.value === 'add-new-template' && this.$singleNotificationChannel) {
window.location = "/services/" + this.$singleChannelService + "/templates/add-" + this.$singleNotificationChannel; window.location = "/services/" + this.$singleChannelService + "/templates/add-" + this.$singleNotificationChannel;
} else { } else {
if (this.currentState === 'add-new-template') {
this.$form.find('input[type=checkbox]').prop('checked', false);
this.selectionStatus.update({ total: 0, templates: 0, folders: 0 });
}
if (this.stateChanged()) { if (this.stateChanged()) {
this.render(); this.render();
} }
@@ -286,7 +291,29 @@
mode = 'dialog'; mode = 'dialog';
} }
if (currentStateObj && ('setFocus' in currentStateObj)) { if (this.currentState === 'add-new-template') {
this.$form.find('.template-list-item').addClass('js-hidden');
$('.live-search').addClass('js-hidden');
$('#breadcrumb-template-folders').addClass('js-hidden');
$('#template-list').addClass('js-hidden');
this.$form.find('input[type=checkbox]').prop('checked', false);
this.selectionStatus.update({ total: 0, templates: 0, folders: 0 });
$('#page-title').text('New Template');
$('#page-description').text('Every message starts with a template. Choose to start with a blank template or copy an existing template.');
document.title = 'New Templates';
} else {
this.$form.find('.template-list-item').removeClass('js-hidden');
$('.live-search').removeClass('js-hidden');
$('#breadcrumb-template-folders').removeClass('js-hidden');
$('#template-list').removeClass('js-hidden');
$('#page-title').text('Select or create a template');
$('#page-description').text('Every message starts with a template. To send, choose or create a template.');
document.title = 'Select or create a template';
}
if (currentStateObj && 'setFocus' in currentStateObj) {
scrollTop = $(window).scrollTop(); scrollTop = $(window).scrollTop();
currentStateObj.setFocus(); currentStateObj.setFocus();
$(window).scrollTop(scrollTop); $(window).scrollTop(scrollTop);

View File

@@ -229,6 +229,10 @@ td.table-empty-message {
display: none; display: none;
} }
.js-hidden {
display: none !important;
}
.folder-heading a.folder-heading-folder, .folder-heading a.folder-heading-folder,
.template-list-folder { .template-list-folder {
background: url(../img/material-icons/folder.svg) no-repeat; background: url(../img/material-icons/folder.svg) no-repeat;

View File

@@ -40,7 +40,7 @@
<nav id="template-list" aria-label="Choose reply"> <nav id="template-list" aria-label="Choose reply">
<ul> <ul>
{% for item in templates_and_folders %} {% for item in 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 %}"> <li class="template-list-item {% if item.ancestors %}template-list-item-hidden-by-default{% else %}template-list-item-without-ancestors{% endif %}">
{% for ancestor in item.ancestors %} {% for ancestor in item.ancestors %}
<a href="{{ url_for('.conversation_reply', service_id=current_service.id, notification_id=notification_id, from_folder=ancestor.id) }}" class="usa-link template-list-folder"> <a href="{{ url_for('.conversation_reply', service_id=current_service.id, notification_id=notification_id, from_folder=ancestor.id) }}" class="usa-link template-list-folder">
{{ ancestor.name }} {{ ancestor.name }}

View File

@@ -32,9 +32,9 @@
{% else %} {% else %}
<div class="grid-row flex-column"> <div class="grid-row flex-column">
<h1 class="font-body-2xl line-height-sans-2 margin-bottom-1 margin-top-0">{{page_title}}</h1> <h1 class="font-body-2xl line-height-sans-2 margin-bottom-1 margin-top-0" id="page-title">{{page_title}}</h1>
<div class="{% if current_user.has_permissions('manage_templates') %} grid-col-10 {% else %} grid-col-12 {% endif %}"> <div class="{% if current_user.has_permissions('manage_templates') %} grid-col-10 {% else %} grid-col-12 {% endif %}">
<p class="margin-top-0 margin-bottom-4"> <p class="margin-top-0 margin-bottom-4" id="page-description">
Every message starts with a template. To send, choose or create a template. Every message starts with a template. To send, choose or create a template.
</p> </p>
{{ folder_path( {{ folder_path(
@@ -59,6 +59,10 @@
{{ live_search(target_selector='#template-list .template-list-item', show=show_search_box, form=search_form) }} {{ live_search(target_selector='#template-list .template-list-item', show=show_search_box, form=search_form) }}
<div class="js-live-search-no-results" style="display: none;">
<p class="usa-body margin-top-2">No templates found</p>
</div>
{% if current_user.has_permissions('manage_templates') and user_has_template_folder_permission %} {% if current_user.has_permissions('manage_templates') and user_has_template_folder_permission %}
{% call form_wrapper( {% call form_wrapper(
class='sticky-scroll-area', class='sticky-scroll-area',

View File

@@ -1,5 +1,6 @@
{% from "components/folder-path.html" import copy_folder_path, page_title_folder_path %} {% from "components/folder-path.html" import copy_folder_path, page_title_folder_path %}
{% from "components/live-search.html" import live_search %} {% from "components/live-search.html" import live_search %}
{% from "components/components/back-link/macro.njk" import usaBackLink %}
{% extends "withnav_template.html" %} {% extends "withnav_template.html" %}
{% set page_title = "Copy an existing template" %} {% set page_title = "Copy an existing template" %}
@@ -8,6 +9,12 @@
{{ page_title }} {{ page_title }}
{% endblock %} {% endblock %}
{% block backLink %}
{% if not from_service %}
{{ usaBackLink({ "href": url_for('.choose_template', service_id=current_service.id),
"html": "Back to all templates" }) }}
{% endif %}
{% endblock %}
{% block maincolumn_content %} {% block maincolumn_content %}
<div class=""> <div class="">
@@ -25,11 +32,14 @@
form=search_form, form=search_form,
autofocus=True autofocus=True
) }} ) }}
<div class="js-live-search-no-results" style="display: none;">
<p class="usa-body margin-top-2">No templates found</p>
</div>
<nav id="template-list" aria-label="Copy template list"> <nav id="template-list" aria-label="Copy template list">
<ul> <ul>
{% for item in services_templates_and_folders %} {% for item in services_templates_and_folders %}
<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 %}"> <li class="template-list-item margin-bottom-2">
{% if item.is_service %} {% if item.is_service %}
{% elif item.is_folder %} {% elif item.is_folder %}
{% else %} {% else %}

View File

@@ -135,7 +135,7 @@ describe('Live search', () => {
window.GOVUK.modules.start(); window.GOVUK.modules.start();
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(listItems.length); expect(listItemsShowing.length).toEqual(listItems.length);
expect(searchTextbox.hasAttribute('aria-label')).toBe(false); expect(searchTextbox.hasAttribute('aria-label')).toBe(false);
@@ -150,7 +150,7 @@ describe('Live search', () => {
window.GOVUK.modules.start(); window.GOVUK.modules.start();
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(1); expect(listItemsShowing.length).toEqual(1);
expect(searchTextbox.hasAttribute('aria-label')).toBe(true); expect(searchTextbox.hasAttribute('aria-label')).toBe(true);
@@ -166,7 +166,7 @@ describe('Live search', () => {
window.GOVUK.modules.start(); window.GOVUK.modules.start();
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(1); expect(listItemsShowing.length).toEqual(1);
expect(searchTextbox.hasAttribute('aria-label')).toBe(true); expect(searchTextbox.hasAttribute('aria-label')).toBe(true);
@@ -182,7 +182,7 @@ describe('Live search', () => {
window.GOVUK.modules.start(); window.GOVUK.modules.start();
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
// all items contain the "Add and edit templates" permission so would match if all text was matched against the search term // all items contain the "Add and edit templates" permission so would match if all text was matched against the search term
// only the text containing the label and email address is matched against // only the text containing the label and email address is matched against
@@ -207,7 +207,7 @@ describe('Live search', () => {
helpers.triggerEvent(searchTextbox, 'input'); helpers.triggerEvent(searchTextbox, 'input');
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(listItems.length); expect(listItemsShowing.length).toEqual(listItems.length);
@@ -225,7 +225,7 @@ describe('Live search', () => {
helpers.triggerEvent(searchTextbox, 'input'); helpers.triggerEvent(searchTextbox, 'input');
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(1); expect(listItemsShowing.length).toEqual(1);
expect(liveRegion.textContent.trim()).toEqual(liveRegionResults(1)); expect(liveRegion.textContent.trim()).toEqual(liveRegionResults(1));
@@ -244,7 +244,7 @@ describe('Live search', () => {
helpers.triggerEvent(searchTextbox, 'input'); helpers.triggerEvent(searchTextbox, 'input');
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
expect(listItemsShowing.length).toEqual(1); expect(listItemsShowing.length).toEqual(1);
expect(liveRegion.textContent.trim()).toEqual(liveRegionResults(1)); expect(liveRegion.textContent.trim()).toEqual(liveRegionResults(1));
@@ -263,7 +263,7 @@ describe('Live search', () => {
helpers.triggerEvent(searchTextbox, 'input'); helpers.triggerEvent(searchTextbox, 'input');
const listItems = list.querySelectorAll('.user-list-item'); const listItems = list.querySelectorAll('.user-list-item');
const listItemsShowing = Array.from(listItems).filter(item => window.getComputedStyle(item).display !== 'none'); const listItemsShowing = Array.from(listItems).filter(item => !item.classList.contains('js-hidden'));
// all items contain the "Add and edit templates" permission so would match if all text was matched against the search term // all items contain the "Add and edit templates" permission so would match if all text was matched against the search term
// only the text containing the label and email address is matched against // only the text containing the label and email address is matched against