Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start date and end date added to Service Message Banner #458

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
779009f
Start date and end date added to Service Message
OgunyemiO Apr 24, 2024
bc7dc7f
version number change
OgunyemiO Apr 24, 2024
1b25632
removed commented lines of code
OgunyemiO Apr 25, 2024
3599471
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
RiteshHMCTS Jun 27, 2024
a2d7304
removed translation from component
OgunyemiO Jun 28, 2024
b2e70d5
version number changed
OgunyemiO Jun 28, 2024
8371017
Merge remote-tracking branch 'refs/remotes/origin/EXUI-1079-start-end…
OgunyemiO Jun 28, 2024
c1afcd8
unit test text changed
OgunyemiO Jun 28, 2024
6ee1fc5
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
RiteshHMCTS Jul 16, 2024
0f0e3d6
version updated
RiteshHMCTS Jul 16, 2024
80497d3
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
OgunyemiO Jul 17, 2024
0cdd0fb
merge master into branch
OgunyemiO Jul 17, 2024
ea48f00
error handling message added
OgunyemiO Jul 23, 2024
9ce2c6d
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
OgunyemiO Jul 31, 2024
79a1671
banner message errors modified
OgunyemiO Aug 5, 2024
464930e
version number amended
OgunyemiO Aug 5, 2024
993923e
error reworked and unit test
OgunyemiO Aug 8, 2024
e09f957
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
OgunyemiO Aug 8, 2024
7a342a2
version change
OgunyemiO Aug 8, 2024
13c2092
AC04 AC05 AC06 and unit test covered
OgunyemiO Aug 21, 2024
3929299
version number changed
OgunyemiO Aug 21, 2024
18299a7
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
OgunyemiO Aug 21, 2024
7704dda
error bug fix
OgunyemiO Aug 28, 2024
103be99
version text change
OgunyemiO Aug 28, 2024
fa6a6f5
message error bug fixes
OgunyemiO Aug 29, 2024
d65653b
version change
OgunyemiO Aug 29, 2024
bfd87c3
reworked greater than dates
OgunyemiO Sep 3, 2024
82e8a29
unit test and version update
OgunyemiO Sep 3, 2024
800a4c1
Merge branch 'master' into EXUI-1079-start-enddate-for-service-banner…
OgunyemiO Sep 3, 2024
fed6c33
Update to release version number
Josh-HMCTS Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/rpx-xui-common-lib",
"version": "2.0.24",
"version": "2.0.24-banner-message-date-error-handling",
"engines": {
"node": ">=18.19.0"
},
Expand Down
2 changes: 1 addition & 1 deletion projects/exui-common-lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hmcts/rpx-xui-common-lib",
"version": "2.0.24",
"version": "2.0.24-banner-message-date-error-handling",
"peerDependencies": {
"launchdarkly-js-client-sdk": "^3.3.0",
"ngx-pagination": "^3.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

<div class="hmcts-banner__message">
<span class="hmcts-banner__assistive">{{'Warning' | rpxTranslate}}</span>
<h2 class="govuk-heading-s" [innerHTML]="message | rpxTranslate"></h2>
<h2 class="govuk-heading-s" [innerHTML]="message_en"></h2>
<h2 *ngIf="message_cy" class="govuk-heading-s" [innerHTML]="message_cy"></h2>
<a [routerLink]="" class="govuk-link--no-visited-state" (click)="onHideMessageEvent(key)">{{'Hide message' | rpxTranslate}}</a>
</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.govuk-link--no-visited-state {
cursor: pointer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Pipe, PipeTransform } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ServiceMessageComponent } from './service-message.component';
import { ServiceMessages } from '../../models/service-message.model';

@Pipe({ name: 'rpxTranslate' })
class RpxTranslateMockPipe implements PipeTransform {
Expand Down Expand Up @@ -35,7 +36,14 @@ describe('ServiceMessageComponent', () => {

describe('onHideMessageEvent()', () => {
it('should emit the id of the message to hide', () => {
const hideKey = 'caseworker-probate';
const hideKey: ServiceMessages = {
roles: 'caseworker-probate',
index: 1,
message_en: 'New message',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2024-04-19T00:00:00'
};
const hideMessageSpy = spyOn(component.hideMessage, 'emit');
component.onHideMessageEvent(hideKey);
expect(hideMessageSpy).toHaveBeenCalledWith(hideKey);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ServiceMessages } from '../../models/service-message.model';

@Component({
selector: 'xuilib-service-message',
templateUrl: './service-message.component.html'
templateUrl: './service-message.component.html',
styleUrls: ['./service-message.component.scss']
})
export class ServiceMessageComponent {
@Input() public message: string;
@Input() public key: string;
@Output() public hideMessage = new EventEmitter<string>();
@Input() public message_en: string;
@Input() public message_cy?: string;
@Input() public key: ServiceMessages;
@Output() public hideMessage = new EventEmitter<ServiceMessages>();
constructor() { }

public onHideMessageEvent(key: string) {
public onHideMessageEvent(key: ServiceMessages) {
this.hideMessage.emit(key);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
<div *ngIf="filteredMessages?.size > 0" class="govuk-width-container govuk-!-margin-top-6">
<xuilib-service-message *ngFor="let message of filteredMessages | keyvalue" [key]="message.key"
[message]="message.value | rpxTranslate" (hideMessage)="hideMessage($event)"></xuilib-service-message>
<div *ngIf="filteredMessages?.length > 0" class="govuk-width-container govuk-!-margin-top-6">
<div *ngIf="isBannerError" class="hmcts-banner hmcts-banner--warning">
<svg class="hmcts-banner__icon" fill="currentColor" role="presentation" focusable="false"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25" height="25" width="25">
<path d="M13.6,15.4h-2.3v-4.5h2.3V15.4z M13.6,19.8h-2.3v-2.2h2.3V19.8z M0,23.2h25L12.5,2L0,23.2z" />
</svg>
<div class="hmcts-banner__message">
<span class="hmcts-banner__assistive">{{'Warning' | rpxTranslate}}</span>
<h2 class="govuk-heading-s">Error:</h2>
<p>{{bannerErrorMsg}}</p>
</div>
</div>

<xuilib-service-message *ngFor="let message of filteredMessages" [key]="message"
[message_en]="message?.message_en | rpxTranslate"
[message_cy]="message?.message_cy | rpxTranslate"
(hideMessage)="hideMessage($event)">
</xuilib-service-message>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RpxTranslationConfig, RpxTranslationService } from 'rpx-xui-translation
import { of } from 'rxjs';
import { FeatureToggleService } from '../../services/feature-toggle/feature-toggle.service';
import { ServiceMessagesComponent } from './service-messages.component';
import { ServiceMessages } from '../../models/service-message.model';

@Pipe({ name: 'rpxTranslate' })
class RpxTranslateMockPipe implements PipeTransform {
Expand All @@ -17,14 +18,25 @@ describe('ServiceMessagesComponent', () => {
let fixture: ComponentFixture<ServiceMessagesComponent>;
const mockFeatureToggleService = jasmine.createSpyObj('FeatureToggleService', ['getValue']);

const serviceMessagesFake = {
'caseworker-divorce': 'Divorce users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-divorce|caseworker-probate': 'Divorce and probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-notfound': 'Not found users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-probate': 'Probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
'caseworker-probate|caseworker-withanotherscript': 'Probate and script users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.<scr<script>Ha!</script>ipt> alert("WOW");</script>*',
'caseworker-probate|caseworker-withscript': 'Probate and script users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.<script>alert("security alert");</script>*<link rel=\"stylesheet\" href=\"styles.css\">*'
};
const
serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Alert services notification',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2034-05-19T00:00:00'
},
{
roles: 'caseworker-probate',
index: 3,
message_en: 'Please submit all required forms today ',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2044-04-20T00:00:00'
}
];

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
Expand Down Expand Up @@ -53,19 +65,152 @@ describe('ServiceMessagesComponent', () => {
expect(component).toBeTruthy();
});

describe('getServiceMessages()', () => {
describe('call createFilteredMessages on getServiceMessages() call', () => {
it('should get the service messages and filter according to roles', () => {
const serveMsgSpy = spyOn<any>(component, 'createFilteredMessages');
component.getServiceMessages();
expect(component.filteredMessages.size).toBe(5);
expect(serveMsgSpy).toHaveBeenCalled();
});
});
describe('call compareDates on createFilteredMessages call', () => {
it('should get the service messages and filter according to roles', () => {
const dateSpy = spyOn<any>(component, 'compareDates');
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(dateSpy).toHaveBeenCalled();
});
});

it('should filter out message if start date is in the future', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Divorce and probate users may experience longer loading times than usual in the system.<br />Click <a href="#">here</a> to find out more.',
message_cy: 'Anyyu',
begin: '2034-04-18T00:00:00',
end: '2034-05-19T00:00:00'
},
{
roles: 'caseworker-probate',
index: 3,
message_en: 'Maintainance notices',
message_cy: 'Anyyu',
begin: '2024-04-18T00:00:00',
end: '2044-04-20T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should show message when no start date or end date provided', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Happy birthday.',
message_cy: 'Anyyu',
begin: '',
end: ''
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(1);
});

it('should filter out message if end date is in the past', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Services up and running',
message_cy: 'Anyyu',
begin: '2024-03-18T00:00:00',
end: '2024-03-19T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

it('should filter out message if start date is greater than end date', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Judiciary experience required',
message_cy: 'Anyyu',
begin: '2024-04-25T00:00:00',
end: '2024-04-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

it('should filter out message if date format is wrong', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Date is in WRONG format',
message_cy: 'Anyyu',
begin: '04-04-2024T19:00:00',
end: '2024-04-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
});

describe('hideMessage()', () => {
it('should add an item to the hidden message list', () => {
component.hiddenBanners = [];
const testRole = 'test-message-1';
component.hideMessage(testRole);
component.hideMessage(serviceMessagesFake[0]);
expect((component.hiddenBanners).length).toBe(1);
});
});
});

it('should show error message if start date is greater than the end date', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 2,
message_en: 'Judiciary experience required',
message_cy: 'Anyyu',
begin: '2024-04-25T00:00:00',
end: '2024-04-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
fixture.detectChanges();
expect(component.isBannerError).toBeTruthy();
expect(component.bannerErrorMsg).toContain(`The start date is greater than the end date for message index: ${serviceMessagesFake[0].index}`);
});
it('should show error message if start date or end date is not well formed', () => {
const serviceMessagesFake: ServiceMessages[] = [
{
roles: 'caseworker-divorce',
index: 10,
message_en: 'Malformed start or end date',
message_cy: 'Incorrect date',
begin: '2024-04-25 T00:00:00',
end: '2024-04-24T00:00:00'
}
];
component['createFilteredMessages'](serviceMessagesFake);
fixture.autoDetectChanges();
expect(component.filteredMessages.length).toBe(0);
fixture.detectChanges();
expect(component.isBannerError).toBeTruthy();
expect(component.bannerErrorMsg).toContain(`Invalid start or end date for message index: 10`);
});
});
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Component, Input, OnInit } from '@angular/core';
import { FeatureToggleService } from '../../services/feature-toggle/feature-toggle.service';
import { ServiceMessages } from '../../models/service-message.model';

export interface ServiceMessages {
[key: string]: string;
}

@Component({
selector: 'xuilib-service-messages',
templateUrl: './service-messages.component.html'
})
export class ServiceMessagesComponent implements OnInit {
public hiddenBanners: string[];
public filteredMessages = new Map<string, string>();
public filteredMessages: ServiceMessages[] = [];
public isBannerError: boolean;
public bannerErrorMsg: string = '';

@Input() public userRoles: string[];
@Input() public featureToggleKey: string;
Expand All @@ -24,27 +24,55 @@ export class ServiceMessagesComponent implements OnInit {
}

public getServiceMessages(): void {
this.featureToggleService.getValue<ServiceMessages>(this.featureToggleKey, null)
this.featureToggleService.getValue<ServiceMessages[]>(this.featureToggleKey, null)
.subscribe(messages => {
if (!!messages) {
this.createFilteredMessages(messages);
}
});
}

private createFilteredMessages(messages: ServiceMessages): void {
private createFilteredMessages(messages: ServiceMessages[]): void {
this.hiddenBanners = JSON.parse(window.sessionStorage.getItem(this.serviceMessageCookie)) || [];
Object.keys(messages).forEach(key => {
const regEx = new RegExp(key);
if (this.userRoles.some(e => regEx.test(e)) && this.hiddenBanners.indexOf(key) === -1) {
this.filteredMessages.set(key, messages[key]);

messages.forEach(key => {
const regEx = new RegExp(key.roles);
if (this.userRoles.some(e => regEx.test(e))) {
this.filteredMessages = messages.filter(msg => !this.hiddenBanners.includes(msg.message_en)
&& this.compareDates(msg));
}
});
}

public hideMessage(key: string): void {
this.filteredMessages.delete(key);
this.hiddenBanners.push(key);
private compareDates(msg: ServiceMessages): boolean {
let currentDateTime = new Date();
let beginDate = null;
let endDate = null;

if (!isNaN(Date.parse(msg.begin))) {
beginDate = new Date(msg.begin);
}
if (!isNaN(Date.parse(msg.end))) {
endDate = new Date(msg.end);
}
if (!isNaN(Date.parse(msg.begin)) && !isNaN(Date.parse(msg.end)) && beginDate > endDate) {
this.isBannerError = true;
this.bannerErrorMsg = `The start date is greater than the end date for message index: ${msg.index}`;
}
if (isNaN(Date.parse(msg.begin)) || isNaN(Date.parse(msg.end))) {
this.isBannerError = true;
this.bannerErrorMsg = `Invalid start or end date for message index: ${msg.index}`;
}

const beginDateOK = !msg.begin || (beginDate && beginDate < currentDateTime);
const endDateOK = !msg.end || (endDate && endDate >= currentDateTime);
return beginDateOK && endDateOK
}


public hideMessage(msg: ServiceMessages): void {
this.filteredMessages = this.filteredMessages.filter(f => f.index !== msg.index)
this.hiddenBanners.push(msg.message_en);
window.sessionStorage.setItem(this.serviceMessageCookie, JSON.stringify(this.hiddenBanners));
}
}
Loading
Loading