From afbfca519eb52a274d6bceaa953d4c02fc6e9335 Mon Sep 17 00:00:00 2001 From: Felipe Barreta Date: Thu, 13 Mar 2025 15:29:34 -0700 Subject: [PATCH 1/2] ALCS-2562 Frontend implementation --- .../release-dialog.component.html | 86 +++++++++++-------- .../release-dialog.component.scss | 62 +++++++++++++ .../release-dialog.component.ts | 1 + 3 files changed, 114 insertions(+), 35 deletions(-) diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html index 501fef639f..cca2ea9c86 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html @@ -2,6 +2,57 @@

Confirm Release Decision

+
+
Send Email (with decision document)
+
+ +
+
+
+
+ info Warning:   Email will not be sent +
+
+
+
+ Email will be sent to Primary Contact and Local/First Nation Government + No auto-emails will be sent +
+
+
+ CC additional recipients on decision release email (optional): +
+ + + + {{ email }} + + + + + + warning Please type a valid email address +
+

Upon releasing the decision:

Visibility: Applicant, Local/First Nation Government, and Public
@@ -16,41 +67,6 @@

Confirm Release Decision

[type]="cancelledStatus" >
-
- Email (with decision document) sent to: - Primary Contact and Local/First Nation Government - No auto-emails will be sent -
- -
-
- CC additional recipients on decision release email (optional): -
- - - - {{ email }} - - - - - - warning Please type a valid email address
diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.scss b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.scss index 9ce4ef0975..adc6f47d0b 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.scss +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.scss @@ -20,4 +20,66 @@ .mat-mdc-form-field-infix { display: flex; } + .toggle { + mat-label { + margin-right: 8px; + } + + & .mdc-form-field { + display: flex; + } + + & .mdc-label { + font-size: 16px; + padding-left: 12px; + } + + & .mat-mdc-slide-toggle .mdc-form-field { + color: colors.$grey; + } + + & .mat-mdc-slide-toggle-checked .mdc-form-field { + color: colors.$black; + + .mdc-label { + font-weight: 700 !important; + } + } + } +} + +.toggle-label { + font-weight: 700; +} + +.toggle { + display: flex; + gap: 4px; + color: colors.$black; + font-weight: 700; + margin-left: 14px; + margin-top: 6px; +} + +.row { + display: flex; + margin: 24px 0; + align-items: flex-start; +} + +.warning { + padding: 16px; + font-size: 14px; + background-color: rgba(colors.$field-warning-bg-color, 0.5); + border-radius: 8px; + display: flex; + align-items: center; + color: colors.$dark-contrast-text; + margin-top: 18px; + margin-bottom: 18px; + + mat-icon { + color: colors.$dark-contrast-text; + margin-right: 16px; + } } diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.ts index 903e16c279..8f2478a4a1 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.ts +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.ts @@ -23,6 +23,7 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { firstDecision = false; releasedStatus: ApplicationSubmissionStatusPill | undefined; cancelledStatus: ApplicationSubmissionStatusPill | undefined; + sendEmail = true; readonly separatorKeysCodes = [ENTER, COMMA, SPACE] as const; emails: string[] = []; From c3337c3a80042cadadf05c9e1f6c1913cf2ad833 Mon Sep 17 00:00:00 2001 From: Felipe Barreta Date: Fri, 14 Mar 2025 13:44:29 -0700 Subject: [PATCH 2/2] ALCS-2562 Backend and NOI implementation --- .../decision-input-v2.component.ts | 16 ++-- .../release-dialog.component.html | 2 +- .../release-dialog.component.ts | 1 + .../decision-input-v2.component.ts | 15 ++-- .../release-dialog.component.html | 87 +++++++++++-------- .../release-dialog.component.scss | 62 +++++++++++++ .../release-dialog.component.ts | 2 + .../application-decision-v2.dto.ts | 1 + .../notice-of-intent-decision.dto.ts | 1 + .../application-decision-v2.service.ts | 2 +- .../application-decision.dto.ts | 4 + .../notice-of-intent-decision-v2.service.ts | 2 +- .../notice-of-intent-decision.dto.ts | 4 + 13 files changed, 145 insertions(+), 54 deletions(-) diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-input-v2.component.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-input-v2.component.ts index 92e0691d31..2a52bed535 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-input-v2.component.ts +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-input-v2.component.ts @@ -373,11 +373,11 @@ export class DecisionInputV2Component implements OnInit, OnDestroy { this.form.controls['criterionModification'].updateValueAndValidity(); } - async onSubmit(isStayOnPage: boolean = false, isDraft: boolean = true, ccEmails: string[] = []) { + async onSubmit(isStayOnPage: boolean = false, isDraft: boolean = true, ccEmails: string[] = [], sendEmail: boolean = true) { this.isLoading = true; try { - await this.saveDecision(isDraft, ccEmails); + await this.saveDecision(isDraft, ccEmails, sendEmail); } finally { if (!isStayOnPage) { this.onCancel(); @@ -389,9 +389,8 @@ export class DecisionInputV2Component implements OnInit, OnDestroy { } } - async saveDecision(isDraft: boolean = true, ccEmails: string[] = []) { - const data = this.mapDecisionDataForSave(isDraft, ccEmails); - + async saveDecision(isDraft: boolean = true, ccEmails: string[] = [], sendEmail: boolean = true) { + const data = this.mapDecisionDataForSave(isDraft, ccEmails, sendEmail); if (this.uuid) { await this.decisionService.update(this.uuid, data); } else { @@ -403,7 +402,7 @@ export class DecisionInputV2Component implements OnInit, OnDestroy { } } - private mapDecisionDataForSave(isDraft: boolean, ccEmails: string[]) { + private mapDecisionDataForSave(isDraft: boolean, ccEmails: string[], sendEmail: boolean = true) { const { date, outcome, @@ -449,6 +448,7 @@ export class DecisionInputV2Component implements OnInit, OnDestroy { decisionComponents: this.components, conditions: this.conditionUpdates, ccEmails, + sendEmail, }; if (ceoCriterion && ceoCriterion === CeoCriterion.MODIFICATION) { data.isTimeExtension = criterionModification?.includes('isTimeExtension'); @@ -592,9 +592,9 @@ export class DecisionInputV2Component implements OnInit, OnDestroy { }, }) .afterClosed() - .subscribe(async (result: { confirmed: boolean; ccEmails: string[] }) => { + .subscribe(async (result: { confirmed: boolean; ccEmails: string[], sendEmail: boolean }) => { if (result.confirmed) { - await this.onSubmit(false, false, result.ccEmails); + await this.onSubmit(false, false, result.ccEmails, result.sendEmail); await this.applicationService.loadApplication(this.fileNumber); } }); diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html index cca2ea9c86..fc14e966fe 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.html @@ -2,7 +2,7 @@

Confirm Release Decision

-
+
Send Email (with decision document)
{ + .subscribe(async (res: { confirmed: boolean; ccEmails: string[], sendEmail: boolean }) => { if (res.confirmed) { - await this.onSubmit(false, false, res.ccEmails); + await this.onSubmit(false, false, res.ccEmails, res.sendEmail); await this.noticeOfIntentDetailService.load(this.fileNumber); } }); diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.html b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.html index 0319e5e952..fc14e966fe 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.html @@ -2,6 +2,57 @@

Confirm Release Decision

+
+
Send Email (with decision document)
+
+ +
+
+
+
+ info Warning:   Email will not be sent +
+
+
+
+ Email will be sent to Primary Contact and Local/First Nation Government + No auto-emails will be sent +
+
+
+ CC additional recipients on decision release email (optional): +
+ + + + {{ email }} + + + + + + warning Please type a valid email address +
+

Upon releasing the decision:

Visibility: Applicant, Local/First Nation Government, and Public
@@ -16,42 +67,6 @@

Confirm Release Decision

[type]="cancelledStatus" >
-
- Email (with decision document) sent to: - Primary Contact and Local/First Nation Government - No auto-emails will be sent -
-
-
-
- CC additional recipients on decision release email (optional): -
- - - - {{ email }} - - - - - - warning Please type a valid email address
diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.scss b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.scss index 9ce4ef0975..adc6f47d0b 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.scss +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.scss @@ -20,4 +20,66 @@ .mat-mdc-form-field-infix { display: flex; } + .toggle { + mat-label { + margin-right: 8px; + } + + & .mdc-form-field { + display: flex; + } + + & .mdc-label { + font-size: 16px; + padding-left: 12px; + } + + & .mat-mdc-slide-toggle .mdc-form-field { + color: colors.$grey; + } + + & .mat-mdc-slide-toggle-checked .mdc-form-field { + color: colors.$black; + + .mdc-label { + font-weight: 700 !important; + } + } + } +} + +.toggle-label { + font-weight: 700; +} + +.toggle { + display: flex; + gap: 4px; + color: colors.$black; + font-weight: 700; + margin-left: 14px; + margin-top: 6px; +} + +.row { + display: flex; + margin: 24px 0; + align-items: flex-start; +} + +.warning { + padding: 16px; + font-size: 14px; + background-color: rgba(colors.$field-warning-bg-color, 0.5); + border-radius: 8px; + display: flex; + align-items: center; + color: colors.$dark-contrast-text; + margin-top: 18px; + margin-bottom: 18px; + + mat-icon { + color: colors.$dark-contrast-text; + margin-right: 16px; + } } diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.ts index 272c3dc348..003539b86f 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.ts @@ -22,6 +22,7 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { firstDecision = false; releasedStatus: ApplicationSubmissionStatusPill | undefined; cancelledStatus: ApplicationSubmissionStatusPill | undefined; + sendEmail = true; readonly separatorKeysCodes = [ENTER, COMMA, SPACE] as const; emails: string[] = []; @@ -57,6 +58,7 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { this.matDialogRef.close({ confirmed: true, ccEmails: this.emails, + sendEmail: this.sendEmail, }); } diff --git a/alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-v2.dto.ts b/alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-v2.dto.ts index ffc0d8c9e0..c1cce7d163 100644 --- a/alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-v2.dto.ts +++ b/alcs-frontend/src/app/services/application/decision/application-decision-v2/application-decision-v2.dto.ts @@ -38,6 +38,7 @@ export interface UpdateApplicationDecisionDto { flaggedByUuid?: string | null; flagEditedByUuid?: string | null; flagEditedAt?: number | null; + sendEmail?: boolean; } export interface CreateApplicationDecisionDto extends UpdateApplicationDecisionDto { diff --git a/alcs-frontend/src/app/services/notice-of-intent/decision-v2/notice-of-intent-decision.dto.ts b/alcs-frontend/src/app/services/notice-of-intent/decision-v2/notice-of-intent-decision.dto.ts index df551592ee..f85052ff87 100644 --- a/alcs-frontend/src/app/services/notice-of-intent/decision-v2/notice-of-intent-decision.dto.ts +++ b/alcs-frontend/src/app/services/notice-of-intent/decision-v2/notice-of-intent-decision.dto.ts @@ -31,6 +31,7 @@ export interface UpdateNoticeOfIntentDecisionDto { flaggedByUuid?: string | null; flagEditedByUuid?: string | null; flagEditedAt?: number | null; + sendEmail?: boolean; } export interface CreateNoticeOfIntentDecisionDto extends UpdateNoticeOfIntentDecisionDto { diff --git a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service.ts b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service.ts index 152f1ee417..6c23646516 100644 --- a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service.ts +++ b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision-v2.service.ts @@ -286,7 +286,7 @@ export class ApplicationDecisionV2Service { existingDecision.rescindedComment = updateDto.rescindedComment; existingDecision.wasReleased = existingDecision.wasReleased || !updateDto.isDraft; existingDecision.linkedResolutionOutcomeCode = updateDto.linkedResolutionOutcomeCode; - existingDecision.emailSent = updateDto.emailSent; + existingDecision.emailSent = updateDto.sendEmail ? updateDto.emailSent : new Date(); existingDecision.ccEmails = filterUndefined(updateDto.ccEmails, existingDecision.ccEmails); existingDecision.isFlagged = updateDto.isFlagged; existingDecision.reasonFlagged = updateDto.reasonFlagged; diff --git a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision.dto.ts b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision.dto.ts index 91851478f8..65f3d3dfb8 100644 --- a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision.dto.ts +++ b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/application-decision.dto.ts @@ -132,6 +132,10 @@ export class UpdateApplicationDecisionDto { @IsOptional() @IsNumber() flagEditedAt?: number | null; + + @IsOptional() + @IsBoolean() + sendEmail?: boolean; } export class CreateApplicationDecisionDto extends UpdateApplicationDecisionDto { diff --git a/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision-v2/notice-of-intent-decision-v2.service.ts b/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision-v2/notice-of-intent-decision-v2.service.ts index a155a3d88f..f64cdea52b 100644 --- a/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision-v2/notice-of-intent-decision-v2.service.ts +++ b/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision-v2/notice-of-intent-decision-v2.service.ts @@ -214,7 +214,7 @@ export class NoticeOfIntentDecisionV2Service { existingDecision.rescindedDate = formatIncomingDate(updateDto.rescindedDate); existingDecision.rescindedComment = updateDto.rescindedComment; existingDecision.wasReleased = existingDecision.wasReleased || !updateDto.isDraft; - existingDecision.emailSent = updateDto.emailSent; + existingDecision.emailSent = updateDto.sendEmail ? updateDto.emailSent : new Date(); existingDecision.ccEmails = updateDto.ccEmails; existingDecision.isFlagged = updateDto.isFlagged; existingDecision.reasonFlagged = updateDto.reasonFlagged; diff --git a/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision.dto.ts b/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision.dto.ts index 9a71143099..e97d670b4c 100644 --- a/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision.dto.ts +++ b/services/apps/alcs/src/alcs/notice-of-intent-decision/notice-of-intent-decision.dto.ts @@ -106,6 +106,10 @@ export class UpdateNoticeOfIntentDecisionDto { @IsOptional() @IsNumber() flagEditedAt?: number | null; + + @IsOptional() + @IsBoolean() + sendEmail?: boolean; } export class CreateNoticeOfIntentDecisionDto extends UpdateNoticeOfIntentDecisionDto {