@ministryofjustice/hmpps-digital-prison-reporting-frontend 9.3.1 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all.bundle.js +91 -90
- package/all.bundle.js.map +1 -1
- package/all.js +91 -90
- package/all.js.map +1 -1
- package/cjs/dpr/components/_dashboards/DataPresentation.js +1 -1
- package/cjs/dpr/components/_dashboards/DataPresentation.js.map +1 -1
- package/cjs/dpr/components/bookmark/utils.js +4 -1
- package/cjs/dpr/components/bookmark/utils.js.map +1 -1
- package/cjs/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-actions/utils.js +8 -5
- package/cjs/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-actions/utils.js.map +1 -1
- package/cjs/dpr/components/my-reports/types.js.map +1 -1
- package/cjs/dpr/components/my-reports/utils.js +4 -2
- package/cjs/dpr/components/my-reports/utils.js.map +1 -1
- package/cjs/dpr/routes/journeys/my-reports/bookmarks/controller.js +16 -2
- package/cjs/dpr/routes/journeys/my-reports/bookmarks/controller.js.map +1 -1
- package/dpr/all.scss +90 -4
- package/dpr/components/_async/async-filters-form/actions/selected-filters/view.njk +10 -1
- package/dpr/components/_dashboards/DataPresentation.js +1 -1
- package/dpr/components/_dashboards/DataPresentation.js.map +1 -1
- package/dpr/components/bookmark/utils.js +4 -1
- package/dpr/components/bookmark/utils.js.map +1 -1
- package/dpr/components/bookmark/view.njk +54 -15
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-actions/utils.js +8 -5
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-actions/utils.js.map +1 -1
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-actions/view.njk +6 -1
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-description/view.njk +1 -0
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/catalogure-row-variant-heading/view.njk +1 -0
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/catalogue-variant-rows/catalogue-variant-row/view.njk +1 -1
- package/dpr/components/catalogue/catalogue-product-rows/catalogue-product-row/view.njk +2 -0
- package/dpr/components/catalogue/catalogue-totals/view.njk +1 -1
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-actions/view.njk +2 -0
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-description/view.njk +1 -0
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-filters/view.njk +1 -0
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-schedule/view.njk +1 -0
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-status/view.njk +1 -0
- package/dpr/components/my-reports/my-reports-list-item/my-reports-list-item-title/view.njk +2 -0
- package/dpr/components/my-reports/types.d.ts +1 -0
- package/dpr/components/my-reports/types.js.map +1 -1
- package/dpr/components/my-reports/utils.js +4 -2
- package/dpr/components/my-reports/utils.js.map +1 -1
- package/dpr/components/subscription/subscription-toggle/view.njk +1 -0
- package/dpr/routes/journeys/my-reports/bookmarks/controller.js +16 -2
- package/dpr/routes/journeys/my-reports/bookmarks/controller.js.map +1 -1
- package/package.json +1 -1
- package/src/dpr/components/_async/async-filters-form/actions/selected-filters/clientClass.d.ts +1 -0
- package/src/dpr/components/_dashboards/visual-regression-tests/helpers/vrtHelpers.spec.d.ts +4 -0
- package/src/dpr/components/bookmark/clientClass.d.ts +10 -29
- package/src/dpr/components/bookmark/utils.d.ts +3 -1
- package/src/dpr/components/my-reports/types.d.ts +1 -0
- package/src/dpr/components/_dashboards/visual-regression-tests/vrtHelpers.d.ts +0 -2
package/all.bundle.js
CHANGED
|
@@ -54,106 +54,94 @@ class DprClientClass {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
var BookmarkAction;
|
|
58
|
-
(function (BookmarkAction) {
|
|
59
|
-
BookmarkAction["ADD"] = "add";
|
|
60
|
-
BookmarkAction["REMOVE"] = "remove";
|
|
61
|
-
})(BookmarkAction || (BookmarkAction = {}));
|
|
62
57
|
class BookmarkButton extends DprClientClass {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
reportType;
|
|
68
|
-
endpoint;
|
|
69
|
-
baseUrl;
|
|
70
|
-
isRunning = false;
|
|
58
|
+
isSubmitting = false;
|
|
59
|
+
form;
|
|
60
|
+
button;
|
|
61
|
+
typeInput;
|
|
71
62
|
static getModuleName() {
|
|
72
63
|
return 'bookmark-button';
|
|
73
64
|
}
|
|
74
65
|
initialise() {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
this.linkType = this.element.getAttribute('data-link-type') || BookmarkAction.ADD;
|
|
81
|
-
this.setReportType();
|
|
82
|
-
this.endpoint = element.getAttribute('data-endpoint') || '';
|
|
83
|
-
this.csrfToken = element.getAttribute('data-csrf-token') || '';
|
|
84
|
-
this.initEventListener();
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Updates the bookmark button UI so that it shows:
|
|
88
|
-
* - the correct text
|
|
89
|
-
* - toggles the bookmark on and off correctly
|
|
90
|
-
*
|
|
91
|
-
* @memberof BookmarkButton
|
|
92
|
-
*/
|
|
93
|
-
updateUI() {
|
|
94
|
-
this.linkType = this.linkType === BookmarkAction.ADD ? BookmarkAction.REMOVE : BookmarkAction.ADD;
|
|
95
|
-
const textContent = this.linkType === BookmarkAction.ADD ? 'Add bookmark' : 'Remove bookmark';
|
|
96
|
-
const element = this.getElement();
|
|
97
|
-
element.setAttribute('data-link-type', this.linkType);
|
|
98
|
-
element.textContent = textContent;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Inits the bookmark button click event
|
|
102
|
-
*
|
|
103
|
-
* @memberof BookmarkButton
|
|
104
|
-
*/
|
|
105
|
-
initEventListener() {
|
|
106
|
-
this.getElement().addEventListener('click', (e) => this.activateBookmark(e));
|
|
107
|
-
this.getElement().addEventListener('keydown', (e) => {
|
|
108
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
109
|
-
this.activateBookmark(e);
|
|
110
|
-
}
|
|
66
|
+
this.form = this.getElement();
|
|
67
|
+
this.button = this.form.querySelector('[data-bookmark-button="true"]');
|
|
68
|
+
this.typeInput = this.form.querySelector('input[name="type"]');
|
|
69
|
+
this.form.addEventListener('submit', event => {
|
|
70
|
+
void this.handleSubmit(event);
|
|
111
71
|
});
|
|
112
72
|
}
|
|
113
|
-
async
|
|
114
|
-
|
|
115
|
-
if (this.
|
|
73
|
+
async handleSubmit(event) {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
if (this.isSubmitting) {
|
|
116
76
|
return;
|
|
117
|
-
|
|
118
|
-
this.
|
|
77
|
+
}
|
|
78
|
+
if (!this.button || !this.typeInput) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
119
81
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
body: JSON.stringify({
|
|
128
|
-
type: this.linkType,
|
|
129
|
-
id: this.id,
|
|
130
|
-
reportId: this.reportId,
|
|
131
|
-
reportType: this.reportType,
|
|
132
|
-
}),
|
|
133
|
-
})
|
|
134
|
-
.then(() => {
|
|
135
|
-
// The page should not reload if on the report/dashboard page so not to have to reload the data and cause a delay
|
|
136
|
-
// Should instead update the UI labels to signify the change has been made
|
|
137
|
-
if (!window.location.href.includes('/report') && !window.location.href.includes('/dashboard')) {
|
|
138
|
-
window.location.reload();
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
this.updateUI();
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
.catch(error => console.error('Error:', error));
|
|
82
|
+
this.startSubmitting(this.button);
|
|
83
|
+
const data = await this.submitBookmark();
|
|
84
|
+
if (!data.success) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.updateUi(this.button, this.typeInput, data);
|
|
88
|
+
this.announceBookmarkUpdate(data.bookmarked);
|
|
145
89
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.getElement().classList.remove('bookmark-disabled');
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error('Bookmark update failed', error);
|
|
149
92
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
93
|
+
finally {
|
|
94
|
+
this.finishSubmitting(this.button);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
startSubmitting(button) {
|
|
98
|
+
this.isSubmitting = true;
|
|
99
|
+
button.classList.add('bookmark-disabled');
|
|
100
|
+
button.disabled = true;
|
|
101
|
+
button.setAttribute('aria-disabled', 'true');
|
|
102
|
+
}
|
|
103
|
+
finishSubmitting(button) {
|
|
104
|
+
this.isSubmitting = false;
|
|
105
|
+
button.classList.remove('bookmark-disabled');
|
|
106
|
+
button.disabled = false;
|
|
107
|
+
button.removeAttribute('aria-disabled');
|
|
108
|
+
}
|
|
109
|
+
async submitBookmark() {
|
|
110
|
+
const csrfToken = this.form.querySelector('input[name="_csrf"]')?.value ?? '';
|
|
111
|
+
const payload = Object.fromEntries(new FormData(this.form).entries());
|
|
112
|
+
const response = await fetch(this.form.action, {
|
|
113
|
+
method: this.form.method || 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
Accept: 'application/json',
|
|
116
|
+
'Content-Type': 'application/json',
|
|
117
|
+
'CSRF-Token': csrfToken,
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify(payload),
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
throw new Error(`Bookmark request failed (${response.status})`);
|
|
123
|
+
}
|
|
124
|
+
return response.json();
|
|
125
|
+
}
|
|
126
|
+
updateUi(button, typeInput, data) {
|
|
127
|
+
const addText = button.dataset['addText'] ?? 'Add bookmark';
|
|
128
|
+
const removeText = button.dataset['removeText'] ?? 'Remove bookmark';
|
|
129
|
+
const isBookmarked = data.type === 'remove';
|
|
130
|
+
typeInput.value = data.type;
|
|
131
|
+
button.textContent = isBookmarked ? removeText : addText;
|
|
132
|
+
button.setAttribute('aria-pressed', String(isBookmarked));
|
|
133
|
+
button.dataset['bookmarked'] = String(data.bookmarked);
|
|
134
|
+
}
|
|
135
|
+
announceBookmarkUpdate(isBookmarked) {
|
|
136
|
+
const liveRegion = document.getElementById('dpr-bookmark-announcements');
|
|
137
|
+
if (!liveRegion) {
|
|
138
|
+
return;
|
|
155
139
|
}
|
|
156
|
-
|
|
140
|
+
liveRegion.textContent = '';
|
|
141
|
+
const announcement = isBookmarked ? 'Bookmark added' : 'Bookmark removed';
|
|
142
|
+
window.setTimeout(() => {
|
|
143
|
+
liveRegion.textContent = announcement;
|
|
144
|
+
}, 10);
|
|
157
145
|
}
|
|
158
146
|
}
|
|
159
147
|
|
|
@@ -655,10 +643,12 @@ class DprSelectedAsyncFilters extends DprClientClass {
|
|
|
655
643
|
name.className = 'dpr-selected-filter__name';
|
|
656
644
|
name.textContent = filter.displayName;
|
|
657
645
|
const value = document.createTextNode(`: ${filter.displayValue}`);
|
|
658
|
-
|
|
646
|
+
const hiddenText = document.createElement('span');
|
|
647
|
+
hiddenText.className = 'govuk-visually-hidden';
|
|
648
|
+
hiddenText.textContent = ', remove filter';
|
|
649
|
+
button.append(name, value, hiddenText);
|
|
659
650
|
button.addEventListener('click', () => {
|
|
660
651
|
const params = new URLSearchParams(window.location.search);
|
|
661
|
-
// Remove ALL values for this filter from the query string
|
|
662
652
|
filter.inputs.forEach(control => {
|
|
663
653
|
params.delete(control.name);
|
|
664
654
|
if (control instanceof HTMLSelectElement) {
|
|
@@ -675,6 +665,7 @@ class DprSelectedAsyncFilters extends DprClientClass {
|
|
|
675
665
|
this.removeAutocompleteHiddenInput(control.name, params);
|
|
676
666
|
control.dispatchEvent(new Event('change', { bubbles: true }));
|
|
677
667
|
});
|
|
668
|
+
this.announceFilterRemoval(filter.displayName, filter.displayValue);
|
|
678
669
|
const query = params.toString();
|
|
679
670
|
const url = query ? `?${query}` : window.location.pathname;
|
|
680
671
|
window.history.replaceState(null, '', url);
|
|
@@ -706,6 +697,16 @@ class DprSelectedAsyncFilters extends DprClientClass {
|
|
|
706
697
|
humanise(value) {
|
|
707
698
|
return value.replace(/-/g, ' ');
|
|
708
699
|
}
|
|
700
|
+
announceFilterRemoval(filterName, filterValue) {
|
|
701
|
+
const liveRegion = document.getElementById('dpr-selected-filters-announcements');
|
|
702
|
+
if (!liveRegion) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
liveRegion.textContent = '';
|
|
706
|
+
window.setTimeout(() => {
|
|
707
|
+
liveRegion.textContent = `${filterName}: ${filterValue} removed`;
|
|
708
|
+
}, 10);
|
|
709
|
+
}
|
|
709
710
|
}
|
|
710
711
|
|
|
711
712
|
class DprFiltersFormClass extends DprClientClass {
|