From ecb45b5cc6d6a721622b8036e5a13febe4a0d2f4 Mon Sep 17 00:00:00 2001 From: StoeBenHMCTS Date: Tue, 4 Mar 2025 16:46:12 +0000 Subject: [PATCH 01/21] adds aria label for current page --- .../components/case-editor/case-edit/case-edit.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts index 38e01bea12..942e42bd72 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts @@ -579,7 +579,7 @@ export class CaseEditComponent implements OnInit, OnDestroy { this.caseSubmit({ form, caseEventData, submit }); } else { // Navigate to tasks tab on case details page - this.router.navigate([`/cases/case-details/${this.getCaseId(caseDetails)}/tasks`], { relativeTo: this.route }); + this.router.navigate([`/cases/case-details/${this.caseDetails.case_type.jurisdiction.id}/${this.caseDetails.case_type.id}/${this.getCaseId(caseDetails)}/tasks`], { relativeTo: this.route }); } } From 70db69f62aa5e6e3d946d54973237d74610ef064 Mon Sep 17 00:00:00 2001 From: StoeBenHMCTS Date: Thu, 27 Feb 2025 12:16:34 +0000 Subject: [PATCH 02/21] updates the case-list labels for checkboxes --- .../case-event-completion-task-cancelled.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.ts index de31081a8f..7a0fca6a68 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.ts @@ -13,9 +13,13 @@ export class CaseEventCompletionTaskCancelledComponent implements OnInit { public notifyEventCompletionCancelled: EventEmitter = new EventEmitter(); public caseId: string; + public jurisdiction: string; + public caseType: string; public ngOnInit(): void { this.caseId = this.context.caseId; + this.jurisdiction = this.context.task.jurisdiction; + this.caseType = this.context.task.case_type_id; } public onContinue(): void { From 94e83f28ef2cb71553facb9a847ba67b579eaced Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Wed, 9 Apr 2025 11:59:52 +0100 Subject: [PATCH 03/21] url changes --- .../case-event-completion-task-cancelled.html | 2 +- ...nt-completion-task-reassigned.component.ts | 4 ++++ ...case-event-completion-task-reassigned.html | 2 +- ...e-challenged-access-success.component.html | 2 +- ...ase-challenged-access-success.component.ts | 4 ++++ .../case-full-access-view.component.ts | 12 ++++++------ ...view-specific-access-reject.component.html | 2 +- ...review-specific-access-reject.component.ts | 4 ++++ .../services/event-trigger.resolver.ts | 3 +++ .../multiple-tasks-exist.component.html | 2 +- .../multiple-tasks-exist.component.ts | 4 ++++ .../no-tasks-available.component.html | 2 +- .../no-tasks-available.component.ts | 4 ++++ .../task-assigned.component.html | 2 +- .../task-assigned/task-assigned.component.ts | 4 ++++ .../task-unassigned.component.html | 2 +- .../task-unassigned.component.ts | 4 ++++ .../event-guard/event-start.guard.ts | 4 ++-- .../event-start-state-machine.service.ts | 19 +++++++++++++------ .../before-you-start.component.ts | 2 +- .../linked-cases-from-table.component.html | 4 ++-- .../linked-cases-to-table.component.html | 4 ++-- .../no-linked-cases.component.ts | 2 +- .../read-linked-cases-field.component.ts | 2 +- 24 files changed, 67 insertions(+), 29 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.html index c572cbb86b..77e0d9f07a 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.html @@ -23,7 +23,7 @@

{{'Task cancelled/marked as done' | rpxTranslate}} {{'Continue' | rpxTranslate}} - {{'Cancel' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts index ad267025f8..73f463ddd5 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts @@ -25,6 +25,8 @@ export class CaseEventCompletionTaskReassignedComponent implements OnInit, OnDes public subscription: Subscription; public caseworkerSubscription: Subscription; public judicialworkerSubscription: Subscription; + public jurisdiction: string; + public caseType: string; constructor(private readonly sessionStorageService: SessionStorageService, private readonly judicialworkerService: JudicialworkerService, @@ -35,6 +37,8 @@ export class CaseEventCompletionTaskReassignedComponent implements OnInit, OnDes // Get case id and task from the parent component this.caseId = this.context.caseId; const task = this.context.reassignedTask; + this.jurisdiction = this.context.task.jurisdiction; + this.caseType = this.context.task.case_type_id; // Current user is a caseworker? this.caseworkerSubscription = this.caseworkerService.getCaseworkers(task.jurisdiction).subscribe(result => { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.html index a24e05bc53..c3ea8ca78f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.html @@ -22,7 +22,7 @@

{{'Task reassigned' | rpxTranslate}}

- {{'Cancel' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.html index b6f52d7375..fc9b9bf17c 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.html @@ -20,7 +20,7 @@

{{'What happens next' | rpxTranslate}}

{{"Your request will be logged for auditing purposes." | rpxTranslate}}

-

{{"View case file" | rpxTranslate}}.

+

{{"View case file" | rpxTranslate}}.

diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.ts index be12a414de..cba8d666e8 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.ts @@ -7,10 +7,14 @@ import { ActivatedRoute } from '@angular/router'; }) export class CaseChallengedAccessSuccessComponent implements OnInit { public caseId: string; + public jurisdiction: string; + public caseType: string; constructor(private readonly route: ActivatedRoute) { } public ngOnInit(): void { this.caseId = this.route.snapshot.params.cid; + this.jurisdiction = this.route.snapshot.params.jurisdiction; + this.caseType = this.route.snapshot.params.caseType; } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts index 385128fed2..4806233a89 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts @@ -296,7 +296,7 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges } // found tasks or hearing tab if (foundTab) { - this.router.navigate(['cases', 'case-details', this.caseDetails.case_id, foundTab.id]).then(() => { + this.router.navigate(['cases', 'case-details', this.caseDetails.case_type.jurisdiction.id, this.caseDetails.case_type.id, this.caseDetails.case_id, foundTab.id]).then(() => { matTab = this.tabGroup._tabs.find((x) => x.textLabel === foundTab.label); // Update selectedIndex only if matTab.position is a non-zero number (positive or negative); this means the // matTab is not already selected (position is relative; positive = right, negative = left) or it would be 0 @@ -310,7 +310,7 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges this.caseDetails.tabs.sort((aTab, bTab) => aTab.order > bTab.order ? 1 : (bTab.order > aTab.order ? -1 : 0)); // select the first tab checking if the tab is visible const preSelectTab: CaseTab = this.findPreSelectedActiveTab(); - this.router.navigate(['cases', 'case-details', this.caseDetails.case_id], { fragment: preSelectTab.label }).then(() => { + this.router.navigate(['cases', 'case-details', this.caseDetails.case_type.jurisdiction.id, this.caseDetails.case_type.id, this.caseDetails.case_id], { fragment: preSelectTab.label }).then(() => { matTab = this.tabGroup._tabs.find((x) => x.textLabel === preSelectTab.label); // Update selectedIndex only if matTab.position is a non-zero number (positive or negative); this means the // matTab is not already selected (position is relative; positive = right, negative = left) or it would be 0 @@ -358,13 +358,13 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges // Hack to get ID from tab as it's not easily achieved through Angular Material Tabs const tab = matTab['_viewContainerRef'] as ViewContainerRef; const id = (tab.element.nativeElement as HTMLElement).id; - // cases/case-details/:caseId/hearings - // cases/case-details/:caseId/roles-and-access + // cases/case-details/:jurisdiction/:caseType/:caseId/hearings + // cases/case-details/:jurisdiction/:caseType/:caseId/roles-and-access this.router.navigate([id], { relativeTo: this.route }); } else { // Routing here is based on tab label, not ideal - // cases/case-details/:caseId#tabLabel - this.router.navigate(['cases', 'case-details', this.caseDetails.case_id], { fragment: tabLabel }); + // cases/case-details/:jurisdiction/:caseType/:caseId#tabLabel + this.router.navigate(['cases', 'case-details', this.caseDetails.case_type.jurisdiction.id, this.caseDetails.case_type.id, this.caseDetails.case_id], { fragment: tabLabel }); } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.html index 02e22760b1..6118756df0 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.html @@ -18,5 +18,5 @@

{{'What happens next' | rpxTranslate}}

{{returnToMyTask | rpxTranslate}}

-

{{retunToTask | rpxTranslate}}

+

{{retunToTask | rpxTranslate}}

diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.ts index 27afb2dcd0..4fd6f18717 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.ts @@ -8,6 +8,8 @@ import { ActivatedRoute } from '@angular/router'; export class CaseReviewSpecificAccessRejectComponent implements OnInit { public caseId: string; + public jurisdiction: string; + public caseType: string; public readonly retunToTask = 'Return to the Tasks tab for this case'; public readonly returnToMyTask = 'Return to My tasks'; @@ -15,5 +17,7 @@ export class CaseReviewSpecificAccessRejectComponent implements OnInit { public ngOnInit(): void { this.caseId = this.route.snapshot.data.case.case_id; + this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; + this.caseType = this.route.snapshot.data.case.case_type.id; } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts index ae9b4268ba..9d633c603f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts @@ -50,6 +50,7 @@ export class EventTriggerResolver implements Resolve { const cid = route.parent.paramMap.get(EventTriggerResolver.PARAM_CASE_ID); // tslint:disable-next-line: prefer-const let caseTypeId: string; + const jurisdiction = route.parent.paramMap.get('jurisdiction'); const eventTriggerId = route.paramMap.get(EventTriggerResolver.PARAM_EVENT_ID); let ignoreWarning = route.queryParamMap.get(EventTriggerResolver.IGNORE_WARNING); if (-1 === EventTriggerResolver.IGNORE_WARNING_VALUES.indexOf(ignoreWarning)) { @@ -74,6 +75,8 @@ export class EventTriggerResolver implements Resolve { this.alertService.setPreserveAlerts(true); this.alertService.error(error.message); this.errorNotifier.announceError(error); + caseTypeId = route.parent.paramMap.get('caseType'); + this.router.navigate([`/cases/case-details/${jurisdiction}/${caseTypeId}/${cid}/tasks`]); this.router.navigate([`/cases/case-details/${cid}/tasks`]); return throwError(error); }) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.html index 1686bf9ecc..e9b4eab7c6 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.html @@ -18,6 +18,6 @@

{{"You're starting work which could complete more than one of the active tasks for this case." | rpxTranslate}}

{{'Return to tasks tab and start the event from there.' | rpxTranslate}}

- {{'Return to tasks tab' | rpxTranslate}} + {{'Return to tasks tab' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.ts index 3556a27387..430cb3bbb5 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.ts @@ -8,8 +8,12 @@ import { ActivatedRoute } from '@angular/router'; export class MultipleTasksExistComponent { public caseId: string; + public jurisdiction: string; + public caseType: string; constructor(private readonly route: ActivatedRoute) { this.caseId = this.route.snapshot.data.case.case_id; + this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; + this.caseType = this.route.snapshot.data.case.case_type.id; } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.html index f78a996def..4f830cbb60 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.html @@ -15,6 +15,6 @@

{{'No task available' | rpxTranslate}}

{{'You should have an assigned task for this event, but something has gone wrong.' | rpxTranslate}}

- {{'Return to tasks tab' | rpxTranslate}} + {{'Return to tasks tab' | rpxTranslate}}
diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.ts index fe2b79ab27..7f9eb7cbf3 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.ts @@ -8,8 +8,12 @@ import { ActivatedRoute, NavigationExtras, Router } from '@angular/router'; export class NoTasksAvailableComponent { public caseId: string; + public jurisdiction: string; + public caseType: string; constructor(private readonly route: ActivatedRoute) { this.caseId = this.route.snapshot.data.case.case_id; + this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; + this.caseType = this.route.snapshot.data.case.case_type.id; } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html index c8c591385d..028006dda1 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html @@ -17,7 +17,7 @@

{{'Task assignment required' | rpxTranslate}}

{{'This task is assigned to' | rpxTranslate}} {{assignedUserName}}. {{'You must assign it to yourself to continue.' | rpxTranslate}}

- + {{'Return to tasks tab' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts index 92b5a6710f..079f7f6275 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts @@ -13,6 +13,8 @@ export class TaskAssignedComponent implements OnInit, OnDestroy { public task: Task = null; public caseId: string; + public jurisdiction: string; + public caseType: string; public assignedUserName: string; public caseworkerSubscription: Subscription; public judicialworkerSubscription: Subscription; @@ -21,6 +23,8 @@ export class TaskAssignedComponent implements OnInit, OnDestroy { private readonly judicialworkerService: JudicialworkerService, private readonly caseworkerService: CaseworkerService) { this.caseId = this.route.snapshot.data.case.case_id; + this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; + this.caseType = this.route.snapshot.data.case.case_type.id; this.task = this.route.snapshot.queryParams as Task; } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.html index 5f5c8935cf..76e10310ca 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.html @@ -18,7 +18,7 @@

{{'Task assignment required' | rpxTranslate}}

{{'You must assign one of the available tasks from the task tab to continue with your work.' | rpxTranslate}}

- + {{'Return to tasks tab to assign a task' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.ts index 254aa793a9..dbd16f80da 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.ts @@ -8,8 +8,12 @@ import { ActivatedRoute } from '@angular/router'; export class TaskUnassignedComponent { public caseId: string; + public jurisdiction: string; + public caseType: string; constructor(private readonly route: ActivatedRoute) { this.caseId = this.route.snapshot.data.case.case_id; + this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; + this.caseType = this.route.snapshot.data.case.case_type.id; } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts index 0b059149b6..c156718269 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts @@ -95,7 +95,7 @@ export class EventStartGuard implements CanActivate { return true; } else if (tasksAssignedToUser.length > 1 && !taskId) { // if more than one task assigned to the user then give multiple tasks error - this.router.navigate([`/cases/case-details/${caseId}/multiple-tasks-exist`]); + this.router.navigate([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/${caseId}/multiple-tasks-exist`]); return false; } else { let task: any; @@ -126,7 +126,7 @@ export class EventStartGuard implements CanActivate { if (this.router && this.router.url && this.router.url.includes('event-start')) { return of(true); } - this.router.navigate([`/cases/case-details/${caseId}/event-start`], { queryParams: { caseId, eventId, taskId } }); + this.router.navigate([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/${caseId}/event-start`], { queryParams: { caseId, eventId, taskId } }); return of(false); } else { return of(this.checkTaskInEventNotRequired(payload, caseId, taskId, eventId, userId)); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts index 10e7474326..6208e95762 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts @@ -108,11 +108,17 @@ export class EventStartStateMachineService { } } + private getJurisdictionNCaseType(context: EventStartStateMachineContext): any { + const caseInfo = context.sessionStorageService.getItem('caseInfo'); + return caseInfo ? JSON.parse(caseInfo) : null; + } + public entryActionForStateNoTask(state: State, context: EventStartStateMachineContext): void { // Trigger final state to complete processing of state machine state.trigger(EventStartStates.FINAL); // Navigate to no tasks available error page - context.router.navigate([`/cases/case-details/${context.caseId}/no-tasks-available`], { relativeTo: context.route }); + const caseDetails = this.getJurisdictionNCaseType(context); + context.router.navigate([`/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/no-tasks-available`], { relativeTo: context.route }); } public entryActionForStateOneOrMoreTasks(state: State, context: EventStartStateMachineContext): void { @@ -159,14 +165,14 @@ export class EventStartStateMachineService { public entryActionForStateTaskUnAssigned(state: State, context: EventStartStateMachineContext): void { let navigationURL = ''; let theQueryParams: Params = {}; - + const caseDetails = this.getJurisdictionNCaseType(context); if (context.tasks[0].assignee) { // Task is assigned to some other user, navigate to task assigned error page - navigationURL = `/cases/case-details/${context.caseId}/task-assigned`; + navigationURL = `/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/task-assigned`; theQueryParams = context.tasks[0]; } else { // Task is unassigned, navigate to task unassigned error page - navigationURL = `/cases/case-details/${context.caseId}/task-unassigned`; + navigationURL = `/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/task-unassigned`; } // Trigger final state to complete processing of state machine @@ -216,15 +222,16 @@ export class EventStartStateMachineService { // EXUI-2668 - Only add client context when taskEventCompletionInfo is set - stops auto completing incorrect tasks context.sessionStorageService.setItem(CaseEditComponent.CLIENT_CONTEXT, JSON.stringify(clientContext)); // Allow user to perform the event - context.router.navigate([`/cases/case-details/${context.caseId}/trigger/${context.eventId}`], + context.router.navigate([`/cases/case-details/${task.jurisdiction}/${task.case_type_id}/${context.caseId}/trigger/${context.eventId}`], { relativeTo: context.route }); } public entryActionForStateMultipleTasksAssignedToUser(state: State, context: EventStartStateMachineContext): void { // Trigger final state to complete processing of state machine state.trigger(EventStartStates.FINAL); + const caseDetails = this.getJurisdictionNCaseType(context); // Navigate to multiple tasks exist error page - context.router.navigate([`/cases/case-details/${context.caseId}/multiple-tasks-exist`], { relativeTo: context.route }); + context.router.navigate([`/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/multiple-tasks-exist`], { relativeTo: context.route }); } public finalAction(state: State): void { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.ts index 8c97536c47..15091ac16a 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.ts @@ -63,6 +63,6 @@ export class BeforeYouStartComponent extends AbstractJourneyComponent implements } public onBack(): void { - this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseId], { fragment: 'Linked cases' }); + this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseJurisdictionID, this.linkedCasesService.caseDetails.case_type, this.linkedCasesService.caseId], { fragment: 'Linked cases' }); } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-from-table.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-from-table.component.html index 9f7ff732e4..22877bc132 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-from-table.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-from-table.component.html @@ -14,7 +14,7 @@ -

{{case.caseNameHmctsInternal}}
{{case.caseReference | ccdCaseReference}}

@@ -24,7 +24,7 @@ {{reason | ccdLinkCasesFromReasonValue}}{{getCaseReferenceLink(case.caseReference)}}
diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-to-table.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-to-table.component.html index cd242787bc..f71538e7e3 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-to-table.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/linked-cases-table/linked-cases-to-table.component.html @@ -13,7 +13,7 @@ -

{{case.caseName}}
{{case.caseReference | ccdCaseReference}}

@@ -24,7 +24,7 @@ {{reason.value | ccdLinkCasesReasonValue}}{{getCaseRefereneLink(case.caseReference)}}
diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.ts index dceea7eb0a..21f2d3c7b1 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.ts @@ -24,6 +24,6 @@ export class NoLinkedCasesComponent extends AbstractJourneyComponent implements } public onBack(): void { - this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseId], { fragment: 'Linked cases' }); + this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseJurisdictionID, this.linkedCasesService.caseDetails.case_type, this.linkedCasesService.caseId], { fragment: 'Linked cases' }); } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts index 5ecc02d294..b35d7cee6e 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts @@ -72,7 +72,7 @@ export class ReadLinkedCasesFieldComponent implements OnInit, AfterViewInit { } public reloadCurrentRoute(): void { - this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseDetails.case_id], { fragment: 'Linked cases' }); + this.router.navigate(['cases', 'case-details', this.linkedCasesService.caseJurisdictionID, this.linkedCasesService.caseDetails.case_type, this.linkedCasesService.caseDetails.case_id], { fragment: 'Linked cases' }); } public getFailureLinkedToNotification(evt): void { From 3bcba4c945e096c8818d8de0159905ae4f3ef5f1 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Mon, 14 Apr 2025 12:16:30 +0100 Subject: [PATCH 04/21] url change --- .../case-viewer/services/event-trigger.resolver.ts | 1 - .../components/task-assigned/task-assigned.component.html | 2 +- .../qualifying-question-options.component.ts | 6 +++++- .../query-confirmation/query-confirmation.component.html | 6 +++--- .../query-confirmation/query-confirmation.component.ts | 4 ++++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts index 9d633c603f..ab9472dc3f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts @@ -77,7 +77,6 @@ export class EventTriggerResolver implements Resolve { this.errorNotifier.announceError(error); caseTypeId = route.parent.paramMap.get('caseType'); this.router.navigate([`/cases/case-details/${jurisdiction}/${caseTypeId}/${cid}/tasks`]); - this.router.navigate([`/cases/case-details/${cid}/tasks`]); return throwError(error); }) ).toPromise(); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html index 028006dda1..ca862ce433 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.html @@ -17,7 +17,7 @@

{{'Task assignment required' | rpxTranslate}}

{{'This task is assigned to' | rpxTranslate}} {{assignedUserName}}. {{'You must assign it to yourself to continue.' | rpxTranslate}}

- + {{'Return to tasks tab' | rpxTranslate}} diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.ts index 765a6115be..30abb970ba 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.ts @@ -15,6 +15,8 @@ export class QualifyingQuestionOptionsComponent implements OnInit { @Input() public qualifyingQuestions$: Observable; public qualifyingQuestionsErrorMessage = QualifyingQuestionsErrorMessage; public caseId: string; + public jurisdiction: string; + public caseType: string; constructor( private readonly route: ActivatedRoute, @@ -24,6 +26,8 @@ export class QualifyingQuestionOptionsComponent implements OnInit { public ngOnInit(): void { this.caseId = this.route.snapshot.params.cid; + this.jurisdiction = this.route.snapshot.params.jurisdiction; + this.caseType = this.route.snapshot.params.caseType; // Check if there's already a selected qualifying question from the service const savedSelection = this.qualifyingQuestionService.getQualifyingQuestionSelection(); @@ -33,7 +37,7 @@ export class QualifyingQuestionOptionsComponent implements OnInit { } public click(): void { - this.router.navigate(['cases', 'case-details', this.caseId], { fragment: 'Queries' }); + this.router.navigate(['cases', 'case-details', this.jurisdiction, this.caseType, this.caseId], { fragment: 'Queries' }); } public get displayError(): boolean { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.html b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.html index 37e45d3eee..8d561458ea 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.html +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.html @@ -12,7 +12,7 @@

{{'What happens next' | rpxTranslate}}

{{'When the response is available it will be added to the \'Queries\' section.' | rpxTranslate}}

{{'You can' | rpxTranslate}} - {{'Go back to the case' | rpxTranslate}} + {{'Go back to the case' | rpxTranslate}}

@@ -23,8 +23,8 @@

{{'Query response submitted' | rpxTranslate}}

diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.ts index d17a1a2386..57dbe969ce 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/query-confirmation/query-confirmation.component.ts @@ -10,6 +10,8 @@ export class QueryConfirmationComponent implements OnInit { @Input() public queryCreateContext: QueryCreateContext; public caseId = ''; + public jurisdiction = ''; + public caseType = ''; public queryCreateContextEnum = QueryCreateContext; constructor(private readonly route: ActivatedRoute) { @@ -17,5 +19,7 @@ export class QueryConfirmationComponent implements OnInit { public ngOnInit(): void { this.caseId = this.route.snapshot.params.cid; + this.jurisdiction = this.route.snapshot.params.jurisdiction; + this.caseType = this.route.snapshot.params.caseType; } } From 04aa6252322b43688499f71d2d9817ade362cd58 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 3 Jun 2025 15:41:02 +0100 Subject: [PATCH 05/21] fixed unit tests --- .../case-edit/case-edit.component.spec.ts | 25 ++++ ...ompletion-task-cancelled.component.spec.ts | 30 ++++- ...mpletion-task-reassigned.component.spec.ts | 2 +- ...nt-completion-task-reassigned.component.ts | 4 +- ...hallenged-access-success.component.spec.ts | 8 +- .../case-event-trigger.component.spec.ts | 6 +- .../case-full-access-view.component.spec.ts | 126 +++++++++++++----- ...w-specific-access-reject.component.spec.ts | 13 +- .../multiple-tasks-exist.component.spec.ts | 8 +- .../no-tasks-available.component.spec.ts | 8 +- .../task-assigned.component.spec.ts | 2 +- .../task-assigned/task-assigned.component.ts | 4 +- .../task-unassigned.component.spec.ts | 8 +- .../event-guard/event-start.guard.spec.ts | 12 +- .../event-start/event-start.component.spec.ts | 2 +- .../event-start-state-machine.service.spec.ts | 11 +- .../event-start-state-machine.service.ts | 16 +-- .../before-you-start.component.spec.ts | 4 +- .../no-linked-cases.component.spec.ts | 4 +- ...lifying-question-options.component.spec.ts | 8 +- 20 files changed, 223 insertions(+), 78 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.spec.ts index 0d09f97890..0738945a91 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.spec.ts @@ -1477,6 +1477,31 @@ describe('CaseEditComponent', () => { component.isCaseFlagSubmission = true; component.isLinkedCasesSubmission = true; component.confirmation = {} as unknown as Confirmation; + component.caseDetails = { + case_type: { + id: 'case_view_1_type_id', + name: 'case view 1 type', + jurisdiction: { + id: 'case_view_1_jurisdiction_id', + name: 'case view 1 jurisdiction', + }, + }, + state: { + id: 'case_view_1_state_id', + name: 'case view 1 state', + }, + channels: [], + tabs: [], + triggers: [], + events: [], + metadataFields: [], + basicFields: { + caseNameHmctsInternal: 'Dummy vs Dummy', + caseManagementLocation: { + baseLocation: 22 + } + } + }; formValueService.sanitise.and.returnValue({ name: 'sweet' }); component.onEventCanBeCompleted({ diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.spec.ts index 4d22301080..236a930444 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-cancelled/case-event-completion-task-cancelled.component.spec.ts @@ -5,6 +5,7 @@ import { MockRpxTranslatePipe } from '../../../../../test/mock-rpx-translate.pip import { CaseEditComponent } from '../../../case-edit'; import { EventCompletionStateMachineContext } from '../../../domain'; import { CaseEventCompletionTaskCancelledComponent } from './case-event-completion-task-cancelled.component'; +import { Task } from '../../../../../domain/work-allocation/Task'; @Component({ template: '' @@ -18,6 +19,33 @@ describe('TaskCancelledComponent', () => { let component: CaseEventCompletionTaskCancelledComponent; let wrapper: WrapperComponent; let fixture: ComponentFixture; + const taskDetails: Task = { + assignee: '1234-1234-1234-1234', + auto_assigned: false, + case_category: 'asylum', + case_id: '1620409659381330', + case_management_category: null, + case_name: 'Alan Jonson', + case_type_id: 'Appeal-864', + created_date: '2021-04-19T14:00:00.000+0000', + due_date: '2021-05-20T16:00:00.000+0000', + execution_type: null, + id: '0d22d838-b25a-11eb-a18c-f2d58a9b7bc6', + jurisdiction: 'Immigration and Asylum', + location: null, + location_name: null, + name: 'Task name', + permissions: null, + region: null, + security_classification: null, + task_state: null, + task_system: null, + task_title: 'Some lovely task name', + type: null, + warning_list: null, + warnings: true, + work_type_id: null + }; beforeEach(async () => { TestBed.configureTestingModule({ @@ -34,7 +62,7 @@ describe('TaskCancelledComponent', () => { wrapper = fixture.componentInstance; component = fixture.componentInstance.appComponentRef; const sessionStorageSpy = jasmine.createSpyObj('mockSessionStorageService', ['removeItem']); - wrapper.context = {caseId: '123456789', sessionStorageService: sessionStorageSpy} as EventCompletionStateMachineContext; + wrapper.context = {caseId: '123456789', task: taskDetails, sessionStorageService: sessionStorageSpy} as EventCompletionStateMachineContext; fixture.detectChanges(); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.spec.ts index f56b33c918..6f2118e7c0 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.spec.ts @@ -46,7 +46,7 @@ describe('TaskReassignedComponent', () => { case_id: '1620409659381330', case_management_category: null, case_name: 'Alan Jonson', - case_type_id: null, + case_type_id: 'Appeal-864', created_date: '2021-04-19T14:00:00.000+0000', due_date: '2021-05-20T16:00:00.000+0000', execution_type: null, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts index 73f463ddd5..ed65591aab 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-event-completion/components/case-event-completion-task-reassigned/case-event-completion-task-reassigned.component.ts @@ -37,8 +37,8 @@ export class CaseEventCompletionTaskReassignedComponent implements OnInit, OnDes // Get case id and task from the parent component this.caseId = this.context.caseId; const task = this.context.reassignedTask; - this.jurisdiction = this.context.task.jurisdiction; - this.caseType = this.context.task.case_type_id; + this.jurisdiction = task.jurisdiction; + this.caseType = task.case_type_id; // Current user is a caseworker? this.caseworkerSubscription = this.caseworkerService.getCaseworkers(task.jurisdiction).subscribe(result => { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.spec.ts index a03089d18e..4a78c1072f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-challenged-access-success/case-challenged-access-success.component.spec.ts @@ -8,10 +8,14 @@ describe('CaseChallengedAccessSuccessComponent', () => { let component: CaseChallengedAccessSuccessComponent; let fixture: ComponentFixture; const caseId = '1234123412341234'; + const jurisdictionId = 'TestJurisdiction'; + const caseTypeId = 'TestCaseType'; const mockRoute = { snapshot: { params: { - cid: caseId + cid: caseId, + jurisdiction: jurisdictionId, + caseType: caseTypeId } } }; @@ -41,6 +45,6 @@ describe('CaseChallengedAccessSuccessComponent', () => { it('should have the correct Case Reference in the \"View case file\" link URL', () => { const viewCaseFileLinkElement = fixture.debugElement.nativeElement.querySelector('p.govuk-body a'); - expect(viewCaseFileLinkElement.getAttribute('href')).toContain(`/cases/case-details/${caseId}`); + expect(viewCaseFileLinkElement.getAttribute('href')).toContain(`/cases/case-details/${jurisdictionId}/${caseTypeId}/${caseId}`); }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts index 2fa7c8bbde..ab41d8ef02 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts @@ -136,7 +136,7 @@ describe('CaseEventTriggerComponent', () => { let sessionStorageService: any; let casesReferencePipe: any; let activityPollingService: any; - const finalUrl = '/cases/case-details/1707912713167104#Claim%20details'; + const finalUrl = '/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104#Claim%20details'; beforeEach(waitForAsync(() => { caseNotifier = createSpyObj('caseService', ['announceCase']); @@ -254,7 +254,7 @@ describe('CaseEventTriggerComponent', () => { it('should verify cancel navigate to the correct url', () => { component.cancel(); - expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/1707912713167104'], { fragment: 'Claim details' }); + expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104'], { fragment: 'Claim details' }); }); it('should bypass validation if the eventTrigger case fields contain a FlagLauncher field', (done) => { @@ -371,7 +371,7 @@ describe('CaseEventTriggerComponent', () => { routerWithModifiedUrl.url = 'linkCases'; component.caseDetails.case_id = '1111-2222-3333-4444'; component.cancel(); - expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/1707912713167104'], { fragment: 'Claim details' }); + expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104'], { fragment: 'Claim details' }); }); it('should call unregisterStoredSpinner if there is a stored spinnter', () => { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts index 3bc3fc2848..74ce54b879 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts @@ -1272,11 +1272,21 @@ describe('CaseFullAccessViewComponent - prependedTabs', () => { path: 'case-details', children: [ { - path: ':id', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } @@ -1309,7 +1319,7 @@ describe('CaseFullAccessViewComponent - prependedTabs', () => { { provide: Location, useClass: class MockLocation { - public path = (_: string) => 'cases/case-details/1234567890123456/tasks'; + public path = (_: string) => 'cases/case-details/TEST/TestAddressBookCase/1234567890123456/tasks'; } }, ErrorNotifierService, @@ -1390,7 +1400,7 @@ describe('CaseFullAccessViewComponent - appendedTabs', () => { convertHrefToRouterService.getHrefMarkdownLinkContent.and.returnValue(of('[Send a new direction](/case/IA/Asylum/1641014744613435/trigger/sendDirection)')); mockLocation = createSpyObj('location', ['path', 'go', 'isCurrentPathEqualTo']); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330#caseNotes'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1234567890123456'); TestBed .configureTestingModule({ @@ -1409,11 +1419,21 @@ describe('CaseFullAccessViewComponent - appendedTabs', () => { path: 'case-details', children: [ { - path: ':id', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } @@ -1623,16 +1643,26 @@ describe('CaseFullAccessViewComponent - ends with caseID', () => { path: 'case-details', children: [ { - path: ':id', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } ] - }, + } ] } ]), @@ -1663,7 +1693,7 @@ describe('CaseFullAccessViewComponent - ends with caseID', () => { { provide: Location, useClass: class MockLocation { - public path = (_: string) => 'cases/case-details/1234567890123456'; + public path = (_: string) => 'cases/case-details/TEST/TestAddressBookCase/1234567890123456'; } }, ErrorNotifierService, @@ -1752,7 +1782,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { navigationNotifierService = new NavigationNotifierService(); spyOn(navigationNotifierService, 'announceNavigation').and.callThrough(); mockLocation = createSpyObj('location', ['path']); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330#caseNotes'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330#caseNotes'); TestBed .configureTestingModule({ imports: [ @@ -1770,11 +1800,21 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { path: 'case-details', children: [ { - path: ':id#overview', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id#overview', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } @@ -1898,7 +1938,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { }); it('should return blank array when prepended tabs are null', () => { - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330'); componentFixture.detectChanges(); caseViewerComponent.prependedTabs = null; caseViewerComponent.organiseTabPosition(); @@ -1912,7 +1952,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { }); it('should navigate to roles and access tab', () => { - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/roles-and-access'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/roles-and-access'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); componentFixture.detectChanges(); expect(caseViewerComponent.tabGroup.selectedIndex).toEqual(1); @@ -1922,7 +1962,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { spyOn(caseViewerComponent, 'organiseTabPosition').and.callThrough(); spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/caseNotes'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/caseNotes'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -1946,7 +1986,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); // Using /caseNotes at the end of the URL ensures there won't be a matching tab found, so the selected tab should // default to the first *in the CaseView object*, which is the "Overview" tab - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/caseNotes'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/caseNotes'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -1960,7 +2000,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { spyOn(caseViewerComponent, 'organiseTabPosition').and.callThrough(); spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/roles-and-access'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/roles-and-access'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -1982,7 +2022,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { spyOn(caseViewerComponent, 'organiseTabPosition').and.callThrough(); spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/dummy'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/dummy'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -1996,7 +2036,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { spyOn(caseViewerComponent, 'organiseTabPosition').and.callThrough(); spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/dummy'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/dummy'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -2017,7 +2057,7 @@ describe('CaseFullAccessViewComponent - Overview with prepended Tabs', () => { spyOn(caseViewerComponent, 'organiseTabPosition').and.callThrough(); spyOn(router, 'navigate').and.returnValue(Promise.resolve(true)); const selectedIndexSetSpy = spyOnProperty(caseViewerComponent.tabGroup, 'selectedIndex', 'set').and.callThrough(); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330/tasks'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330/tasks'); caseViewerComponent.ngOnChanges({ prependedTabs: new SimpleChange(null, prependedTabsList, false) }); tick(); componentFixture.detectChanges(); @@ -2041,7 +2081,7 @@ describe('CaseFullAccessViewComponent - get default hrefMarkdownLinkContent', () convertHrefToRouterService = jasmine.createSpyObj('ConvertHrefToRouterService', ['getHrefMarkdownLinkContent', 'callAngularRouter']); convertHrefToRouterService.getHrefMarkdownLinkContent.and.returnValue(of('Default')); mockLocation = createSpyObj('location', ['path']); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330#caseNotes'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330#caseNotes'); subscribeSpy = spyOn(subscriptionMock, 'unsubscribe'); alertService = createSpyObj('alertService', ['setPreserveAlerts', 'success', 'warning', 'clear']); @@ -2065,11 +2105,21 @@ describe('CaseFullAccessViewComponent - get default hrefMarkdownLinkContent', () path: 'case-details', children: [ { - path: ':id#overview', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id#overview', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } @@ -2218,7 +2268,7 @@ describe('CaseFullAccessViewComponent - findPreSelectedActiveTab', () => { beforeEach(async () => { mockLocation = createSpyObj('location', ['path']); - mockLocation.path.and.returnValue('/cases/case-details/1620409659381330'); + mockLocation.path.and.returnValue('/cases/case-details/TEST/TestAddressBookCase/1620409659381330'); convertHrefToRouterService = jasmine.createSpyObj('ConvertHrefToRouterService', ['getHrefMarkdownLinkContent', 'callAngularRouter']); convertHrefToRouterService.getHrefMarkdownLinkContent.and.returnValue(of('Default')); @@ -2237,11 +2287,21 @@ describe('CaseFullAccessViewComponent - findPreSelectedActiveTab', () => { path: 'case-details', children: [ { - path: ':id#overview', + path: ':jurisdiction', children: [ { - path: 'tasks', - component: TasksContainerComponent + path: ':caseType', + children: [ + { + path: ':id#overview', + children: [ + { + path: 'tasks', + component: TasksContainerComponent + } + ] + } + ] } ] } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.spec.ts index 4ace550844..054aebdbda 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-review-specific-access-reject/case-review-specific-access-reject.component.spec.ts @@ -9,11 +9,20 @@ describe('CaseReviewSpecificAccessRejectComponent', () => { let component: CaseReviewSpecificAccessRejectComponent; let fixture: ComponentFixture; const caseId = '1234123412341234'; + const caseTypeId = 'TestCaseType'; + const caseJurisdictionId = 'TestJurisdiction'; + const mockRoute = { snapshot: { data: { case: { - case_id: caseId + case_id: caseId, + case_type: { + id: caseTypeId, + jurisdiction: { + id: caseJurisdictionId + } + } } } } @@ -55,6 +64,6 @@ describe('CaseReviewSpecificAccessRejectComponent', () => { const myTaskLinkElement = fixture.debugElement.nativeElement.querySelector('.govuk-button'); expect(myTaskLinkElement.getAttribute('href')).toEqual(`tasks/list`); const viewCaseFileLinkElement = fixture.debugElement.nativeElement.querySelector('.cancel a'); - expect(viewCaseFileLinkElement.getAttribute('href')).toEqual(`cases/case-details/${caseId}`); + expect(viewCaseFileLinkElement.getAttribute('href')).toEqual(`cases/case-details/${caseJurisdictionId}/${caseTypeId}/${caseId}`); }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.spec.ts index 1489f7f5f9..1433c788d1 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/multiple-tasks-exist/multiple-tasks-exist.component.spec.ts @@ -16,7 +16,13 @@ describe('MultipleTasksExistComponent', () => { snapshot: { data: { case: { - case_id: '1620409659381330' + case_id: '1620409659381330', + case_type: { + id: 'TestCaseType', + jurisdiction: { + id: 'TestJurisdiction' + } + } } } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.spec.ts index 18538837fe..fe9692b477 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/no-tasks-available/no-tasks-available.component.spec.ts @@ -13,7 +13,13 @@ describe('NoTasksAvalaibleComponent', () => { snapshot: { data: { case: { - case_id: '1620409659381330' + case_id: '1620409659381330', + case_type: { + id: 'TestCaseType', + jurisdiction: { + id: 'TestJurisdiction' + } + } } } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.spec.ts index adab83903d..8a4eade048 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.spec.ts @@ -30,7 +30,7 @@ describe('TaskRequirementComponent', () => { case_id: '1620409659381330', case_management_category: null, case_name: 'Alan Jonson', - case_type_id: null, + case_type_id: 'TestCaseType', created_date: '2021-04-19T14:00:00.000+0000', due_date: '2021-05-20T16:00:00.000+0000', execution_type: null, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts index 079f7f6275..1e88cf6309 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-assigned/task-assigned.component.ts @@ -23,13 +23,13 @@ export class TaskAssignedComponent implements OnInit, OnDestroy { private readonly judicialworkerService: JudicialworkerService, private readonly caseworkerService: CaseworkerService) { this.caseId = this.route.snapshot.data.case.case_id; - this.jurisdiction = this.route.snapshot.data.case.case_type.jurisdiction.id; - this.caseType = this.route.snapshot.data.case.case_type.id; this.task = this.route.snapshot.queryParams as Task; } public ngOnInit(): void { // Current user is a caseworker? + this.jurisdiction = this.task.jurisdiction; + this.caseType = this.task.case_type_id; this.caseworkerSubscription = this.caseworkerService.getCaseworkers(this.task.jurisdiction).subscribe(result => { if (result && result[0].service === this.task.jurisdiction && result[0].caseworkers) { const caseworker = result[0].caseworkers.find(x => x.idamId === this.task.assignee); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.spec.ts index 2d3644a45b..43f3b940f3 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/components/task-unassigned/task-unassigned.component.spec.ts @@ -13,7 +13,13 @@ describe('TaskUnassignedComponent', () => { snapshot: { data: { case: { - case_id: '1620409659381330' + case_id: '1620409659381330', + case_type: { + id: 'TestCaseType', + jurisdiction: { + id: 'TestJurisdiction' + } + } } } } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts index 8cf1bfc87f..4f384a8dfd 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts @@ -18,13 +18,15 @@ describe('EventStartGuard', () => { id: '0d22d838-b25a-11eb-a18c-f2d58a9b7bc6', task_title: 'Some lovely task name', dueDate: '2021-05-20T16:00:00.000+0000', - description: '[End the appeal](/cases/case-details/${[CASE_REFERENCE]}/trigger/endAppeal/endAppealendAppeal', + description: '[End the appeal](/cases/case-details/${[JURISDICTION]}/${[CASE_TYPE]}/${[CASE_REFERENCE]}/trigger/endAppeal/endAppealendAppeal', location_name: 'Newcastle', location_id: '366796', case_id: '1620409659381330', case_category: 'asylum', case_name: 'Alan Jonson', permissions: [], + jurisdiction: 'TestJurisdiction', + case_type_id: 'TestCaseType' } ]; @@ -99,12 +101,12 @@ describe('EventStartGuard', () => { it('canActivate should navigate to event-start if task is required for event', () => { sessionStorageService.getItem.and.returnValue(JSON.stringify({ cid: 'caseId' })); const route = createActivatedRouteSnapshot('1620409659381330', 'eventId'); - const payload: TaskPayload = { task_required_for_event: true } as TaskPayload; + const payload: TaskPayload = { task_required_for_event: true, tasks} as TaskPayload; service.getTasksByCaseIdAndEventId.and.returnValue(of(payload)); const result$ = guard.canActivate(route); result$.subscribe(result => { expect(result).toEqual(false); - expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/1620409659381330/event-start'], { queryParams: { caseId: '1620409659381330', eventId: 'eventId', taskId: undefined } }); + expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/1620409659381330/event-start`], { queryParams: { caseId: '1620409659381330', eventId: 'eventId', taskId: undefined } }); }); }); @@ -176,7 +178,7 @@ describe('EventStartGuard', () => { const mockPayload: TaskPayload = {task_required_for_event: false, tasks}; sessionStorageService.getItem.and.returnValue(JSON.stringify(getExampleUserInfo())); expect(guard.checkTaskInEventNotRequired(mockPayload, caseId, null, null, null)).toBe(false); - expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/${caseId}/multiple-tasks-exist`]); + expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/${mockPayload.tasks[0].jurisdiction}/${mockPayload.tasks[0].case_type_id}/${caseId}/multiple-tasks-exist`]); }); it('should return true and navigate to event trigger if navigated to via task next steps', () => { @@ -241,7 +243,7 @@ describe('EventStartGuard - error', () => { id: '0d22d838-b25a-11eb-a18c-f2d58a9b7bc6', task_title: 'Some lovely task name', dueDate: '2021-05-20T16:00:00.000+0000', - description: '[End the appeal](/cases/case-details/${[CASE_REFERENCE]}/trigger/endAppeal/endAppealendAppeal', + description: '[End the appeal](/cases/case-details/${[JURISDICTION]}/${[CASE_TYPE]}/${[CASE_REFERENCE]}/trigger/endAppeal/endAppealendAppeal', location_name: 'Newcastle', location_id: '366796', case_id: '1620409659381330', diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-start.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-start.component.spec.ts index bb06f3b1d6..7c641b3af0 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-start.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-start.component.spec.ts @@ -33,7 +33,7 @@ describe('EventStartComponent', () => { case_id: '1620409659381330', case_management_category: null, case_name: 'Alan Jonson', - case_type_id: null, + case_type_id: 'Appeal', created_date: '2021-04-19T14:00:00.000+0000', due_date: '2021-05-20T16:00:00.000+0000', execution_type: null, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.spec.ts index d2ea4c7e81..972d276b00 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.spec.ts @@ -31,7 +31,7 @@ describe('EventStartStateMachineService', () => { case_id: '1620409659381330', case_management_category: null, case_name: 'Alan Jonson', - case_type_id: null, + case_type_id: 'Appeal-864', created_date: '2021-04-19T14:00:00.000+0000', due_date: '2021-05-20T16:00:00.000+0000', execution_type: null, @@ -193,7 +193,7 @@ describe('EventStartStateMachineService', () => { service.startStateMachine(stateMachine); expect(stateMachine.currentState.id).toEqual(EventStartStates.FINAL); expect(mockSessionStorageService.setItem).toHaveBeenCalled(); - expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.caseId}/trigger/${context.eventId}`], + expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.tasks[0].jurisdiction}/${context.tasks[0].case_type_id}/${context.caseId}/trigger/${context.eventId}`], { relativeTo: mockRoute }); }); @@ -209,7 +209,7 @@ describe('EventStartStateMachineService', () => { service.startStateMachine(stateMachine); expect(stateMachine.currentState.id).toEqual(EventStartStates.FINAL); expect(mockSessionStorageService.setItem).toHaveBeenCalled(); - expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.caseId}/trigger/${context.eventId}`], + expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.tasks[0].jurisdiction}/${context.tasks[0].case_type_id}/${context.caseId}/trigger/${context.eventId}`], { relativeTo: mockRoute }); }); @@ -221,7 +221,7 @@ describe('EventStartStateMachineService', () => { service.addTransitions(); service.startStateMachine(stateMachine); expect(stateMachine.currentState.id).toEqual(EventStartStates.FINAL); - expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.caseId}/task-unassigned`], + expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.tasks[0].jurisdiction}/${context.tasks[0].case_type_id}/${context.caseId}/task-unassigned`], { queryParams: {}, relativeTo: mockRoute }); }); @@ -233,10 +233,9 @@ describe('EventStartStateMachineService', () => { service.addTransitions(); service.startStateMachine(stateMachine); expect(stateMachine.currentState.id).toEqual(EventStartStates.FINAL); - expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.caseId}/task-assigned`], + expect(mockRouter.navigate).toHaveBeenCalledWith([`/cases/case-details/${context.tasks[0].jurisdiction}/${context.tasks[0].case_type_id}/${context.caseId}/task-assigned`], { queryParams: context.tasks[0], relativeTo: context.route }); }); - it('should action no task available', () => { stateMachine = service.initialiseStateMachine(context); service.createStates(stateMachine); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts index 6208e95762..f4099dceba 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/services/event-start-state-machine.service.ts @@ -108,17 +108,11 @@ export class EventStartStateMachineService { } } - private getJurisdictionNCaseType(context: EventStartStateMachineContext): any { - const caseInfo = context.sessionStorageService.getItem('caseInfo'); - return caseInfo ? JSON.parse(caseInfo) : null; - } - public entryActionForStateNoTask(state: State, context: EventStartStateMachineContext): void { // Trigger final state to complete processing of state machine state.trigger(EventStartStates.FINAL); // Navigate to no tasks available error page - const caseDetails = this.getJurisdictionNCaseType(context); - context.router.navigate([`/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/no-tasks-available`], { relativeTo: context.route }); + context.router.navigate([`/cases/case-details/${context.tasks[0]?.jurisdiction}/${context.tasks[0]?.case_type_id}/${context.caseId}/no-tasks-available`], { relativeTo: context.route }); } public entryActionForStateOneOrMoreTasks(state: State, context: EventStartStateMachineContext): void { @@ -165,14 +159,13 @@ export class EventStartStateMachineService { public entryActionForStateTaskUnAssigned(state: State, context: EventStartStateMachineContext): void { let navigationURL = ''; let theQueryParams: Params = {}; - const caseDetails = this.getJurisdictionNCaseType(context); if (context.tasks[0].assignee) { // Task is assigned to some other user, navigate to task assigned error page - navigationURL = `/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/task-assigned`; + navigationURL = `/cases/case-details/${context.tasks[0]?.jurisdiction}/${context.tasks[0]?.case_type_id}/${context.caseId}/task-assigned`; theQueryParams = context.tasks[0]; } else { // Task is unassigned, navigate to task unassigned error page - navigationURL = `/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/task-unassigned`; + navigationURL = `/cases/case-details/${context.tasks[0]?.jurisdiction}/${context.tasks[0]?.case_type_id}/${context.caseId}/task-unassigned`; } // Trigger final state to complete processing of state machine @@ -229,9 +222,8 @@ export class EventStartStateMachineService { public entryActionForStateMultipleTasksAssignedToUser(state: State, context: EventStartStateMachineContext): void { // Trigger final state to complete processing of state machine state.trigger(EventStartStates.FINAL); - const caseDetails = this.getJurisdictionNCaseType(context); // Navigate to multiple tasks exist error page - context.router.navigate([`/cases/case-details/${caseDetails?.jurisdiction}/${caseDetails.caseType}/${context.caseId}/multiple-tasks-exist`], { relativeTo: context.route }); + context.router.navigate([`/cases/case-details/${context.tasks[0]?.jurisdiction}/${context.tasks[0]?.case_type_id}/${context.caseId}/multiple-tasks-exist`], { relativeTo: context.route }); } public finalAction(state: State): void { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.spec.ts index 5e90dd0561..0470bc13bc 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/before-you-start/before-you-start.component.spec.ts @@ -20,7 +20,9 @@ describe('BeforeYouStartComponent', () => { serverLinkedApiError: null, hasContinuedFromStart: false, casesToUnlink: [], - initialCaseLinks: [] + initialCaseLinks: [], + caseJurisdictionID: 'TEST_JURISDICTION', + caseDetails: { case_type: 'TEST_CASE_TYPE' }, }; const mockRouter = { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.spec.ts index acc29ab0fc..298d3096ec 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/components/no-linked-cases/no-linked-cases.component.spec.ts @@ -18,6 +18,8 @@ describe('NoLinkedCasesComponent', () => { const linkedCasesService = { caseId: '1682374819203471', + caseJurisdictionID: 'TEST_JURISDICTION', + caseDetails: { case_type: 'TEST_CASE_TYPE' }, getAllLinkedCaseInformation() {} }; @@ -46,6 +48,6 @@ describe('NoLinkedCasesComponent', () => { it('should back button navigate to linked cases tab', () => { component.onBack(); - expect(router.navigate).toHaveBeenCalledWith(['cases', 'case-details', caseId], { fragment: 'Linked cases' }); + expect(router.navigate).toHaveBeenCalledWith(['cases', 'case-details', 'TEST_JURISDICTION', 'TEST_CASE_TYPE', caseId], { fragment: 'Linked cases' }); }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.spec.ts index 15da28e323..22ba77db0e 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/query-management/components/qualifying-questions/qualifying-question-options/qualifying-question-options.component.spec.ts @@ -17,10 +17,14 @@ describe('QualifyingQuestionOptionsComponent', () => { navigate: jasmine.createSpy('navigate') }; const caseId = '12345'; + const jurisdictionId = 'TestJurisdiction'; + const caseTypeId = 'TestCaseType'; const mockRoute = { snapshot: { params: { - cid: caseId + cid: caseId, + jurisdiction: jurisdictionId, + caseType: caseTypeId } } }; @@ -67,7 +71,7 @@ describe('QualifyingQuestionOptionsComponent', () => { it('should have the link to case details queries tab', () => { component.click(); - expect(router.navigate).toHaveBeenCalledWith(['cases', 'case-details', '12345'], { fragment: 'Queries' }); + expect(router.navigate).toHaveBeenCalledWith(['cases', 'case-details', 'TestJurisdiction', 'TestCaseType', '12345'], { fragment: 'Queries' }); }); describe('displayError', () => { From 195571ed511c80681b50d2e831748fc9b7b4c726 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 3 Jun 2025 16:02:54 +0100 Subject: [PATCH 06/21] fixed sonar issue --- .../palette/linked-cases/read-linked-cases-field.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts index b35d7cee6e..b88afa017f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/palette/linked-cases/read-linked-cases-field.component.ts @@ -56,7 +56,7 @@ export class ReadLinkedCasesFieldComponent implements OnInit, AfterViewInit { } public ngAfterViewInit(): void { - this.linkedCasesService.caseFieldValue = this.caseField?.value || []; + this.linkedCasesService.caseFieldValue = this.caseField?.value ?? []; let labelField = document.getElementsByClassName('govuk-heading-l'); if (labelField && labelField.length) { labelField[0].replaceWith(''); From 5c17e0fa82d4ce15a943e1f8797c0690573f4192 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Fri, 6 Jun 2025 10:11:33 +0100 Subject: [PATCH 07/21] url change --- .../components/case-editor/case-edit/case-edit.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts index 942e42bd72..e252a32205 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-editor/case-edit/case-edit.component.ts @@ -224,7 +224,7 @@ export class CaseEditComponent implements OnInit, OnDestroy { } public emitSubmitted(response: Record): void { - this.submitted.emit({ caseId: response['id'], status: this.getStatus(response) }); + this.submitted.emit({ caseId: response['id'], jurisdiction: response['jurisdiction'], caseType: response['case_type'], status: this.getStatus(response) }); } public getNextPage({ wizard, currentPageId, eventTrigger, form }: CaseEditGetNextPage): WizardPage { From 1da348a116ee83e5464ab3cb12d2c2331683fcb5 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 10 Jun 2025 14:37:36 +0100 Subject: [PATCH 08/21] url change --- .../case-full-access-view.component.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts index 4806233a89..3c2c8f6632 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts @@ -360,7 +360,14 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges const id = (tab.element.nativeElement as HTMLElement).id; // cases/case-details/:jurisdiction/:caseType/:caseId/hearings // cases/case-details/:jurisdiction/:caseType/:caseId/roles-and-access - this.router.navigate([id], { relativeTo: this.route }); + this.router.navigate([ + 'cases', + 'case-details', + this.caseDetails.case_type.jurisdiction.id, + this.caseDetails.case_type.id, + this.caseDetails.case_id, + id + ], { relativeTo: this.route.root }); } else { // Routing here is based on tab label, not ideal // cases/case-details/:jurisdiction/:caseType/:caseId#tabLabel From 209c35280a76228e14a686e3a2fb23fa02d6b170 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Fri, 27 Jun 2025 15:16:05 +0100 Subject: [PATCH 09/21] version updated --- RELEASE-NOTES.md | 3 +++ package.json | 2 +- projects/ccd-case-ui-toolkit/package.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index fbd0e5c117..b582648487 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,5 +1,8 @@ ## RELEASE NOTES +### Version 7.2.13-exui-2761-rc1 +**EXUI-2761** url change + ### Version 7.2.13 **EXUI-2703** Add apply and cancel filter buttons at the top of the case filters **EXUI-3050** SSCS - Duration of the hearing Value updating bug diff --git a/package.json b/package.json index c779ebb96f..7c6144fbd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13", + "version": "7.2.13-exui-2761-rc1", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/package.json b/projects/ccd-case-ui-toolkit/package.json index ac75e2580f..66ad4d37c4 100644 --- a/projects/ccd-case-ui-toolkit/package.json +++ b/projects/ccd-case-ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13", + "version": "7.2.13-exui-2761-rc1", "engines": { "node": ">=18.19.0" }, From 799d47c900ac12c576c605c1ce534a88c890791b Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 1 Jul 2025 15:53:45 +0100 Subject: [PATCH 10/21] fixed test --- package.json | 2 +- projects/ccd-case-ui-toolkit/package.json | 2 +- .../event-start/event-guard/event-start.guard.spec.ts | 10 +++++++--- .../event-start/event-guard/event-start.guard.ts | 8 ++++---- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 226f5b8a52..f137e18ab6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc2", + "version": "7.2.13-exui-2761-rc3", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/package.json b/projects/ccd-case-ui-toolkit/package.json index b18ce5a07f..cc44b90aee 100644 --- a/projects/ccd-case-ui-toolkit/package.json +++ b/projects/ccd-case-ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc2", + "version": "7.2.13-exui-2761-rc3", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts index 4f384a8dfd..b5dd84efcf 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.spec.ts @@ -101,12 +101,14 @@ describe('EventStartGuard', () => { it('canActivate should navigate to event-start if task is required for event', () => { sessionStorageService.getItem.and.returnValue(JSON.stringify({ cid: 'caseId' })); const route = createActivatedRouteSnapshot('1620409659381330', 'eventId'); - const payload: TaskPayload = { task_required_for_event: true, tasks} as TaskPayload; + guard.jurisdiction = 'jid'; + guard.caseType = 'ctid'; + const payload: TaskPayload = { task_required_for_event: true} as TaskPayload; service.getTasksByCaseIdAndEventId.and.returnValue(of(payload)); const result$ = guard.canActivate(route); result$.subscribe(result => { expect(result).toEqual(false); - expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/1620409659381330/event-start`], { queryParams: { caseId: '1620409659381330', eventId: 'eventId', taskId: undefined } }); + expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/jid/ctid/1620409659381330/event-start`], { queryParams: { caseId: '1620409659381330', eventId: 'eventId', taskId: undefined } }); }); }); @@ -175,10 +177,12 @@ describe('EventStartGuard', () => { it('should return false with error navigation if there are more than 1 tasks assigned to the user', () => { tasks[0].assignee = '1'; tasks.push(tasks[0]); + guard.jurisdiction = 'jid'; + guard.caseType = 'ctid'; const mockPayload: TaskPayload = {task_required_for_event: false, tasks}; sessionStorageService.getItem.and.returnValue(JSON.stringify(getExampleUserInfo())); expect(guard.checkTaskInEventNotRequired(mockPayload, caseId, null, null, null)).toBe(false); - expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/${mockPayload.tasks[0].jurisdiction}/${mockPayload.tasks[0].case_type_id}/${caseId}/multiple-tasks-exist`]); + expect(router.navigate).toHaveBeenCalledWith([`/cases/case-details/jid/ctid/${caseId}/multiple-tasks-exist`]); }); it('should return true and navigate to event trigger if navigated to via task next steps', () => { diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts index 453dfe9699..abf8d29894 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/event-start/event-guard/event-start.guard.ts @@ -12,8 +12,8 @@ import { removeTaskFromClientContext } from '../../case-editor/case-edit-utils/c @Injectable() export class EventStartGuard implements CanActivate { - private jurisdiction: string; - private caseType: string; + public jurisdiction: string; + public caseType: string; private caseId: string; constructor(private readonly workAllocationService: WorkAllocationService, @@ -119,7 +119,7 @@ export class EventStartGuard implements CanActivate { return true; } else if (tasksAssignedToUser.length > 1 && !taskId) { // if more than one task assigned to the user then give multiple tasks error - this.router.navigate([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/${caseId}/multiple-tasks-exist`]); + this.router.navigate([`/cases/case-details/${this.jurisdiction}/${this.caseType}/${caseId}/multiple-tasks-exist`]); return false; } else { let task: any; @@ -150,7 +150,7 @@ export class EventStartGuard implements CanActivate { if (this.router && this.router.url && this.router.url.includes('event-start')) { return of(true); } - this.router.navigate([`/cases/case-details/${payload.tasks[0].jurisdiction}/${payload.tasks[0].case_type_id}/${caseId}/event-start`], { queryParams: { caseId, eventId, taskId } }); + this.router.navigate([`/cases/case-details/${this.jurisdiction}/${this.caseType}/${caseId}/event-start`], { queryParams: { caseId, eventId, taskId } }); return of(false); } else { return of(this.checkTaskInEventNotRequired(payload, caseId, taskId, eventId, userId)); From d830f1dca6e4134faed75eca79a390f503d594fe Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 1 Jul 2025 15:59:07 +0100 Subject: [PATCH 11/21] cve --- yarn-audit-known-issues | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-audit-known-issues b/yarn-audit-known-issues index 68f9db8ad8..780225daac 100644 --- a/yarn-audit-known-issues +++ b/yarn-audit-known-issues @@ -7,7 +7,7 @@ {"value":"core-js","children":{"ID":"core-js (deprecation)","Issue":"core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.","Severity":"moderate","Vulnerable Versions":"1.2.7","Tree Versions":["1.2.7"],"Dependents":["fbjs@npm:0.8.18"]}} {"value":"cross-spawn","children":{"ID":1104663,"Issue":"Regular Expression Denial of Service (ReDoS) in cross-spawn","URL":"https://github.com/advisories/GHSA-3xgq-45jj-v275","Severity":"high","Vulnerable Versions":"<6.0.6","Tree Versions":["5.1.0"],"Dependents":["execa@npm:0.7.0"]}} {"value":"domexception","children":{"ID":"domexception (deprecation)","Issue":"Use your platform's native DOMException instead","Severity":"moderate","Vulnerable Versions":"4.0.0","Tree Versions":["4.0.0"],"Dependents":["jsdom@virtual:ce56289c4b7a2e9003d709997e253c1c80dcaee4c6fbe440cbe9ba5de5db8af3a7b7ad41bbdec5a5e3d40dc9c3c54bef92dd6885ff84cd436d636d5a1b380a61#npm:20.0.3"]}} -{"value":"dompurify","children":{"ID":1102259,"Issue":"DOMPurify allows Cross-site Scripting (XSS)","URL":"https://github.com/advisories/GHSA-vhxf-7vqr-mrjg","Severity":"moderate","Vulnerable Versions":"<3.2.4","Tree Versions":["3.1.5"],"Dependents":["mermaid@npm:10.9.1"]}} +{"value":"dompurify","children":{"ID":1105772,"Issue":"DOMPurify allows Cross-site Scripting (XSS)","URL":"https://github.com/advisories/GHSA-vhxf-7vqr-mrjg","Severity":"moderate","Vulnerable Versions":"<3.2.4","Tree Versions":["3.1.5"],"Dependents":["mermaid@npm:10.9.1"]}} {"value":"express","children":{"ID":1096820,"Issue":"Express.js Open Redirect in malformed URLs","URL":"https://github.com/advisories/GHSA-rv95-896h-c2vc","Severity":"moderate","Vulnerable Versions":"<4.19.2","Tree Versions":["4.18.2"],"Dependents":["json-server@npm:0.15.1"]}} {"value":"express","children":{"ID":1100530,"Issue":"express vulnerable to XSS via response.redirect()","URL":"https://github.com/advisories/GHSA-qw6h-vgh9-j6wx","Severity":"low","Vulnerable Versions":"<4.20.0","Tree Versions":["4.18.2"],"Dependents":["json-server@npm:0.15.1"]}} {"value":"figgy-pudding","children":{"ID":"figgy-pudding (deprecation)","Issue":"This module is no longer supported.","Severity":"moderate","Vulnerable Versions":"3.5.2","Tree Versions":["3.5.2"],"Dependents":["npm-registry-fetch@npm:4.0.7"]}} @@ -35,7 +35,7 @@ {"value":"path-to-regexp","children":{"ID":1105199,"Issue":"path-to-regexp contains a ReDoS","URL":"https://github.com/advisories/GHSA-rhx6-c78j-4q9w","Severity":"high","Vulnerable Versions":"<0.1.12","Tree Versions":["0.1.7"],"Dependents":["express@npm:4.18.2"]}} {"value":"prismjs","children":{"ID":1089189,"Issue":"prismjs Regular Expression Denial of Service vulnerability","URL":"https://github.com/advisories/GHSA-hqhp-5p83-hx96","Severity":"moderate","Vulnerable Versions":"<1.25.0","Tree Versions":["1.24.1"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} {"value":"prismjs","children":{"ID":1090424,"Issue":"Cross-site Scripting in Prism","URL":"https://github.com/advisories/GHSA-3949-f494-cm99","Severity":"high","Vulnerable Versions":">=1.14.0 <1.27.0","Tree Versions":["1.24.1"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} -{"value":"prismjs","children":{"ID":1102459,"Issue":"PrismJS DOM Clobbering vulnerability","URL":"https://github.com/advisories/GHSA-x7hr-w5r2-h6wg","Severity":"moderate","Vulnerable Versions":"<1.30.0","Tree Versions":["1.24.1"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} +{"value":"prismjs","children":{"ID":1105770,"Issue":"PrismJS DOM Clobbering vulnerability","URL":"https://github.com/advisories/GHSA-x7hr-w5r2-h6wg","Severity":"moderate","Vulnerable Versions":"<1.30.0","Tree Versions":["1.24.1"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} {"value":"request","children":{"ID":1096727,"Issue":"Server-Side Request Forgery in Request","URL":"https://github.com/advisories/GHSA-p8p7-x288-28g6","Severity":"moderate","Vulnerable Versions":"<=2.88.2","Tree Versions":["2.88.2"],"Dependents":["json-server@npm:0.15.1"]}} {"value":"resolve-url","children":{"ID":"resolve-url (deprecation)","Issue":"https://github.com/lydell/resolve-url#deprecated","Severity":"moderate","Vulnerable Versions":"0.2.1","Tree Versions":["0.2.1"],"Dependents":["source-map-resolve@npm:0.5.3"]}} {"value":"rimraf","children":{"ID":"rimraf (deprecation)","Issue":"Rimraf versions prior to v4 are no longer supported","Severity":"moderate","Vulnerable Versions":"2.7.1","Tree Versions":["2.7.1"],"Dependents":["cacache@npm:12.0.4"]}} From c15703581920c83dff6b685ad8999b69324a4a7e Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 1 Jul 2025 15:59:57 +0100 Subject: [PATCH 12/21] version updated --- package.json | 2 +- projects/ccd-case-ui-toolkit/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f137e18ab6..c2d6d73759 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc3", + "version": "7.2.13-exui-2761-rc4", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/package.json b/projects/ccd-case-ui-toolkit/package.json index cc44b90aee..8f79910cca 100644 --- a/projects/ccd-case-ui-toolkit/package.json +++ b/projects/ccd-case-ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc3", + "version": "7.2.13-exui-2761-rc4", "engines": { "node": ">=18.19.0" }, From 5f3f4d104fb7619f75b78a07ef657e83dc35d098 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 10:46:53 +0100 Subject: [PATCH 13/21] fix back button url link --- package.json | 2 +- projects/ccd-case-ui-toolkit/package.json | 2 +- .../case-event-trigger.component.spec.ts | 16 +++++++++++++++- .../case-event-trigger.component.ts | 19 ++++++++++++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c2d6d73759..470460d90b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc4", + "version": "7.2.13-exui-2761-rc5", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/package.json b/projects/ccd-case-ui-toolkit/package.json index 8f79910cca..2e92c52c50 100644 --- a/projects/ccd-case-ui-toolkit/package.json +++ b/projects/ccd-case-ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.13-exui-2761-rc4", + "version": "7.2.13-exui-2761-rc5", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts index ab41d8ef02..f7b8c59bb9 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts @@ -136,7 +136,7 @@ describe('CaseEventTriggerComponent', () => { let sessionStorageService: any; let casesReferencePipe: any; let activityPollingService: any; - const finalUrl = '/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104#Claim%20details'; + let finalUrl = '/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104#Claim%20details'; beforeEach(waitForAsync(() => { caseNotifier = createSpyObj('caseService', ['announceCase']); @@ -380,5 +380,19 @@ describe('CaseEventTriggerComponent', () => { component.ngOnInit(); expect(loadingService.hasSharedSpinner).toBeTruthy(); expect(loadingService.unregisterSharedSpinner).toHaveBeenCalled(); + }) + + it('cancel should navigate to url with fragment if previousUrl contains #', () => { + finalUrl = '/cases/case-details/1707912713167104#Claim%20details' + spyOn(component as any, 'getNavigationUrl').and.callThrough(); + component.cancel(); + expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104'], { fragment: 'Claim details' }); + }); + +it('getNavigationUrl should transform url if it matches /case-details/:id', () => { + component.caseDetails = CASE_DETAILS; + const url = '/case-details/1707912713167104'; + const result = component['getNavigationUrl'](url); + expect(result).toBe('/case-details/TEST/TEST_CASE_TYPE/1707912713167104'); }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index c0825d0d18..43d7b56e6f 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -123,9 +123,25 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { }); } + // replace the old link with the new one with jurisdiction and case type id + private getNavigationUrl(url: string): string { + const urlRegex = /\/case-details\/(\d+)/; + const match = url.match(urlRegex); + if (match && /^\d+$/.test(match[1]) && this.caseDetails?.case_type) { + const jurisdiction = this.caseDetails.case_type.jurisdiction.id; + const id = this.caseDetails.case_type.id; + return url.replace( + urlRegex, + `/case-details/${jurisdiction}/${id}/${match[1]}` + ); + } + return url; + } + public cancel(): Promise { - const previousUrl = this.routerCurrentNavigation?.previousNavigation?.finalUrl?.toString(); + let previousUrl = this.routerCurrentNavigation?.previousNavigation?.finalUrl?.toString(); if (previousUrl) { + previousUrl = this.getNavigationUrl(previousUrl); if (previousUrl.indexOf('#') > -1) { const url = previousUrl.split('#')[0]; const fragment = previousUrl.split('#')[1].replace(/%20/g, ' '); @@ -134,6 +150,7 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return this.router.navigate([previousUrl]); } } else { + this.parentUrl = this.getNavigationUrl(this.parentUrl); return this.router.navigate([this.parentUrl]); } } From c84713686be47bcedc8f5ee84c70821b0be3bd2b Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 14:20:27 +0100 Subject: [PATCH 14/21] fixed navigation --- .../case-event-trigger.component.spec.ts | 2 +- .../case-event-trigger.component.ts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts index f7b8c59bb9..758e8d1eaf 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts @@ -389,7 +389,7 @@ describe('CaseEventTriggerComponent', () => { expect(router.navigate).toHaveBeenCalledWith(['/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104'], { fragment: 'Claim details' }); }); -it('getNavigationUrl should transform url if it matches /case-details/:id', () => { + it('getNavigationUrl should transform url if it matches /case-details/:id', () => { component.caseDetails = CASE_DETAILS; const url = '/case-details/1707912713167104'; const result = component['getNavigationUrl'](url); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index 43d7b56e6f..a19a99c073 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -138,6 +138,22 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return url; } + private getNavigationUrlWithTab(url: string): string { + const hasTidQuery = this.router.url.includes('?tid='); + const isNotCasesPath = !this.parentUrl.includes('/cases'); + const match = this.parentUrl.match(/(\d+)(.*)$/); + const hasNoExtraPath = match && !match[2]; + + if (hasTidQuery && isNotCasesPath && hasNoExtraPath) { + // Only add '/cases' prefix if not already present + if (!this.parentUrl.startsWith('/cases')) { + return `/cases${this.parentUrl}/tasks`; + } + return `${this.parentUrl}/tasks`; + } + return url; + } + public cancel(): Promise { let previousUrl = this.routerCurrentNavigation?.previousNavigation?.finalUrl?.toString(); if (previousUrl) { @@ -151,6 +167,8 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { } } else { this.parentUrl = this.getNavigationUrl(this.parentUrl); + // If there is no tab name in the URL, we need to navigate to the tasks tab + this.parentUrl = this.getNavigationUrlWithTab(this.parentUrl); return this.router.navigate([this.parentUrl]); } } From eed2234535fd6b6480353ff8ed1e323a0ce4f98d Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 15:14:41 +0100 Subject: [PATCH 15/21] fixe unit test --- .../case-event-trigger.component.spec.ts | 6 +++++ .../case-event-trigger.component.ts | 24 +++++++++---------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts index 758e8d1eaf..eaaaa3886a 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts @@ -395,4 +395,10 @@ describe('CaseEventTriggerComponent', () => { const result = component['getNavigationUrl'](url); expect(result).toBe('/case-details/TEST/TEST_CASE_TYPE/1707912713167104'); }); + + it('getNavigationUrlWithTab should add /cases prefix and /tasks if needed', () => { + finalUrl = '/case-details/TEST/TEST_CASE_TYPE/1707912713167104'; + const result = component['getNavigationUrlWithTab'](finalUrl); + expect(result).toBe('/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104/tasks'); + }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index a19a99c073..86c88c12fe 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -138,20 +138,18 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return url; } - private getNavigationUrlWithTab(url: string): string { - const hasTidQuery = this.router.url.includes('?tid='); - const isNotCasesPath = !this.parentUrl.includes('/cases'); - const match = this.parentUrl.match(/(\d+)(.*)$/); + private getNavigationUrlWithTab(urlLink: string): string { + const isNotCasesPath = !urlLink.startsWith('/cases'); + const match = urlLink.match(/^.*?(\d+)([^\/]*)$/); const hasNoExtraPath = match && !match[2]; - - if (hasTidQuery && isNotCasesPath && hasNoExtraPath) { + if (isNotCasesPath && hasNoExtraPath) { // Only add '/cases' prefix if not already present - if (!this.parentUrl.startsWith('/cases')) { - return `/cases${this.parentUrl}/tasks`; + if (!urlLink.startsWith('/cases')) { + return `/cases${urlLink}/tasks`; } - return `${this.parentUrl}/tasks`; + return `${urlLink}/tasks`; } - return url; + return urlLink; } public cancel(): Promise { @@ -166,10 +164,10 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return this.router.navigate([previousUrl]); } } else { - this.parentUrl = this.getNavigationUrl(this.parentUrl); + const url = this.getNavigationUrl(this.parentUrl); // If there is no tab name in the URL, we need to navigate to the tasks tab - this.parentUrl = this.getNavigationUrlWithTab(this.parentUrl); - return this.router.navigate([this.parentUrl]); + const updatedUrl = this.getNavigationUrlWithTab(url); + return this.router.navigate([updatedUrl]); } } From dc025e01269b1e87ee9815f905ce5add684426c0 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 15:24:46 +0100 Subject: [PATCH 16/21] updated regex for security failure --- .../case-event-trigger/case-event-trigger.component.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index 86c88c12fe..e60c1448df 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -140,7 +140,8 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { private getNavigationUrlWithTab(urlLink: string): string { const isNotCasesPath = !urlLink.startsWith('/cases'); - const match = urlLink.match(/^.*?(\d+)([^\/]*)$/); + // Use a safer regex to avoid super-linear runtime (ReDoS) + const match = urlLink.match(/(?:^|\/)(\d+)([^\/]*)$/); const hasNoExtraPath = match && !match[2]; if (isNotCasesPath && hasNoExtraPath) { // Only add '/cases' prefix if not already present From 54edf394d5702580a10ae40f8e52efc25fa7c552 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 15:38:51 +0100 Subject: [PATCH 17/21] updatetest and revert the change --- .../case-event-trigger/case-event-trigger.component.spec.ts | 6 ------ .../case-event-trigger/case-event-trigger.component.ts | 4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts index eaaaa3886a..758e8d1eaf 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.spec.ts @@ -395,10 +395,4 @@ describe('CaseEventTriggerComponent', () => { const result = component['getNavigationUrl'](url); expect(result).toBe('/case-details/TEST/TEST_CASE_TYPE/1707912713167104'); }); - - it('getNavigationUrlWithTab should add /cases prefix and /tasks if needed', () => { - finalUrl = '/case-details/TEST/TEST_CASE_TYPE/1707912713167104'; - const result = component['getNavigationUrlWithTab'](finalUrl); - expect(result).toBe('/cases/case-details/TEST/TEST_CASE_TYPE/1707912713167104/tasks'); - }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index e60c1448df..854c871d96 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -165,9 +165,7 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return this.router.navigate([previousUrl]); } } else { - const url = this.getNavigationUrl(this.parentUrl); - // If there is no tab name in the URL, we need to navigate to the tasks tab - const updatedUrl = this.getNavigationUrlWithTab(url); + const updatedUrl = this.getNavigationUrl(this.parentUrl); return this.router.navigate([updatedUrl]); } } From a0504d68fdbf04d2dccd635036e7173c49b35851 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Thu, 3 Jul 2025 15:52:24 +0100 Subject: [PATCH 18/21] revert the unwanted code --- .../case-event-trigger.component.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts index 854c871d96..a5ee525dca 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-event-trigger/case-event-trigger.component.ts @@ -138,21 +138,6 @@ export class CaseEventTriggerComponent implements OnInit, OnDestroy { return url; } - private getNavigationUrlWithTab(urlLink: string): string { - const isNotCasesPath = !urlLink.startsWith('/cases'); - // Use a safer regex to avoid super-linear runtime (ReDoS) - const match = urlLink.match(/(?:^|\/)(\d+)([^\/]*)$/); - const hasNoExtraPath = match && !match[2]; - if (isNotCasesPath && hasNoExtraPath) { - // Only add '/cases' prefix if not already present - if (!urlLink.startsWith('/cases')) { - return `/cases${urlLink}/tasks`; - } - return `${urlLink}/tasks`; - } - return urlLink; - } - public cancel(): Promise { let previousUrl = this.routerCurrentNavigation?.previousNavigation?.finalUrl?.toString(); if (previousUrl) { From 4811486a2faf16bf46f0b94e891d75bd27db11a8 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Wed, 20 Aug 2025 16:42:09 +0100 Subject: [PATCH 19/21] cve --- yarn-audit-known-issues | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-audit-known-issues b/yarn-audit-known-issues index eeb01c9307..b1e285317f 100644 --- a/yarn-audit-known-issues +++ b/yarn-audit-known-issues @@ -27,6 +27,7 @@ {"value":"marked","children":{"ID":1095051,"Issue":"Inefficient Regular Expression Complexity in marked","URL":"https://github.com/advisories/GHSA-rrrm-qjm4-v8hf","Severity":"high","Vulnerable Versions":"<4.0.10","Tree Versions":["0.7.0"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} {"value":"marked","children":{"ID":1095052,"Issue":"Inefficient Regular Expression Complexity in marked","URL":"https://github.com/advisories/GHSA-5v2h-r2cx-5xgj","Severity":"high","Vulnerable Versions":"<4.0.10","Tree Versions":["0.7.0"],"Dependents":["@hmcts/ccd-case-ui-toolkit@workspace:."]}} {"value":"mermaid","children":{"ID":1100231,"Issue":"Prototype pollution vulnerability found in Mermaid's bundled version of DOMPurify","URL":"https://github.com/advisories/GHSA-m4gq-x24j-jpmf","Severity":"high","Vulnerable Versions":"<=10.9.2","Tree Versions":["10.9.1"],"Dependents":["ngx-markdown@virtual:6ff8c2a3aef81417d9f60600e3255d97c9c6c863d8733a87ed99d869392767523e0e28c07db1eb2a034bc9265813386132447698258584d621a7fd0e13d93585#npm:17.2.1"]}} +{"value":"mermaid","children":{"ID":1106952,"Issue":"Mermaid improperly sanitizes sequence diagram labels leading to XSS","URL":"https://github.com/advisories/GHSA-7rqq-prvp-x9jh","Severity":"moderate","Vulnerable Versions":">=10.9.0-rc.1 <11.10.0","Tree Versions":["10.9.1"],"Dependents":["ngx-markdown@virtual:6ff8c2a3aef81417d9f60600e3255d97c9c6c863d8733a87ed99d869392767523e0e28c07db1eb2a034bc9265813386132447698258584d621a7fd0e13d93585#npm:17.2.1"]}} {"value":"micromatch","children":{"ID":1098681,"Issue":"Regular Expression Denial of Service (ReDoS) in micromatch","URL":"https://github.com/advisories/GHSA-952p-6rrq-rcjv","Severity":"moderate","Vulnerable Versions":"<4.0.8","Tree Versions":["4.0.5"],"Dependents":["fast-glob@npm:3.3.2"]}} {"value":"move-concurrently","children":{"ID":"move-concurrently (deprecation)","Issue":"This package is no longer supported.","Severity":"moderate","Vulnerable Versions":"1.0.1","Tree Versions":["1.0.1"],"Dependents":["cacache@npm:12.0.4"]}} {"value":"nanoid","children":{"ID":1101163,"Issue":"Predictable results in nanoid generation when given non-integer values","URL":"https://github.com/advisories/GHSA-mwcw-c2x4-8c55","Severity":"moderate","Vulnerable Versions":"<3.3.8","Tree Versions":["2.1.11"],"Dependents":["json-server@npm:0.15.1"]}} From cb24513a707784c52da35dacd5bc8758dfc67410 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Tue, 26 Aug 2025 12:27:20 +0100 Subject: [PATCH 20/21] version updated --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27e6588edc..61171ec7f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.38-exui-2761-rc1", + "version": "7.2.23-exui-2761-rc3", "engines": { "node": ">=18.19.0" }, From bfaea77d61095aba41eb66ce82c91f563b679cc7 Mon Sep 17 00:00:00 2001 From: RiteshHMCTS Date: Fri, 19 Sep 2025 16:14:28 +0100 Subject: [PATCH 21/21] fir for markdown link event --- package.json | 2 +- projects/ccd-case-ui-toolkit/package.json | 2 +- .../case-full-access-view.component.spec.ts | 17 +- .../case-full-access-view.component.ts | 15 ++ .../services/event-trigger.resolver.spec.ts | 173 ++++++++++++++++-- .../services/event-trigger.resolver.ts | 42 ++++- 6 files changed, 233 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 09ee35aa89..a3fa101040 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.43-exui-2761-rc1", + "version": "7.2.43-exui-2761-rc2", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/package.json b/projects/ccd-case-ui-toolkit/package.json index 90d53ff959..310401be9e 100644 --- a/projects/ccd-case-ui-toolkit/package.json +++ b/projects/ccd-case-ui-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@hmcts/ccd-case-ui-toolkit", - "version": "7.2.43-exui-2761-rc1", + "version": "7.2.43-exui-2761-rc2", "engines": { "node": ">=18.19.0" }, diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts index 74ce54b879..f61a4a26ff 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.spec.ts @@ -739,7 +739,7 @@ describe('CaseFullAccessViewComponent', () => { fixture.detectChanges(); })); -it('should set case view tab based on navigation end event', () => { + it('should set case view tab based on navigation end event', () => { // Mock tabGroup._tabs with some dummy values for testing component.tabGroup = { _tabs: [{ textLabel: 'Tab1' }, { textLabel: 'Tab2' }] } as any; @@ -767,6 +767,21 @@ it('should set case view tab based on navigation end event', () => { }); }) + it('should call setCaseInfo', () => { + spyOn(component, 'setCaseInfo'); + component.ngOnInit(); + expect((component as any).setCaseInfo).toHaveBeenCalled(); + }); + + it('should call setCaseInfo and update sessionStorage if caseId differs', () => { + sessionStorageMockService.getItem.and.returnValue(JSON.stringify({ caseId: 'old' })); + component.caseDetails.case_id = 'new'; + component.caseDetails.case_type.jurisdiction.id = 'jid'; + component.caseDetails.case_type.id = 'ctid'; + component['setCaseInfo'](); + expect(sessionStorageMockService.setItem).toHaveBeenCalled(); + }); + it('should call reset for linkedCaseService and caseFlagStateService oninit', () => { const linkedCasesService = TestBed.inject(LinkedCasesService); const caseFlagStateService = TestBed.inject(CaseFlagStateService); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts index 3c2c8f6632..525e3fb257 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/case-full-access-view/case-full-access-view.component.ts @@ -136,6 +136,8 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges this.checkRouteAndSetCaseViewTab(); + this.setCaseInfo(); + // Check for active Case Flags this.activeCaseFlags = this.hasActiveCaseFlags(); this.linkedCasesService.resetLinkedCaseData(); @@ -150,6 +152,19 @@ export class CaseFullAccessViewComponent implements OnInit, OnDestroy, OnChanges } } + private setCaseInfo(): void { + const caseInfo = JSON.parse(this.sessionStorageService.getItem('caseInfo') || '{}'); + console.log('Case Info from session storage: ', caseInfo); + if (caseInfo?.caseId !== this.caseDetails.case_id) { + const newCaseInfo = { + caseId: this.caseDetails.case_id, + jurisdiction: this.caseDetails.case_type.jurisdiction.id, + caseType: this.caseDetails.case_type.id + }; + this.sessionStorageService.setItem('caseInfo', JSON.stringify(newCaseInfo)); + } + } + public isPrintEnabled(): boolean { return this.caseDetails.case_type.printEnabled; } diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.spec.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.spec.ts index 9335320973..4b370ae32d 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.spec.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.spec.ts @@ -4,7 +4,7 @@ import { AbstractAppConfig } from '../../../../app.config'; import { CaseEventTrigger, HttpError, Profile } from '../../../domain'; import { createAProfile } from '../../../domain/profile/profile.test.fixture'; import { createCaseEventTrigger } from '../../../fixture'; -import { ErrorNotifierService, HttpService, LoadingService, ProfileNotifier, ProfileService } from '../../../services'; +import { ErrorNotifierService, HttpService, LoadingService, ProfileNotifier, ProfileService, SessionStorageService } from '../../../services'; import { CaseResolver } from './case.resolver'; import { EventTriggerResolver } from './event-trigger.resolver'; @@ -32,6 +32,7 @@ describe('EventTriggerResolver', () => { let alertService: any; let orderService: any; let loadingService: any; + let sessionStorageService: any; let route: any; @@ -79,6 +80,7 @@ describe('EventTriggerResolver', () => { profileService = createSpyObj('profileService', ['get']); profileNotifier = new ProfileNotifier(); errorNotifier = new ErrorNotifierService(); + sessionStorageService = createSpyObj('sessionStorageService', ['getItem']); router = createSpyObj('router', ['navigate']); @@ -88,7 +90,7 @@ describe('EventTriggerResolver', () => { httpService = createSpyObj('httpService', ['get']); httpService.get.and.returnValue(of(MOCK_PROFILE)); - eventTriggerResolver = new EventTriggerResolver(casesService, alertService, profileService, profileNotifier, router, appConfig, errorNotifier, loadingService); + eventTriggerResolver = new EventTriggerResolver(casesService, alertService, profileService, profileNotifier, router, appConfig, errorNotifier, loadingService, sessionStorageService); route = { firstChild: { @@ -110,8 +112,11 @@ describe('EventTriggerResolver', () => { }); route.parent.paramMap.get.and.callFake(key => { - // tslint:disable-next-line:switch-default switch (key) { + case 'jurisdiction': + return 'PRIVATELAW'; + case 'caseType': + return 'PRLAPPS'; case PARAM_CASE_ID: return CASE_ID; } @@ -140,7 +145,7 @@ describe('EventTriggerResolver', () => { expect(profileService.get).toHaveBeenCalledWith(); expect(casesService.getEventTrigger).toHaveBeenCalledWith(undefined, EVENT_TRIGGER_ID, CASE_ID, IGNORE_WARNING_VALUE); expect(route.paramMap.get).toHaveBeenCalledWith(PARAM_EVENT_ID); - expect(route.paramMap.get).toHaveBeenCalledTimes(1); + expect(route.paramMap.get).toHaveBeenCalledTimes(3); expect(eventTriggerResolver['cachedEventTrigger']).toBe(EVENT_TRIGGER); }); @@ -155,6 +160,16 @@ describe('EventTriggerResolver', () => { paramMap: createSpyObj('paramMap', ['get']), } }; + route.parent.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return 'PRIVATELAW'; + case 'caseType': + return 'PRLAPPS'; + case PARAM_CASE_ID: + return CASE_ID; + } + }); casesService.getEventTrigger.and.returnValue(EVENT_TRIGGER_OBS); expect(eventTriggerResolver['cachedEventTrigger']).toBeUndefined(); profileService.get.and.returnValue(PROFILE_OBS); @@ -167,25 +182,35 @@ describe('EventTriggerResolver', () => { expect(profileService.get).toHaveBeenCalledWith(); expect(casesService.getEventTrigger).toHaveBeenCalled(); expect(route.paramMap.get).toHaveBeenCalledWith(PARAM_EVENT_ID); - expect(route.paramMap.get).toHaveBeenCalledTimes(1); + expect(route.paramMap.get).toHaveBeenCalledTimes(3); expect(eventTriggerResolver['cachedEventTrigger']).toBe(EVENT_TRIGGER); }); it('should return cached event trigger when route is not trigger/:eid if cache is not empty', () => { route = { firstChild: { - url: ['someChild'] - }, - queryParamMap : createSpyObj('queryParamMap', ['get']), + url: ['someChild'] + }, + queryParamMap: createSpyObj('queryParamMap', ['get']), paramMap: createSpyObj('paramMap', ['get']), parent: { - paramMap: createSpyObj('paramMap', ['get']) + paramMap: createSpyObj('paramMap', ['get']) }, params: { - eid: EVENT_TRIGGER_ID, - cid: '42' + eid: EVENT_TRIGGER_ID, + cid: '42' } }; + route.parent.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return 'PRIVATELAW'; + case 'caseType': + return 'PRLAPPS'; + case PARAM_CASE_ID: + return CASE_ID; + } + }); casesService.getEventTrigger.and.returnValue(EVENT_TRIGGER_OBS); eventTriggerResolver['cachedEventTrigger'] = EVENT_TRIGGER; profileService.get.and.returnValue(PROFILE_OBS); @@ -249,4 +274,130 @@ describe('EventTriggerResolver', () => { expect(casesService.getEventTrigger).toHaveBeenCalled(); expect(eventTriggerResolver['cachedProfile']).toBe(PROFILE); }); + +it('should redirect and return null if jurisdiction or caseType are missing and caseInfo is incomplete', async () => { + route.parent.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return null; + case 'caseType': + return null; + case PARAM_CASE_ID: + return CASE_ID; + } + }); + route.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return null; + case 'caseType': + return null; + case PARAM_EVENT_ID: + return EVENT_TRIGGER_ID; + case PARAM_CASE_ID: + return CASE_ID; + } + }); + sessionStorageService.getItem.and.returnValue('{}'); + eventTriggerResolver + .resolve(route) + .then(result => { + expect(result).toBeNull(); + expect(alertService.error).toHaveBeenCalledWith({ phrase: 'Cannot determine jurisdiction and case type' }); + expect(router.navigate).toHaveBeenCalledWith([router.url]); + }); + }); + + it('should redirect to correct URL if jurisdiction or caseType are missing but caseInfo is present', async () => { + const caseInfo = { + jurisdiction: 'testJurisdiction', + caseType: 'testCaseType', + caseId: CASE_ID + }; + route.parent.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return null; + case 'caseType': + return null; + case PARAM_CASE_ID: + return CASE_ID; + } + }); + route.paramMap.get.and.callFake(key => { + switch (key) { + case 'jurisdiction': + return null; + case 'caseType': + return null; + case PARAM_EVENT_ID: + return EVENT_TRIGGER_ID; + case PARAM_CASE_ID: + return CASE_ID; + } + }); + route.queryParams = { foo: 'bar' }; + sessionStorageService.getItem.and.returnValue(JSON.stringify(caseInfo)); + eventTriggerResolver + .resolve(route) + .then(result => { + expect(result).toBeNull(); + expect(router.navigate).toHaveBeenCalledWith([ + '/cases/case-details', + caseInfo.jurisdiction, + caseInfo.caseType, + CASE_ID, + 'trigger', + EVENT_TRIGGER_ID + ], { queryParams: { foo: 'bar' } }); + }); + }); + + it('should reset cached event trigger', () => { + eventTriggerResolver['cachedEventTrigger'] = EVENT_TRIGGER; + eventTriggerResolver.resetCachedEventTrigger(); + expect(eventTriggerResolver['cachedEventTrigger']).toBeNull(); + }); + + it('should set ignoreWarning to false if not valid value', async () => { + route.queryParamMap.get.and.returnValue('invalid'); + casesService.getEventTrigger.and.callFake((caseTypeId, eventTriggerId, cid, ignoreWarning) => { + expect(ignoreWarning).toBe('false'); + return EVENT_TRIGGER_OBS; + }); + profileService.get.and.returnValue(PROFILE_OBS); + await eventTriggerResolver.resolve(route); + }); + + it('should call profileNotifier.announceProfile with cachedProfile', async () => { + eventTriggerResolver['cachedProfile'] = PROFILE; + spyOn(profileNotifier, 'announceProfile'); + casesService.getEventTrigger.and.returnValue(EVENT_TRIGGER_OBS); + await eventTriggerResolver.resolve(route); + expect(profileNotifier.announceProfile).toHaveBeenCalledWith(PROFILE); + }); + + it('should call profileNotifier.announceProfile after profileService.get', async () => { + eventTriggerResolver['cachedProfile'] = undefined; + spyOn(profileNotifier, 'announceProfile'); + profileService.get.and.returnValue(of(PROFILE)); + casesService.getEventTrigger.and.returnValue(EVENT_TRIGGER_OBS); + await eventTriggerResolver.resolve(route); + expect(profileNotifier.announceProfile).toHaveBeenCalledWith(PROFILE); + }); + + it('should handle error in getAndCacheEventTrigger and propagate error', async () => { + casesService.getEventTrigger.and.returnValue(throwError(ERROR)); + profileService.get.and.returnValue(PROFILE_OBS); + spyOn(errorNotifier, 'announceError'); + try { + await eventTriggerResolver.resolve(route); + fail('Should throw'); + } catch (err) { + expect(alertService.setPreserveAlerts).toHaveBeenCalledWith(true); + expect(alertService.error).toHaveBeenCalledWith(ERROR.message); + expect(errorNotifier.announceError).toHaveBeenCalledWith(jasmine.objectContaining({ message: ERROR.message })); + expect(router.navigate).toHaveBeenCalled(); + } + }); }); diff --git a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts index c6e894faf7..a6a83dbd18 100644 --- a/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts +++ b/projects/ccd-case-ui-toolkit/src/lib/shared/components/case-viewer/services/event-trigger.resolver.ts @@ -10,7 +10,7 @@ import { ProfileService } from '../../../services/profile/profile.service'; import { CasesService } from '../../case-editor/services/cases.service'; import { AbstractAppConfig } from '../../../../app.config'; import { ErrorNotifierService } from '../../../services/error/error-notifier.service'; -import { LoadingService } from '../../../services'; +import { LoadingService, SessionStorageService } from '../../../services'; @Injectable() export class EventTriggerResolver implements Resolve { @@ -28,10 +28,44 @@ export class EventTriggerResolver implements Resolve { private router: Router, private appConfig: AbstractAppConfig, private errorNotifier: ErrorNotifierService, - private readonly loadingService: LoadingService + private readonly loadingService: LoadingService, + private readonly sessionStorageService: SessionStorageService, ) {} public resolve(route: ActivatedRouteSnapshot): Promise { + const jurisdiction = route.parent?.paramMap.get('jurisdiction') || route.paramMap.get('jurisdiction'); + const caseType = route.parent?.paramMap.get('caseType') || route.paramMap.get('caseType'); + const eventTriggerId = route.paramMap.get(EventTriggerResolver.PARAM_EVENT_ID); + const cid = route.paramMap.get(EventTriggerResolver.PARAM_CASE_ID); + const query = route.queryParams; + + // If jurisdiction or caseType are missing, redirect to correct URL + if (!jurisdiction || !caseType) { + const caseInfo = JSON.parse(this.sessionStorageService.getItem('caseInfo') || '{}'); + const jurisdictionId = caseInfo?.jurisdiction; + const caseTypeId = caseInfo?.caseType; + const caseId = caseInfo?.caseId; + if (!jurisdictionId || !caseTypeId || !caseId || (caseId !== cid)) { + this.alertService.error({ phrase: 'Cannot determine jurisdiction and case type' }); + this.router.navigate([this.router.url]); + return Promise.resolve(null); + } + + this.router.navigate([ + '/cases/case-details', + jurisdictionId, + caseTypeId, + cid, + 'trigger', + eventTriggerId + ], { + queryParams: { + ...query + } + }); + return Promise.resolve(null); + } + if (this.isRootTriggerEventRoute(route)) { return this.getAndCacheEventTrigger(route); } @@ -55,6 +89,7 @@ export class EventTriggerResolver implements Resolve { // tslint:disable-next-line: prefer-const let caseTypeId: string; const jurisdiction = route.parent.paramMap.get('jurisdiction'); + const caseType = route.parent.paramMap.get('caseType'); const eventTriggerId = route.paramMap.get(EventTriggerResolver.PARAM_EVENT_ID); let ignoreWarning = route.queryParamMap.get(EventTriggerResolver.IGNORE_WARNING); if (-1 === EventTriggerResolver.IGNORE_WARNING_VALUES.indexOf(ignoreWarning)) { @@ -79,8 +114,7 @@ export class EventTriggerResolver implements Resolve { this.alertService.setPreserveAlerts(true); this.alertService.error(error.message); this.errorNotifier.announceError(error); - caseTypeId = route.parent.paramMap.get('caseType'); - this.router.navigate([`/cases/case-details/${jurisdiction}/${caseTypeId}/${cid}/tasks`]); + this.router.navigate([`/cases/case-details/${jurisdiction}/${caseType}/${cid}/tasks`]); return throwError(error); }) ).toPromise();