diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index a5423f7bb8..e6e316f248 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -8,6 +8,16 @@ on: options: - https://alcs-dev-portal.apps.silver.devops.gov.bc.ca - https://alcs-test-portal.apps.silver.devops.gov.bc.ca + alcsBaseUrl: + type: choice + description: ALCS Base URL + options: + - https://alcs-dev.apps.silver.devops.gov.bc.ca + - https://alcs-test.apps.silver.devops.gov.bc.ca + branch: + type: string + description: 'Branch to checkout' + default: 'develop' schedule: # 5:23 am daily - cron: "23 5 * * *" @@ -19,7 +29,7 @@ jobs: - uses: actions/checkout@v4 with: # This does not need to align with URL - ref: develop + ref: ${{ inputs.branch || 'develop' }} - uses: actions/setup-node@v4 - name: Install dependencies working-directory: ./e2e @@ -32,6 +42,7 @@ jobs: env: # Default to dev PORTAL_BASE_URL: ${{ inputs.portalBaseUrl || 'https://alcs-dev-portal.apps.silver.devops.gov.bc.ca' }} + ALCS_BASE_URL: ${{ inputs.alcsBaseUrl || 'https://alcs-dev.apps.silver.devops.gov.bc.ca' }} BCEID_BASIC_USERNAME: ${{ secrets.BCEID_BASIC_USERNAME }} BCEID_BASIC_PASSWORD: ${{ secrets.BCEID_BASIC_PASSWORD }} run: npx playwright test diff --git a/alcs-frontend/package-lock.json b/alcs-frontend/package-lock.json index 7dedc4380f..9fc888dd33 100644 --- a/alcs-frontend/package-lock.json +++ b/alcs-frontend/package-lock.json @@ -24,6 +24,7 @@ "@bcgov/bc-sans": "^2.1.0", "@ng-matero/extensions": "^17.2.0", "@ng-select/ng-option-highlight": "^12.0.6", + "@types/validator": "^13.12.0", "angular-mentions": "^1.5.0", "jwt-decode": "^4.0.0", "moment": "^2.30.1", @@ -32,6 +33,7 @@ "rxjs": "~7.8.1", "source-map-support": "^0.5.21", "tslib": "^2.6.2", + "validator": "^13.12.0", "zone.js": "~0.14.4" }, "devDependencies": { @@ -6177,6 +6179,11 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, + "node_modules/@types/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -7620,12 +7627,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -8981,9 +8988,9 @@ "dev": true }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -9921,9 +9928,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -17678,6 +17685,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -18692,9 +18707,9 @@ } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/alcs-frontend/package.json b/alcs-frontend/package.json index 65ac923cc5..028226ffa2 100644 --- a/alcs-frontend/package.json +++ b/alcs-frontend/package.json @@ -30,6 +30,7 @@ "@bcgov/bc-sans": "^2.1.0", "@ng-matero/extensions": "^17.2.0", "@ng-select/ng-option-highlight": "^12.0.6", + "@types/validator": "^13.12.0", "angular-mentions": "^1.5.0", "jwt-decode": "^4.0.0", "moment": "^2.30.1", @@ -38,6 +39,7 @@ "rxjs": "~7.8.1", "source-map-support": "^0.5.21", "tslib": "^2.6.2", + "validator": "^13.12.0", "zone.js": "~0.14.4" }, "devDependencies": { diff --git a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.html b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.html index c994769009..5b266119a9 100644 --- a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.html +++ b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.html @@ -60,8 +60,10 @@

{{ title }} Government

[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addEmail($event)" + [formControl]="email" /> + warning Please type a valid email address
diff --git a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.scss b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.scss index 445a5adcb7..4b8280bfe5 100644 --- a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.scss +++ b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.scss @@ -18,4 +18,10 @@ .mat-mdc-form-field-infix { display: flex; } + + mat-error { + display: flex; + font-size: 15px; + font-weight: bold; + } } diff --git a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.ts b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.ts index bc187645e8..a7494c4a7f 100644 --- a/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.ts +++ b/alcs-frontend/src/app/features/admin/local-government/dialog/local-government-dialog.component.ts @@ -7,6 +7,8 @@ import { LocalGovernmentDto } from '../../../../services/admin-local-government/ import { AdminLocalGovernmentService } from '../../../../services/admin-local-government/admin-local-government.service'; import { ApplicationRegionDto } from '../../../../services/application/application-code.dto'; import { ApplicationService } from '../../../../services/application/application.service'; +import { FormControl } from '@angular/forms'; +import { strictEmailValidator } from '../../../../shared/validators/email-validator'; @Component({ selector: 'app-admin-local-government-dialog', @@ -29,6 +31,8 @@ export class LocalGovernmentDialogComponent implements OnInit, OnDestroy { }; regions: ApplicationRegionDto[] = []; + email = new FormControl(null, [strictEmailValidator]); + isLoading = false; constructor( @@ -48,7 +52,7 @@ export class LocalGovernmentDialogComponent implements OnInit, OnDestroy { } ngOnInit(): void { - if (this.data) { + if (Object.keys(this.data).length !== 0) { this.model = { ...this.data, isFirstNation: this.data.isFirstNation ? 'true' : 'false', @@ -100,6 +104,10 @@ export class LocalGovernmentDialogComponent implements OnInit, OnDestroy { } addEmail(event: MatChipInputEvent): void { + if (this.email.invalid) { + return; + } + const value = (event.value || '').trim(); if (value) { this.model.emails.push(value); diff --git a/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.html b/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.html index b0711c2180..a8c1921caf 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.html @@ -1,20 +1,17 @@ -
-
-
-
Comment for Applicant
- {{ submission.returnedComment }} -
- - -
-
- +
+
+
Comment for Applicant
+ {{ submission.returnedComment }}
+ +
+
+
diff --git a/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.scss b/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.scss index b7d0259c4e..74a3106748 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.scss +++ b/alcs-frontend/src/app/features/application/applicant-info/applicant-info.component.scss @@ -1,11 +1,5 @@ @use '../../../../styles/colors'; -.applicant-info { - & > div { - margin: 12px 0; - } -} - .subheading1 { margin-bottom: 4px !important; } diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.html b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.html index a5e9cb754d..c0db79316e 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.html @@ -1,3 +1,6 @@ +
+

Applicant Info

+
@@ -9,7 +12,7 @@
-

Other Owned Parcels

+

Other Owned Parcels

Do any of the land owners added previously own or lease other parcels that might inform this application process? @@ -39,7 +42,7 @@

Other Owned Parcels

-

Primary Contact Information

+

Primary Contact Information

Type
@@ -93,10 +96,10 @@

Primary Contact Information

-

Land Use

+

Land Use

-

Land Use of Parcel(s) under Application

+
Land Use of Parcel(s) under Application
Describe all agriculture that currently takes place on the parcel(s).
@@ -111,7 +114,7 @@

Land Use of Parcel(s) under Application

{{ submission.parcelsNonAgricultureUseDescription }}
-

Land Use of Adjacent Parcels

+
Land Use of Adjacent Parcels
@@ -154,7 +157,7 @@

Land Use of Adjacent Parcels

-

Proposal

+

Proposal

Proposal
-

Optional Documents

+

Optional Documents

File Name
diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.scss b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.scss index 21eb0d060c..9d7f6babea 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.scss +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/application-details.component.scss @@ -68,7 +68,6 @@ .adjacent-parcels { display: grid; grid-template-columns: 1fr 1fr 2fr; - overflow-x: auto; grid-column-gap: 36px; grid-row-gap: 12px; @@ -118,3 +117,7 @@ .edit-section { margin-top: -40px; } + +.header { + margin-bottom: 42px; +} diff --git a/alcs-frontend/src/app/features/application/applicant-info/application-details/parcel/parcel.component.html b/alcs-frontend/src/app/features/application/applicant-info/application-details/parcel/parcel.component.html index 20ac97e32c..b51ba3b1a8 100644 --- a/alcs-frontend/src/app/features/application/applicant-info/application-details/parcel/parcel.component.html +++ b/alcs-frontend/src/app/features/application/applicant-info/application-details/parcel/parcel.component.html @@ -1,6 +1,6 @@ -

+

{{ pageTitle }} -

+
@@ -9,7 +9,7 @@

-

Parcel #{{ parcelInd + 1 }}

+
Parcel #{{ parcelInd + 1 }}
Ownership Type
diff --git a/alcs-frontend/src/app/features/application/application.component.html b/alcs-frontend/src/app/features/application/application.component.html index b2f12fbb41..c3ebc88276 100644 --- a/alcs-frontend/src/app/features/application/application.component.html +++ b/alcs-frontend/src/app/features/application/application.component.html @@ -6,6 +6,8 @@ [reconsiderations]="reconsiderations" [showStatus]="true" [submissionStatusService]="applicationStatusService" + [applicationDetailService]="applicationDetailService" + [applicationSubmissionService]="applicationSubmissionService" days="Business Days" heading="Application" > diff --git a/alcs-frontend/src/app/features/application/application.component.ts b/alcs-frontend/src/app/features/application/application.component.ts index 5abd7f08f5..8823637cec 100644 --- a/alcs-frontend/src/app/features/application/application.component.ts +++ b/alcs-frontend/src/app/features/application/application.component.ts @@ -188,8 +188,8 @@ export class ApplicationComponent implements OnInit, OnDestroy { showSubmittedToLfngMenuItems = false; constructor( - private applicationDetailService: ApplicationDetailService, - private applicationSubmissionService: ApplicationSubmissionService, + public applicationDetailService: ApplicationDetailService, + public applicationSubmissionService: ApplicationSubmissionService, private reconsiderationService: ApplicationReconsiderationService, private modificationService: ApplicationModificationService, private route: ActivatedRoute, diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.html b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.html index af02592cda..03f29be59f 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.html +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.html @@ -8,5 +8,6 @@ [value]="component.alrArea?.toString()" (save)="onSaveAlrArea($event)" [decimals]="5" + [nonZeroEmptyValidation]="nonZeroEmptyValidation" >
diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.ts index 3bbe0074cf..f4f6108f4c 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.ts +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-component/basic/basic.component.ts @@ -9,6 +9,7 @@ import { ApplicationDecisionComponentDto } from '../../../../../../services/appl export class BasicComponent { @Input() component!: ApplicationDecisionComponentDto; @Input() fillRow = false; + @Input() nonZeroEmptyValidation = false; @Output() saveAlrArea = new EventEmitter(); constructor() {} diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.html b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.html index f7acde72fd..ced49f66f9 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.html +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.html @@ -24,7 +24,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.ts index dbf5b30e51..1435b8b0ef 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.ts +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-documents/decision-documents.component.ts @@ -9,6 +9,7 @@ import { ApplicationDecisionDocumentDto } from '../../../../../services/applicat import { ToastService } from '../../../../../services/toast/toast.service'; import { ConfirmationDialogService } from '../../../../../shared/confirmation-dialog/confirmation-dialog.service'; import { DecisionDocumentUploadDialogComponent } from '../decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component'; +import { FILE_NAME_TRUNCATE_LENGTH } from '../../../../../shared/constants'; @Component({ selector: 'app-decision-documents', @@ -32,6 +33,8 @@ export class DecisionDocumentsComponent implements OnInit, OnDestroy { dataSource: MatTableDataSource = new MatTableDataSource(); private fileId = ''; + + readonly fileNameTruncLen = FILE_NAME_TRUNCATE_LENGTH; constructor( private decisionService: ApplicationDecisionV2Service, diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts index f80aa2d470..42fa785246 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts @@ -19,7 +19,7 @@ import { AG_CAP_OPTIONS, AG_CAP_SOURCE_OPTIONS } from '../../../../../../../shar import { formatDateForApi } from '../../../../../../../shared/utils/api-date-formatter'; import { SubdInputComponent } from './subd-input/subd-input.component'; -const MIN_SOIL_FIELDS = 0.01; +const MIN_SOIL_FIELDS = 0.00001; @Component({ selector: 'app-decision-component', @@ -310,22 +310,22 @@ export class DecisionComponentComponent implements OnInit { private getPofoDataChange(): PofoDecisionComponentDto { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, - soilFillTypeToPlace: this.fillTypeToPlace.value ?? null, - soilToPlaceArea: this.areaToPlace.value ?? null, - soilToPlaceVolume: this.volumeToPlace.value ?? null, - soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ?? null, - soilToPlaceAverageDepth: this.averageDepthToPlace.value ?? null, + soilFillTypeToPlace: this.fillTypeToPlace.value ? this.fillTypeToPlace.value : null, + soilToPlaceArea: this.areaToPlace.value ? this.areaToPlace.value : null, + soilToPlaceVolume: this.volumeToPlace.value ? this.volumeToPlace.value : null, + soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ? this.maximumDepthToPlace.value : null, + soilToPlaceAverageDepth: this.averageDepthToPlace.value ? this.averageDepthToPlace.value : null, }; } private getRosoDataChange(): RosoDecisionComponentDto { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, - soilTypeRemoved: this.soilTypeRemoved.value ?? null, - soilToRemoveArea: this.areaToRemove.value ?? null, - soilToRemoveVolume: this.volumeToRemove.value ?? null, - soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ?? null, - soilToRemoveAverageDepth: this.averageDepthToRemove.value ?? null, + soilTypeRemoved: this.soilTypeRemoved.value ? this.soilTypeRemoved.value : null, + soilToRemoveArea: this.areaToRemove.value ? this.areaToRemove.value : null, + soilToRemoveVolume: this.volumeToRemove.value ? this.volumeToRemove.value : null, + soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ? this.maximumDepthToRemove.value : null, + soilToRemoveAverageDepth: this.averageDepthToRemove.value ? this.averageDepthToRemove.value : null, }; } @@ -333,16 +333,16 @@ export class DecisionComponentComponent implements OnInit { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, endDate2: this.endDate2.value ? formatDateForApi(this.endDate2.value) : null, - soilTypeRemoved: this.soilTypeRemoved.value ?? null, - soilToRemoveArea: this.areaToRemove.value ?? null, - soilToRemoveVolume: this.volumeToRemove.value ?? null, - soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ?? null, - soilToRemoveAverageDepth: this.averageDepthToRemove.value ?? null, - soilFillTypeToPlace: this.fillTypeToPlace.value ?? null, - soilToPlaceArea: this.areaToPlace.value ?? null, - soilToPlaceVolume: this.volumeToPlace.value ?? null, - soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ?? null, - soilToPlaceAverageDepth: this.averageDepthToPlace.value ?? null, + soilTypeRemoved: this.soilTypeRemoved.value ? this.soilTypeRemoved.value : null, + soilToRemoveArea: this.areaToRemove.value ? this.areaToRemove.value : null, + soilToRemoveVolume: this.volumeToRemove.value ? this.volumeToRemove.value : null, + soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ? this.maximumDepthToRemove.value : null, + soilToRemoveAverageDepth: this.averageDepthToRemove.value ? this.averageDepthToRemove.value : null, + soilFillTypeToPlace: this.fillTypeToPlace.value ? this.fillTypeToPlace.value : null, + soilToPlaceArea: this.areaToPlace.value ? this.areaToPlace.value : null, + soilToPlaceVolume: this.volumeToPlace.value ? this.volumeToPlace.value : null, + soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ? this.maximumDepthToPlace.value : null, + soilToPlaceAverageDepth: this.averageDepthToPlace.value ? this.averageDepthToPlace.value : null, }; } @@ -355,7 +355,11 @@ export class DecisionComponentComponent implements OnInit { } private getSubdDataChange(): SubdDecisionComponentDto { - const update = this.subdApprovedLots.value?.map((e) => ({ ...e }) as ProposedDecisionLotDto); + const update = this.subdApprovedLots.value?.map((e) => ({ + ...e, + size: e.size ? e.size : null, + alrArea: e.alrArea ? e.alrArea : null + }) as ProposedDecisionLotDto); return { lots: update ?? undefined, expiryDate: this.expiryDate.value ? formatDateForApi(this.expiryDate.value) : null, diff --git a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/expiry-date-input/expiry-date-input.component.html b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/expiry-date-input/expiry-date-input.component.html index 418d69ca45..4efb3b5dcc 100644 --- a/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/expiry-date-input/expiry-date-input.component.html +++ b/alcs-frontend/src/app/features/application/decision/decision-v2/decision-input/decision-components/decision-component/expiry-date-input/expiry-date-input.component.html @@ -5,7 +5,7 @@ {{ component.applicationDecisionComponentType?.label }}

[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -199,6 +200,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -211,6 +213,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -223,6 +226,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -235,6 +239,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -247,6 +252,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -259,6 +265,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -274,6 +281,7 @@
{{ component.applicationDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > 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 2c930e9522..501fef639f 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 @@ -47,8 +47,10 @@

Confirm Release Decision

[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addEmail($event)" + [formControl]="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.ts b/alcs-frontend/src/app/features/application/decision/decision-v2/release-dialog/release-dialog.component.ts index aaf2899b91..903e16c279 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 @@ -8,6 +8,8 @@ import { SUBMISSION_STATUS } from '../../../../../services/application/applicati import { ApplicationDecisionV2Service } from '../../../../../services/application/decision/application-decision-v2/application-decision-v2.service'; import { NOI_SUBMISSION_STATUS } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; import { ApplicationSubmissionStatusPill } from '../../../../../shared/application-submission-status-type-pill/application-submission-status-type-pill.component'; +import { FormControl } from '@angular/forms'; +import { strictEmailValidator } from '../../../../../shared/validators/email-validator'; @Component({ selector: 'app-release-dialog', @@ -25,6 +27,8 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { readonly separatorKeysCodes = [ENTER, COMMA, SPACE] as const; emails: string[] = []; + email = new FormControl(null, [strictEmailValidator]); + constructor( private decisionService: ApplicationDecisionV2Service, private applicationSubmissionStatusService: ApplicationSubmissionStatusService, @@ -100,6 +104,10 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { } addEmail(event: MatChipInputEvent): void { + if (this.email.invalid) { + return; + } + const value = (event.value || '').trim(); if (value) { this.emails.push(value); diff --git a/alcs-frontend/src/app/features/application/documents/documents.component.html b/alcs-frontend/src/app/features/application/documents/documents.component.html index dcb0fef78a..ac28b6b961 100644 --- a/alcs-frontend/src/app/features/application/documents/documents.component.html +++ b/alcs-frontend/src/app/features/application/documents/documents.component.html @@ -13,7 +13,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + @@ -61,7 +66,7 @@

Documents

- Actions + Actions
- + {{ model.uuid ? 'Update' : 'Create' }} Information Reques > Waiting for additional information from applicant - + > + Other: - +
diff --git a/alcs-frontend/src/app/features/application/info-requests/info-request-dialog/info-request-dialog.component.scss b/alcs-frontend/src/app/features/application/info-requests/info-request-dialog/info-request-dialog.component.scss index 8ccfc63712..540e30f5c2 100644 --- a/alcs-frontend/src/app/features/application/info-requests/info-request-dialog/info-request-dialog.component.scss +++ b/alcs-frontend/src/app/features/application/info-requests/info-request-dialog/info-request-dialog.component.scss @@ -48,10 +48,16 @@ label { } } -.other-text { - border-bottom: 1px solid colors.$black; - padding-bottom: 4px; +.other-radio-button { + display: inline-block !important; +} + +.other-text.mat-mdc-input-element { + border-bottom: 1px solid colors.$black !important; margin-bottom: -5px; + margin-left: 10px; + width: 80%; + max-width: 90%; } :host::ng-deep { diff --git a/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.html b/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.html index 5a8b22094b..0c78b56765 100644 --- a/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.html +++ b/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.html @@ -17,7 +17,7 @@

L/FNG Info

- infoApplication not subjected to Local/First Nation Government Review. + infoApplication not subject to Local/First Nation Government Review.
infoPending Local/First Nation Government review. diff --git a/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.scss b/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.scss index a1cac5a45c..87b2570418 100644 --- a/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.scss +++ b/alcs-frontend/src/app/features/application/lfng-info/lfng-info.component.scss @@ -14,6 +14,7 @@ h4 { padding: 16px; display: flex; align-items: center; + margin-bottom: 24px; mat-icon { margin-right: 12px; diff --git a/alcs-frontend/src/app/features/board/board.component.scss b/alcs-frontend/src/app/features/board/board.component.scss index 5a49703177..eebc077058 100644 --- a/alcs-frontend/src/app/features/board/board.component.scss +++ b/alcs-frontend/src/app/features/board/board.component.scss @@ -9,11 +9,14 @@ .board-header { display: flex; + background-color: white; justify-content: space-between; align-items: center; padding: 24px 80px 12px 76px; position: sticky; left: 0; + top: 0; + z-index: 1000; } .board-content { diff --git a/alcs-frontend/src/app/features/board/dialogs/inquiry/create/create-inquiry-dialog.component.ts b/alcs-frontend/src/app/features/board/dialogs/inquiry/create/create-inquiry-dialog.component.ts index 5cc5abb3bd..f9c7bf8469 100644 --- a/alcs-frontend/src/app/features/board/dialogs/inquiry/create/create-inquiry-dialog.component.ts +++ b/alcs-frontend/src/app/features/board/dialogs/inquiry/create/create-inquiry-dialog.component.ts @@ -14,6 +14,7 @@ import { CardService } from '../../../../../services/card/card.service'; import { InquiryParcelCreateDto } from '../../../../../services/inquiry/inquiry-parcel/inquiry-parcel.dto'; import { CreateInquiryDto, InquiryTypeDto } from '../../../../../services/inquiry/inquiry.dto'; import { InquiryService } from '../../../../../services/inquiry/inquiry.service'; +import { strictEmailValidator } from '../../../../../shared/validators/email-validator'; @Component({ selector: 'app-create-inquiry', @@ -38,7 +39,7 @@ export class CreateInquiryDialogComponent implements OnInit, OnDestroy { lastName = new FormControl(null, []); organization = new FormControl(null, []); phone = new FormControl(null, []); - email = new FormControl(null, [Validators.email]); + email = new FormControl(null, [strictEmailValidator]); displayedColumns = ['index', 'address', 'pid', 'pin', 'actions']; parcels: InquiryParcelCreateDto[] = []; diff --git a/alcs-frontend/src/app/features/home/assigned/assigned-table/assigned-table.component.html b/alcs-frontend/src/app/features/home/assigned/assigned-table/assigned-table.component.html index dbd79a4959..3b10ba5976 100644 --- a/alcs-frontend/src/app/features/home/assigned/assigned-table/assigned-table.component.html +++ b/alcs-frontend/src/app/features/home/assigned/assigned-table/assigned-table.component.html @@ -16,6 +16,9 @@ Type + + - + diff --git a/alcs-frontend/src/app/features/home/subtask/subtask-table/subtask-table.component.html b/alcs-frontend/src/app/features/home/subtask/subtask-table/subtask-table.component.html index e623f740c6..353eca8f02 100644 --- a/alcs-frontend/src/app/features/home/subtask/subtask-table/subtask-table.component.html +++ b/alcs-frontend/src/app/features/home/subtask/subtask-table/subtask-table.component.html @@ -7,7 +7,7 @@ - Cards + Cards {{ element.title }} @@ -16,6 +16,9 @@ Type + + - + - Active Days + Active Days {{ element.activeDays ?? '-' }} @@ -46,12 +49,12 @@ - Workflow Stage + Workflow Stage - Assignee + Assignee input { margin-bottom: 8px; } + padding: 0 0 0 10px; + .ng-input { + padding: 0 0 0 10px; + } + &:hover { + background-color: colors.$grey-light !important; + } } + +::ng-deep ng-dropdown-panel { + padding: 8px 0 !important; + .ng-dropdown-panel-items .ng-option { + padding: 4px 16px !important; + } +} \ No newline at end of file diff --git a/alcs-frontend/src/app/features/inquiry/detail/details.component.html b/alcs-frontend/src/app/features/inquiry/detail/details.component.html index 9e4d05e71b..7d28f8d4cc 100644 --- a/alcs-frontend/src/app/features/inquiry/detail/details.component.html +++ b/alcs-frontend/src/app/features/inquiry/detail/details.component.html @@ -72,7 +72,11 @@
Inquirer
Email
- +
diff --git a/alcs-frontend/src/app/features/inquiry/documents/documents.component.html b/alcs-frontend/src/app/features/inquiry/documents/documents.component.html index caea7696a0..460be3ac0d 100644 --- a/alcs-frontend/src/app/features/inquiry/documents/documents.component.html +++ b/alcs-frontend/src/app/features/inquiry/documents/documents.component.html @@ -13,7 +13,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + @@ -28,7 +33,7 @@

Documents

- Actions + Actions
-

Optional Documents

+

Optional Documents

Type
diff --git a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/notice-of-intent-details.component.scss b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/notice-of-intent-details.component.scss index 1e5282d2c5..ee2b367418 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/notice-of-intent-details.component.scss +++ b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/notice-of-intent-details.component.scss @@ -79,7 +79,6 @@ .adjacent-parcels { display: grid; grid-template-columns: 1fr 1fr 2fr; - overflow-x: auto; grid-column-gap: 36px; grid-row-gap: 12px; @@ -129,3 +128,7 @@ .edit-section { margin-top: -40px; } + +.header { + margin-bottom: 42px; +} diff --git a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/parcel/parcel.component.html b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/parcel/parcel.component.html index 4c4afa8078..7e0e55bb20 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/parcel/parcel.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/applicant-info/notice-of-intent-details/parcel/parcel.component.html @@ -1,4 +1,4 @@ -

Notice of Intent Parcels

+

Notice of Intent Parcels

@@ -7,7 +7,7 @@

Notice of Intent Parcels

-

Parcel #{{ parcelInd + 1 }}

+
Parcel #{{ parcelInd + 1 }}
Ownership Type
diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.html b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.html index 40aae52ce4..eafdd464a2 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.html @@ -3,6 +3,7 @@
diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.ts index 3231e2c1e8..5a71f3ccb9 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-component/basic/basic.component.ts @@ -9,6 +9,7 @@ import { NoticeOfIntentDecisionComponentDto } from '../../../../../../services/n export class BasicComponent { @Input() component!: NoticeOfIntentDecisionComponentDto; @Input() fillRow = false; + @Input() nonZeroEmptyValidation = false; @Output() saveAlrArea = new EventEmitter(); constructor() {} diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.html b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.html index 4f628d2e0c..40a8cc8ee6 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.html @@ -25,7 +25,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.ts index fdf8582b9e..3bcbfb3485 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-documents/decision-documents.component.ts @@ -11,6 +11,7 @@ import { import { ToastService } from '../../../../../services/toast/toast.service'; import { ConfirmationDialogService } from '../../../../../shared/confirmation-dialog/confirmation-dialog.service'; import { DecisionDocumentUploadDialogComponent } from '../decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component'; +import { FILE_NAME_TRUNCATE_LENGTH } from '../../../../../shared/constants'; @Component({ selector: 'app-decision-documents', @@ -35,6 +36,8 @@ export class DecisionDocumentsComponent implements OnInit, OnDestroy { @ViewChild(MatSort) sort!: MatSort; dataSource = new MatTableDataSource(); + readonly fileNameTruncLen = FILE_NAME_TRUNCATE_LENGTH; + constructor( private decisionService: NoticeOfIntentDecisionV2Service, private dialog: MatDialog, diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts index c38252bbad..68f7aca6ab 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-components/decision-component/decision-component.component.ts @@ -186,21 +186,21 @@ export class DecisionComponentComponent implements OnInit { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, soilFillTypeToPlace: this.fillTypeToPlace.value ?? null, - soilToPlaceArea: this.areaToPlace.value ?? null, - soilToPlaceVolume: this.volumeToPlace.value ?? null, - soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ?? null, - soilToPlaceAverageDepth: this.averageDepthToPlace.value ?? null, + soilToPlaceArea: this.areaToPlace.value ? this.areaToPlace.value : null, + soilToPlaceVolume: this.volumeToPlace.value ? this.volumeToPlace.value: null, + soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ? this.maximumDepthToPlace.value : null, + soilToPlaceAverageDepth: this.averageDepthToPlace.value ? this.averageDepthToPlace.value : null, }; } private getRosoDataChange(): RosoDecisionComponentDto { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, - soilTypeRemoved: this.soilTypeRemoved.value ?? null, - soilToRemoveArea: this.areaToRemove.value ?? null, - soilToRemoveVolume: this.volumeToRemove.value ?? null, - soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ?? null, - soilToRemoveAverageDepth: this.averageDepthToRemove.value ?? null, + soilTypeRemoved: this.soilTypeRemoved.value ? this.soilTypeRemoved.value : null, + soilToRemoveArea: this.areaToRemove.value ? this.areaToRemove.value : null, + soilToRemoveVolume: this.volumeToRemove.value ? this.volumeToRemove.value : null, + soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ? this.maximumDepthToRemove.value : null, + soilToRemoveAverageDepth: this.averageDepthToRemove.value ? this.averageDepthToRemove.value : null, }; } @@ -208,16 +208,16 @@ export class DecisionComponentComponent implements OnInit { return { endDate: this.endDate.value ? formatDateForApi(this.endDate.value) : null, endDate2: this.endDate2.value ? formatDateForApi(this.endDate2.value) : null, - soilTypeRemoved: this.soilTypeRemoved.value ?? null, - soilToRemoveArea: this.areaToRemove.value ?? null, - soilToRemoveVolume: this.volumeToRemove.value ?? null, - soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ?? null, - soilToRemoveAverageDepth: this.averageDepthToRemove.value ?? null, - soilFillTypeToPlace: this.fillTypeToPlace.value ?? null, - soilToPlaceArea: this.areaToPlace.value ?? null, - soilToPlaceVolume: this.volumeToPlace.value ?? null, - soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ?? null, - soilToPlaceAverageDepth: this.averageDepthToPlace.value ?? null, + soilTypeRemoved: this.soilTypeRemoved.value ? this.soilTypeRemoved.value : null, + soilToRemoveArea: this.areaToRemove.value ? this.areaToRemove.value : null, + soilToRemoveVolume: this.volumeToRemove.value ? this.volumeToRemove.value : null, + soilToRemoveMaximumDepth: this.maximumDepthToRemove.value ? this.maximumDepthToRemove.value : null, + soilToRemoveAverageDepth: this.averageDepthToRemove.value ? this.averageDepthToRemove.value : null, + soilFillTypeToPlace: this.fillTypeToPlace.value ? this.fillTypeToPlace.value : null, + soilToPlaceArea: this.areaToPlace.value ? this.areaToPlace.value : null, + soilToPlaceVolume: this.volumeToPlace.value ? this.volumeToPlace.value : null, + soilToPlaceMaximumDepth: this.maximumDepthToPlace.value ? this.maximumDepthToPlace.value : null, + soilToPlaceAverageDepth: this.averageDepthToPlace.value ? this.averageDepthToPlace.value : null, }; } diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-v2.component.html b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-v2.component.html index 228f4ec732..e96e0dd99c 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-v2.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-v2.component.html @@ -175,6 +175,7 @@
{{ component.noticeOfIntentDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -187,6 +188,7 @@
{{ component.noticeOfIntentDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > @@ -199,6 +201,7 @@
{{ component.noticeOfIntentDecisionComponentType?.label }}
[component]="component" [fillRow]="true" (saveAlrArea)="onSaveAlrArea(decision.uuid, component.uuid, $event)" + [nonZeroEmptyValidation]="decision.wasReleased" > 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 ccdb7a5013..0319e5e952 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 @@ -48,8 +48,10 @@

Confirm Release Decision

[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="true" (matChipInputTokenEnd)="addEmail($event)" + [formControl]="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.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/release-dialog/release-dialog.component.ts index 6752ae72c6..272c3dc348 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 @@ -7,6 +7,8 @@ import { NoticeOfIntentDecisionV2Service } from '../../../../../services/notice- import { NoticeOfIntentSubmissionStatusService } from '../../../../../services/notice-of-intent/notice-of-intent-submission-status/notice-of-intent-submission-status.service'; import { NOI_SUBMISSION_STATUS } from '../../../../../services/notice-of-intent/notice-of-intent.dto'; import { ApplicationSubmissionStatusPill } from '../../../../../shared/application-submission-status-type-pill/application-submission-status-type-pill.component'; +import { strictEmailValidator } from '../../../../../shared/validators/email-validator'; +import { FormControl } from '@angular/forms'; @Component({ selector: 'app-release-dialog', @@ -24,6 +26,8 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { readonly separatorKeysCodes = [ENTER, COMMA, SPACE] as const; emails: string[] = []; + email = new FormControl(null, [strictEmailValidator]); + constructor( private decisionService: NoticeOfIntentDecisionV2Service, private submissionStatusService: NoticeOfIntentSubmissionStatusService, @@ -95,6 +99,10 @@ export class ReleaseDialogComponent implements OnInit, OnDestroy { } addEmail(event: MatChipInputEvent): void { + if (this.email.invalid) { + return; + } + const value = (event.value || '').trim(); if (value) { this.emails.push(value); diff --git a/alcs-frontend/src/app/features/notice-of-intent/documents/documents.component.html b/alcs-frontend/src/app/features/notice-of-intent/documents/documents.component.html index 465b127163..b7f7923896 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/documents/documents.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/documents/documents.component.html @@ -13,7 +13,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + @@ -48,7 +53,7 @@

Documents

- Actions + Actions
- + {{ model.uuid ? 'Update' : 'Create' }} Information Reques Waiting for additional information from applicant - + Other: - +
diff --git a/alcs-frontend/src/app/features/notice-of-intent/info-requests/info-request-dialog/info-request-dialog.component.scss b/alcs-frontend/src/app/features/notice-of-intent/info-requests/info-request-dialog/info-request-dialog.component.scss index 8ccfc63712..540e30f5c2 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/info-requests/info-request-dialog/info-request-dialog.component.scss +++ b/alcs-frontend/src/app/features/notice-of-intent/info-requests/info-request-dialog/info-request-dialog.component.scss @@ -48,10 +48,16 @@ label { } } -.other-text { - border-bottom: 1px solid colors.$black; - padding-bottom: 4px; +.other-radio-button { + display: inline-block !important; +} + +.other-text.mat-mdc-input-element { + border-bottom: 1px solid colors.$black !important; margin-bottom: -5px; + margin-left: 10px; + width: 80%; + max-width: 90%; } :host::ng-deep { diff --git a/alcs-frontend/src/app/features/notice-of-intent/proposal/proposal.component.html b/alcs-frontend/src/app/features/notice-of-intent/proposal/proposal.component.html index 268d7b2e60..2c75181097 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/proposal/proposal.component.html +++ b/alcs-frontend/src/app/features/notice-of-intent/proposal/proposal.component.html @@ -27,7 +27,7 @@
Proposal Components - {{ noticeOfIntent.type.label }}
-
Agricultural Capability Consultant 2
+
Agricultural Capability Consultant
-
- -
+
+
diff --git a/alcs-frontend/src/app/features/notification/applicant-info/applicant-info.component.scss b/alcs-frontend/src/app/features/notification/applicant-info/applicant-info.component.scss index 480cb3d0e2..d377c71785 100644 --- a/alcs-frontend/src/app/features/notification/applicant-info/applicant-info.component.scss +++ b/alcs-frontend/src/app/features/notification/applicant-info/applicant-info.component.scss @@ -1,10 +1,3 @@ -.applicant-info { - & > div { - margin: 32px 0; - } - } - - .subheading1 { - margin-bottom: 4px !important; - } - \ No newline at end of file +.subheading1 { + margin-bottom: 4px !important; +} diff --git a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.html b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.html index 8df597ccb3..cc91f5ba32 100644 --- a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.html +++ b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.html @@ -1,8 +1,11 @@ +
+

Applicant Info

+
-

Transferee(s)

+

Transferee(s)

Type
@@ -26,7 +29,7 @@

Transferee(s)

-

Primary Contact Information

+

Primary Contact Information

First Name
@@ -56,7 +59,7 @@

Primary Contact Information

-

Purpose of SRW

+

Purpose of SRW

Submitter’s File Number
@@ -107,7 +110,7 @@

Purpose of SRW

-

Optional Documents

+

Optional Documents

File Name
diff --git a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.scss b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.scss index be32732d4b..bb0b06f09a 100644 --- a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.scss +++ b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/notification-details.component.scss @@ -102,3 +102,7 @@ } } } + +.header { + margin-bottom: 42px; +} diff --git a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/parcel/parcel.component.html b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/parcel/parcel.component.html index 2c5b9c684e..a13702b62b 100644 --- a/alcs-frontend/src/app/features/notification/applicant-info/notification-details/parcel/parcel.component.html +++ b/alcs-frontend/src/app/features/notification/applicant-info/notification-details/parcel/parcel.component.html @@ -1,9 +1,9 @@ -

Notification Parcels

+

Notification Parcels

-

Parcel {{ parcelInd + 1 }}

+
Parcel {{ parcelInd + 1 }}
Ownership Type
diff --git a/alcs-frontend/src/app/features/notification/documents/documents.component.html b/alcs-frontend/src/app/features/notification/documents/documents.component.html index 5dea30e042..9a374eafc8 100644 --- a/alcs-frontend/src/app/features/notification/documents/documents.component.html +++ b/alcs-frontend/src/app/features/notification/documents/documents.component.html @@ -13,7 +13,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + @@ -58,7 +63,7 @@

Documents

- Actions + Actions
@@ -39,6 +40,7 @@

ALC Intake

diff --git a/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.html b/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.html index 4454c01830..8f5f3b7e5b 100644 --- a/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.html +++ b/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.html @@ -24,7 +24,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + diff --git a/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.ts b/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.ts index 1de8f1a863..0428b65070 100644 --- a/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.ts +++ b/alcs-frontend/src/app/features/planning-review/decision/decision-documents/decision-documents.component.ts @@ -11,6 +11,7 @@ import { PlanningReviewDecisionService } from '../../../../services/planning-rev import { ToastService } from '../../../../services/toast/toast.service'; import { ConfirmationDialogService } from '../../../../shared/confirmation-dialog/confirmation-dialog.service'; import { DecisionDocumentUploadDialogComponent } from '../decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component'; +import { FILE_NAME_TRUNCATE_LENGTH } from '../../../../shared/constants'; @Component({ selector: 'app-decision-documents', @@ -33,6 +34,8 @@ export class DecisionDocumentsComponent implements OnDestroy, OnChanges { dataSource: MatTableDataSource = new MatTableDataSource(); + readonly fileNameTruncLen = FILE_NAME_TRUNCATE_LENGTH; + constructor( private decisionService: PlanningReviewDecisionService, private dialog: MatDialog, diff --git a/alcs-frontend/src/app/features/planning-review/documents/documents.component.html b/alcs-frontend/src/app/features/planning-review/documents/documents.component.html index 6d0956f57a..12f697f5c6 100644 --- a/alcs-frontend/src/app/features/planning-review/documents/documents.component.html +++ b/alcs-frontend/src/app/features/planning-review/documents/documents.component.html @@ -13,7 +13,12 @@

Documents

Document Name - {{ element.fileName }} + + {{ element.fileName | truncate: fileNameTruncLen}} + @@ -40,7 +45,7 @@

Documents

- Actions + Actions
- -
-
{{ _application.fileNumber }} ({{ applicant }})
+
+
{{ _application.fileNumber }}
+
(
+ {{ _application.applicant }} +
)
+
diff --git a/alcs-frontend/src/app/shared/details-header/details-header.component.scss b/alcs-frontend/src/app/shared/details-header/details-header.component.scss index bb8b0dfe37..1ac722bcd9 100644 --- a/alcs-frontend/src/app/shared/details-header/details-header.component.scss +++ b/alcs-frontend/src/app/shared/details-header/details-header.component.scss @@ -64,3 +64,12 @@ flex-direction: row-reverse; align-items: flex-end; } + +.detail-heading { + display: flex; + align-items: center; + + .file-number { + margin-right: 8px; + } +} diff --git a/alcs-frontend/src/app/shared/details-header/details-header.component.ts b/alcs-frontend/src/app/shared/details-header/details-header.component.ts index 6be9dfb213..e940ad1db8 100644 --- a/alcs-frontend/src/app/shared/details-header/details-header.component.ts +++ b/alcs-frontend/src/app/shared/details-header/details-header.component.ts @@ -21,6 +21,8 @@ import { RETROACTIVE_TYPE_LABEL, } from '../application-type-pill/application-type-pill.constants'; import { TimeTrackable } from '../time-tracker/time-tracker.component'; +import { ApplicationDetailService } from '../../services/application/application-detail.service'; +import { ApplicationSubmissionService } from '../../services/application/application-submission/application-submission.service'; @Component({ selector: 'app-details-header[application]', @@ -38,12 +40,14 @@ export class DetailsHeaderComponent { | NoticeOfIntentSubmissionStatusService | NotificationSubmissionStatusService; + @Input() applicationDetailService?: ApplicationDetailService; + @Input() applicationSubmissionService?: ApplicationSubmissionService; + legacyId?: string; _application: ApplicationDto | CommissionerApplicationDto | NoticeOfIntentDto | NotificationDto | undefined; types: ApplicationTypeDto[] | NoticeOfIntentTypeDto[] = []; timeTrackable?: TimeTrackable; - applicant?: string; @Input() set application( application: ApplicationDto | CommissionerApplicationDto | NoticeOfIntentDto | NotificationDto | undefined, @@ -51,10 +55,6 @@ export class DetailsHeaderComponent { if (application) { this._application = application; - if ('applicant' in application) { - this.applicant = application.applicant; - } - if ('retroactive' in application) { this.isNOI = true; } @@ -161,4 +161,11 @@ export class DetailsHeaderComponent { this.linkedCards = result; } + + async onSaveApplicant(applicant: string | undefined) { + if (this._application?.fileNumber) { + await this.applicationDetailService?.updateApplication(this._application?.fileNumber, { applicant }); + await this.applicationSubmissionService?.update(this._application?.fileNumber, { applicant }); + } + } } diff --git a/alcs-frontend/src/app/shared/drag-drop-board/drag-drop-board.component.scss b/alcs-frontend/src/app/shared/drag-drop-board/drag-drop-board.component.scss index a0316208a2..2f1ab09483 100644 --- a/alcs-frontend/src/app/shared/drag-drop-board/drag-drop-board.component.scss +++ b/alcs-frontend/src/app/shared/drag-drop-board/drag-drop-board.component.scss @@ -21,7 +21,7 @@ justify-content: center; margin: 0 -2px 8px; position: sticky; - top: 0; + top: 84px; text-align: center; z-index: 1000; } diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.html b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.html index ddcf20bcc0..7e90e143af 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.html +++ b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.html @@ -25,15 +25,25 @@ name="value" [placeholder]="placeholder" #editInput - [(ngModel)]="pendingValue" - (keydown.enter)="confirmEdit()" + (keydown.enter)="!valueControl.invalid ? confirmEdit(): preventKeydown($event)" (keydown.escape)="cancelEdit()" + [formControl]="valueControl" /> + warning Value cannot be 0 + warning Value cannot be Empty
- + +
diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.scss b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.scss index 6487e5e781..f99f4255a9 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.scss +++ b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.scss @@ -41,6 +41,10 @@ color: colors.$primary-color; } +.disabled { + color: colors.$grey; +} + :host::ng-deep { .mat-form-field-wrapper { padding: 0 !important; diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.ts b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.ts index 86910130d8..ad76cf87d7 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.ts +++ b/alcs-frontend/src/app/shared/inline-editors/inline-number/inline-number.component.ts @@ -1,4 +1,6 @@ import { AfterContentChecked, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +import { FormControl, Validators } from '@angular/forms'; +import { NonZeroValidator } from '../../validators/value-validator'; @Component({ selector: 'app-inline-number[value]', @@ -9,18 +11,26 @@ export class InlineNumberComponent implements AfterContentChecked { @Input() value?: string | null; @Input() placeholder: string = 'Enter a value'; @Input() decimals = 2; + @Input() nonZeroEmptyValidation: boolean = false; @Output() save = new EventEmitter(); @ViewChild('editInput') textInput!: ElementRef; isEditing = false; - pendingValue: null | string | undefined; + + valueControl = new FormControl(null, []); constructor() {} + ngOnInit() { + if (this.nonZeroEmptyValidation) { + this.valueControl.setValidators([NonZeroValidator, Validators.required]); + } + } + startEdit() { this.isEditing = true; - this.pendingValue = this.value; + this.valueControl.setValue(this.value); } ngAfterContentChecked(): void { @@ -30,9 +40,9 @@ export class InlineNumberComponent implements AfterContentChecked { } confirmEdit() { - if (this.pendingValue !== this.value) { - this.save.emit(this.pendingValue?.toString() ?? null); - this.value = this.pendingValue; + if (this.valueControl.value !== this.value) { + this.save.emit(this.valueControl.value?.toString() ?? null); + this.value = this.valueControl.value; } this.isEditing = false; @@ -40,6 +50,11 @@ export class InlineNumberComponent implements AfterContentChecked { cancelEdit() { this.isEditing = false; - this.pendingValue = this.value; + this.valueControl.setValue(this.value); + } + + preventKeydown(event: Event) { + const keyboardEvent = event as KeyboardEvent; + keyboardEvent.preventDefault(); } } diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html index 51da2b329d..60e1d6e871 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html +++ b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html @@ -1,4 +1,4 @@ -
+
Add text @@ -18,11 +18,12 @@ }" >
- + {{ editInput?.value?.length || 0 }}/{{ maxLength }} -
diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.scss b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.scss index b5ff963fe4..fba5a09459 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.scss +++ b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.scss @@ -2,14 +2,33 @@ .inline-number-wrapper { padding-top: 4px; -} -.editing { - display: inline-block; + &.fixed-height { + padding-top: 0; + + .editing { + display: flex; + align-items: center; + gap: 8px; + } + } + + .editing.hidden { + display: none; + } } -.editing.hidden { - display: none; +::ng-deep { + .inline-number-wrapper .editing { + .mat-mdc-form-field-infix { + padding: 0 !important; + min-height: 0 !important; + } + + .mdc-text-field { + padding-inline: 8px; + } + } } .edit-button { @@ -65,4 +84,8 @@ .mat-mdc-icon-button.mat-mdc-button-base { padding: 0 !important; } + + .mat-mdc-button-disabled { + color: silver; + } } diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts index bc8ea5440d..8b01bd7d44 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts +++ b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts @@ -8,21 +8,27 @@ import { Output, ViewChild, } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { strictEmailValidator } from '../../validators/email-validator'; @Component({ selector: 'app-inline-text[value]', templateUrl: './inline-text.component.html', styleUrls: ['./inline-text.component.scss'], }) -export class InlineTextComponent implements AfterContentChecked { +export class InlineTextComponent implements AfterContentChecked, OnInit { @Input() updateOnSave: boolean = true; @Input() value?: string | undefined; @Input() placeholder: string = 'Enter a value'; @Input() required = false; + @Input() isEmail = false; + @Input() isFixedHeight = false; @Output() save = new EventEmitter(); @Input() mask?: string | undefined; @Input() maxLength: number | null = null; + textInputControl = new FormControl(null, []); + @ViewChild('editInput') textInput!: ElementRef; isEditing = false; @@ -30,6 +36,12 @@ export class InlineTextComponent implements AfterContentChecked { constructor() {} + ngOnInit() { + if (this.isEmail) { + this.textInputControl.setValidators([strictEmailValidator]); + } + } + startEdit() { this.isEditing = true; this.pendingValue = this.value; @@ -42,6 +54,10 @@ export class InlineTextComponent implements AfterContentChecked { } confirmEdit() { + if (this.textInputControl.invalid) { + return; + } + if (this.pendingValue !== this.value) { this.save.emit(this.pendingValue?.toString() ?? null); diff --git a/alcs-frontend/src/app/shared/mention-textarea/mention-textarea.component.html b/alcs-frontend/src/app/shared/mention-textarea/mention-textarea.component.html index 14b6a05a9f..849448a10e 100644 --- a/alcs-frontend/src/app/shared/mention-textarea/mention-textarea.component.html +++ b/alcs-frontend/src/app/shared/mention-textarea/mention-textarea.component.html @@ -1,5 +1,5 @@
- + {{ labelText }} diff --git a/alcs-frontend/src/app/shared/utils/file.ts b/alcs-frontend/src/app/shared/utils/file.ts index 21284d7223..1585b4c88e 100644 --- a/alcs-frontend/src/app/shared/utils/file.ts +++ b/alcs-frontend/src/app/shared/utils/file.ts @@ -32,7 +32,16 @@ export const openFileInline = (url: string, fileName: string) => { export const splitExtension = (documentName: string) => { const lastPeriod = documentName.lastIndexOf('.'); - const extension = documentName.substring(lastPeriod); - const fileName = documentName.substring(0, lastPeriod); - return { fileName, extension }; + + if (lastPeriod <= 0 || lastPeriod === documentName.length - 1) { + return { + fileName: documentName, + extension: '', + }; + } + + return { + fileName: documentName.substring(0, lastPeriod), + extension: documentName.substring(lastPeriod), + }; }; diff --git a/alcs-frontend/src/app/shared/validators/email-validator.ts b/alcs-frontend/src/app/shared/validators/email-validator.ts new file mode 100644 index 0000000000..c736a70286 --- /dev/null +++ b/alcs-frontend/src/app/shared/validators/email-validator.ts @@ -0,0 +1,18 @@ +import { AbstractControl, ValidationErrors } from '@angular/forms'; +import validator from 'validator'; + +const isString = (s: string) => { + return Object.prototype.toString.call(s) === '[object String]'; +}; + +const isEmail = (s: string) => { + return isString(s) && validator.isEmail(s, { allow_display_name: true }); +}; + +export const strictEmailValidator = (control: AbstractControl): ValidationErrors | null => { + return !control.value || isEmail(control.value) ? null : { email: true }; +}; + +export const strictEmailListValidator = (control: AbstractControl): ValidationErrors | null => { + return !control.value || control.value.every(isEmail) ? null : { email: true }; +}; diff --git a/alcs-frontend/src/app/shared/validators/value-validator.ts b/alcs-frontend/src/app/shared/validators/value-validator.ts new file mode 100644 index 0000000000..684dcc3f00 --- /dev/null +++ b/alcs-frontend/src/app/shared/validators/value-validator.ts @@ -0,0 +1,9 @@ +import { AbstractControl, ValidationErrors } from "@angular/forms"; + +export const NonZeroValidator = (control: AbstractControl): ValidationErrors | null => { + const value = control.value; + if (value === 0) { + return { nonZero: true }; + } + return null; +} \ No newline at end of file diff --git a/alcs-frontend/src/styles/ngselect.scss b/alcs-frontend/src/styles/ngselect.scss index a909d29e2a..1c0292cd5d 100644 --- a/alcs-frontend/src/styles/ngselect.scss +++ b/alcs-frontend/src/styles/ngselect.scss @@ -7,11 +7,14 @@ } .ng-select.ng-select-focused .ng-select-container.ng-appearance-outline:after, -.ng-select.ng-select-focused .ng-select-container.ng-appearance-outline:hover:after, -.ng-select.ng-select-focused .ng-select-container:after { +.ng-select.ng-select-focused .ng-select-container.ng-appearance-outline:hover:after { border-color: colors.$primary-color !important; } +.ng-select .ng-select-container:after { + border-color: transparent !important; +} + .ng-select .ng-arrow { color: colors.$primary-color !important; } diff --git a/e2e/pages/alcs/alcs-login-page.ts b/e2e/pages/alcs/alcs-login-page.ts index 440e72eafd..cff0d3fbd3 100644 --- a/e2e/pages/alcs/alcs-login-page.ts +++ b/e2e/pages/alcs/alcs-login-page.ts @@ -11,7 +11,7 @@ export class ALCSLoginPage { constructor(page: Page, baseUrl: string) { this.page = page; this.baseUrl = baseUrl; - this.idirLink = page.getByRole('link', { name: 'IDIR' }); + this.idirLink = page.getByRole('link', { name: 'Basic or Business BCeID' }); // There is an error with the username label on BCeID page this.userIdTextbox = page.getByRole('textbox').nth(0); this.passwordTextbox = page.getByLabel('Password'); diff --git a/e2e/pages/alcs/applicant-info-page/parcels-section.ts b/e2e/pages/alcs/applicant-info-page/parcels-section.ts index 29b3d7520e..f4c80c479a 100644 --- a/e2e/pages/alcs/applicant-info-page/parcels-section.ts +++ b/e2e/pages/alcs/applicant-info-page/parcels-section.ts @@ -20,7 +20,7 @@ export class ParcelsSection { async expectParcelDetails(parcelNumber: number, parcel: ParcelDetails) { await expect(this.typeText(parcelNumber)).toHaveText(parcel.type); await expect(this.legalDescriptionText(parcelNumber)).toHaveText(parcel.legalDescription); - await expect(this.mapAreaText(parcelNumber)).toHaveText(parcel.mapArea); + await expect(this.mapAreaText(parcelNumber)).toHaveText(`${parcel.mapArea} ha`); if (parcel.pid !== undefined) { await expect(this.pidText(parcelNumber)).toHaveText(parcel.pid); } diff --git a/e2e/pages/portal/parcels-page.ts b/e2e/pages/portal/parcels-page.ts index c2788e9cd0..f72829039f 100644 --- a/e2e/pages/portal/parcels-page.ts +++ b/e2e/pages/portal/parcels-page.ts @@ -184,7 +184,12 @@ export class ParcelsPage { // Month uses 3-letter abbreviation (e.g., 'Apr') async setDate(parcelNumber: number, year: string, month: string, day: string) { - await this.parcelBody(parcelNumber).getByRole('button', { name: 'Open calendar' }).click(); + const calendarButton = await this.parcelBody(parcelNumber).getByRole('button', { name: 'Open calendar' }); + await calendarButton.evaluate((e) => { + e.scrollIntoView({ block: 'center', inline: 'center' }); + }); + await this.page.waitForTimeout(500); + await calendarButton.click(); // Can't have more than one datepicker open at once // We just have to trust the correct one is still open await this.page.getByRole('button', { name: year }).click(); diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index bb85faf430..a87e2c03d5 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -17,11 +17,12 @@ export default defineConfig({ /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 2 : 0, + retries: process.env.CI ? 2 : 1, /* Opt out of parallel tests on CI. */ - workers: process.env.CI ? 1 : undefined, + workers: process.env.CI ? 1 : 1, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: 'html', + timeout: 120000, /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ diff --git a/e2e/tests/tur.spec.ts b/e2e/tests/tur.spec.ts index 27ac46662b..da70f3ae87 100644 --- a/e2e/tests/tur.spec.ts +++ b/e2e/tests/tur.spec.ts @@ -193,7 +193,7 @@ test.describe.serial('Portal TUR submission and ALCS applicant info flow', () => test('submission data should appear in ALCS applicant info', async ({ page }) => { const alcsLoginPage = new ALCSLoginPage(page, process.env.ALCS_BASE_URL); await alcsLoginPage.goto(); - await alcsLoginPage.login(process.env.IDIR_USERNAME, process.env.IDIR_PASSWORD); + await alcsLoginPage.login(process.env.BCEID_BASIC_USERNAME, process.env.BCEID_BASIC_PASSWORD); const alcsMainNavidation = new ALCSMainNavigation(page); diff --git a/portal-frontend/package-lock.json b/portal-frontend/package-lock.json index f73a262287..9e2714a37a 100644 --- a/portal-frontend/package-lock.json +++ b/portal-frontend/package-lock.json @@ -20,12 +20,14 @@ "@angular/router": "^17.3.3", "@bcgov/bc-sans": "^2.1.0", "@types/uuid": "^9.0.8", + "@types/validator": "^13.12.0", "jwt-decode": "^4.0.0", "ngx-mask": "17.0.4", "rxjs": "~7.8.1", "source-map-support": "^0.5.21", "tslib": "^2.6.2", "uuid": "^9.0.1", + "validator": "^13.12.0", "zone.js": "~0.14.4" }, "devDependencies": { @@ -6174,6 +6176,11 @@ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==" }, + "node_modules/@types/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" + }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -7295,12 +7302,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -9492,9 +9499,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -16965,6 +16972,14 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -17484,9 +17499,9 @@ } }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" diff --git a/portal-frontend/package.json b/portal-frontend/package.json index 086e3f602e..d6ec30e6aa 100644 --- a/portal-frontend/package.json +++ b/portal-frontend/package.json @@ -25,12 +25,14 @@ "@angular/router": "^17.3.3", "@bcgov/bc-sans": "^2.1.0", "@types/uuid": "^9.0.8", + "@types/validator": "^13.12.0", "jwt-decode": "^4.0.0", "ngx-mask": "17.0.4", "rxjs": "~7.8.1", "source-map-support": "^0.5.21", "tslib": "^2.6.2", "uuid": "^9.0.1", + "validator": "^13.12.0", "zone.js": "~0.14.4" }, "devDependencies": { diff --git a/portal-frontend/src/app/features/applications/edit-submission/primary-contact/primary-contact.component.ts b/portal-frontend/src/app/features/applications/edit-submission/primary-contact/primary-contact.component.ts index b409cb500d..eb7c05bd35 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/primary-contact/primary-contact.component.ts +++ b/portal-frontend/src/app/features/applications/edit-submission/primary-contact/primary-contact.component.ts @@ -21,6 +21,7 @@ import { OwnerDialogComponent } from '../../../../shared/owner-dialogs/owner-dia import { CrownOwnerDialogComponent } from '../../../../shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component'; import { scrollToElement } from '../../../../shared/utils/scroll-helper'; import { MatButtonToggleChange } from '@angular/material/button-toggle'; +import { strictEmailValidator } from '../../../../shared/validators/email-validator'; @Component({ selector: 'app-primary-contact', @@ -35,7 +36,7 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni files: (ApplicationDocumentDto & { errorMessage?: string })[] = []; needsAuthorizationLetter = false; - selectedThirdPartyAgent = false; + selectedThirdPartyAgent: boolean | null = false; selectedLocalGovernment = false; _selectedOwnerUuid: string | undefined = undefined; isCrownOwner = false; @@ -50,7 +51,7 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); form = new FormGroup({ firstName: this.firstName, @@ -266,9 +267,12 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni } async onSelectPrimaryContactType(event: MatButtonToggleChange) { - const isExistingOwner = event.value; + const isExistingOwner: boolean = event.value; const hasValues = Object.values(this.form.value).some((value) => value); + // This is necessary to keep toggle and variable in sync + this.selectedThirdPartyAgent = !isExistingOwner; + if (hasValues) { await this.dialog .open(PrimaryContactConfirmationDialogComponent, { @@ -279,10 +283,12 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni }, }) .beforeClosed() - .subscribe(async (confirmed) => { + .subscribe(async (confirmed: boolean) => { if (confirmed) { this.form.reset(); this.switchPrimaryContactType(isExistingOwner); + } else { + this.selectedThirdPartyAgent = isExistingOwner; } }); } else { diff --git a/portal-frontend/src/app/features/applications/edit-submission/proposal/cove-proposal/transferee-dialog/transferee-dialog.component.ts b/portal-frontend/src/app/features/applications/edit-submission/proposal/cove-proposal/transferee-dialog/transferee-dialog.component.ts index 559cbc1d1f..54b6d59058 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/proposal/cove-proposal/transferee-dialog/transferee-dialog.component.ts +++ b/portal-frontend/src/app/features/applications/edit-submission/proposal/cove-proposal/transferee-dialog/transferee-dialog.component.ts @@ -10,6 +10,7 @@ import { import { CovenantTransfereeService } from '../../../../../../services/covenant-transferee/covenant-transferee.service'; import { OWNER_TYPE } from '../../../../../../shared/dto/owner.dto'; import { TransfereeDialogComponent } from '../../../../../notifications/edit-submission/transferees/transferee-dialog/transferee-dialog.component'; +import { strictEmailValidator } from '../../../../../../shared/validators/email-validator'; @Component({ selector: 'app-transferee-dialog', @@ -23,7 +24,7 @@ export class CovenantTransfereeDialogComponent { lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); isEdit = false; isLoading = false; @@ -45,7 +46,7 @@ export class CovenantTransfereeDialogComponent { public data: { submissionUuid: string; existingTransferee?: CovenantTransfereeDto; - } + }, ) { if (data && data.existingTransferee) { this.onChangeType({ diff --git a/portal-frontend/src/app/features/applications/edit-submission/success/success.component.html b/portal-frontend/src/app/features/applications/edit-submission/success/success.component.html index 3f43254ee6..f022a4185c 100644 --- a/portal-frontend/src/app/features/applications/edit-submission/success/success.component.html +++ b/portal-frontend/src/app/features/applications/edit-submission/success/success.component.html @@ -45,7 +45,7 @@

Application ID: {{ fileId }} Submitted!



- The Primary Contact will be emailed this information and all future correspondence. + The Primary Contact will be emailed this information and all future correspondence. Please check junk and spam folders.

diff --git a/portal-frontend/src/app/features/applications/review-submission/review-contact-information/review-contact-information.component.ts b/portal-frontend/src/app/features/applications/review-submission/review-contact-information/review-contact-information.component.ts index f70ff1da25..d2e442738e 100644 --- a/portal-frontend/src/app/features/applications/review-submission/review-contact-information/review-contact-information.component.ts +++ b/portal-frontend/src/app/features/applications/review-submission/review-contact-information/review-contact-information.component.ts @@ -4,6 +4,7 @@ import { Router } from '@angular/router'; import { Subject, takeUntil } from 'rxjs'; import { ApplicationSubmissionReviewService } from '../../../../services/application-submission-review/application-submission-review.service'; import { ReviewApplicationSteps } from '../review-submission.component'; +import { strictEmailValidator } from '../../../../shared/validators/email-validator'; @Component({ selector: 'app-review-contact-information', @@ -22,7 +23,7 @@ export class ReviewContactInformationComponent implements OnInit, OnDestroy { position = new FormControl('', [Validators.required]); department = new FormControl('', [Validators.required]); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); isFirstNationGovernment = false; governmentName = ''; diff --git a/portal-frontend/src/app/features/applications/view-submission/view-application-submission.component.scss b/portal-frontend/src/app/features/applications/view-submission/view-application-submission.component.scss index e6e94496ff..82a88c4760 100644 --- a/portal-frontend/src/app/features/applications/view-submission/view-application-submission.component.scss +++ b/portal-frontend/src/app/features/applications/view-submission/view-application-submission.component.scss @@ -2,13 +2,7 @@ @use '../../../../styles/colors'; .navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } -} - -.content { - margin: rem(24) 0; + margin-top: rem(18); } :host::ng-deep { diff --git a/portal-frontend/src/app/features/home/home.component.scss b/portal-frontend/src/app/features/home/home.component.scss index ace9e2f42c..86e824e429 100644 --- a/portal-frontend/src/app/features/home/home.component.scss +++ b/portal-frontend/src/app/features/home/home.component.scss @@ -1,12 +1,6 @@ @use '../../../styles/functions' as *; @use '../../../styles/colors'; -.navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } -} - :host::ng-deep { .no-data { color: colors.$grey; diff --git a/portal-frontend/src/app/features/home/inbox/inbox-table/inbox-table.component.html b/portal-frontend/src/app/features/home/inbox/inbox-table/inbox-table.component.html index 5fe12167eb..5b5f88a768 100644 --- a/portal-frontend/src/app/features/home/inbox/inbox-table/inbox-table.component.html +++ b/portal-frontend/src/app/features/home/inbox/inbox-table/inbox-table.component.html @@ -33,7 +33,7 @@ - {{ type === 'Notifications' ? 'Transferee' : 'Owner Name' }} + {{ type === 'Notifications' ? 'Transferee' : 'Name' }} {{ row.ownerName || '(Unknown)' }} diff --git a/portal-frontend/src/app/features/home/inbox/inbox.component.html b/portal-frontend/src/app/features/home/inbox/inbox.component.html index 91bc7cc15e..61b6fc8422 100644 --- a/portal-frontend/src/app/features/home/inbox/inbox.component.html +++ b/portal-frontend/src/app/features/home/inbox/inbox.component.html @@ -190,7 +190,7 @@ [items]="applications" [totalCount]="applicationTotal" (loadMore)="onLoadMore('APP')" - type="Applications" + type="Application" > @@ -210,7 +210,7 @@ [items]="noticeOfIntents" [totalCount]="noticeOfIntentTotal" (loadMore)="onLoadMore('NOI')" - type="Notices of Intent" + type="Notice of Intent" > @@ -229,13 +229,13 @@ [items]="notifications" [totalCount]="notificationTotal" (loadMore)="onLoadMore('NOTI')" - type="Notifications" + type="Notification" > diff --git a/portal-frontend/src/app/features/notice-of-intents/edit-submission/primary-contact/primary-contact.component.ts b/portal-frontend/src/app/features/notice-of-intents/edit-submission/primary-contact/primary-contact.component.ts index a7a1a72eae..31eaaa9fbd 100644 --- a/portal-frontend/src/app/features/notice-of-intents/edit-submission/primary-contact/primary-contact.component.ts +++ b/portal-frontend/src/app/features/notice-of-intents/edit-submission/primary-contact/primary-contact.component.ts @@ -22,6 +22,7 @@ import { PrimaryContactConfirmationDialogComponent } from './primary-contact-con import { CrownOwnerDialogComponent } from '../../../../shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component'; import { scrollToElement } from '../../../../shared/utils/scroll-helper'; import { MatButtonToggleChange } from '@angular/material/button-toggle'; +import { strictEmailValidator } from '../../../../shared/validators/email-validator'; @Component({ selector: 'app-primary-contact', @@ -37,7 +38,7 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni needsAuthorizationLetter = false; showVirusError = false; - selectedThirdPartyAgent = false; + selectedThirdPartyAgent: boolean | null = false; selectedLocalGovernment = false; _selectedOwnerUuid: string | undefined = undefined; isCrownOwner = false; @@ -51,7 +52,7 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); form = new FormGroup({ firstName: this.firstName, @@ -268,9 +269,12 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni } async onSelectPrimaryContactType(event: MatButtonToggleChange) { - const isExistingOwner = event.value; + const isExistingOwner: boolean = event.value; const hasValues = Object.values(this.form.value).some((value) => value); + // This is necessary to keep toggle and variable in sync + this.selectedThirdPartyAgent = !isExistingOwner; + if (hasValues) { await this.dialog .open(PrimaryContactConfirmationDialogComponent, { @@ -281,10 +285,12 @@ export class PrimaryContactComponent extends FilesStepComponent implements OnIni }, }) .beforeClosed() - .subscribe(async (confirmed) => { + .subscribe(async (confirmed: boolean) => { if (confirmed) { this.form.reset(); this.switchPrimaryContactType(isExistingOwner); + } else { + this.selectedThirdPartyAgent = isExistingOwner; } }); } else { diff --git a/portal-frontend/src/app/features/notice-of-intents/edit-submission/success/success.component.html b/portal-frontend/src/app/features/notice-of-intents/edit-submission/success/success.component.html index 2a2c0e12ca..3f485724a1 100644 --- a/portal-frontend/src/app/features/notice-of-intents/edit-submission/success/success.component.html +++ b/portal-frontend/src/app/features/notice-of-intents/edit-submission/success/success.component.html @@ -21,7 +21,7 @@

NOI ID: {{ fileId }} Submitted!

In Victoria call: 250-387-6121
Elsewhere in BC call: 1-800-663-7867

- The Primary Contact will be emailed this information and all future correspondence. + The Primary Contact will be emailed this information and all future correspondence. Please check junk and spam folders.

diff --git a/portal-frontend/src/app/features/notice-of-intents/view-submission/view-notice-of-intent-submission.component.scss b/portal-frontend/src/app/features/notice-of-intents/view-submission/view-notice-of-intent-submission.component.scss index 0c27210f48..77d79d4922 100644 --- a/portal-frontend/src/app/features/notice-of-intents/view-submission/view-notice-of-intent-submission.component.scss +++ b/portal-frontend/src/app/features/notice-of-intents/view-submission/view-notice-of-intent-submission.component.scss @@ -2,9 +2,7 @@ @use '../../../../styles/colors'; .navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } + margin-top: rem(18); } .content { diff --git a/portal-frontend/src/app/features/notifications/edit-submission/primary-contact/primary-contact.component.ts b/portal-frontend/src/app/features/notifications/edit-submission/primary-contact/primary-contact.component.ts index ae6b818c5a..0f11f740ad 100644 --- a/portal-frontend/src/app/features/notifications/edit-submission/primary-contact/primary-contact.component.ts +++ b/portal-frontend/src/app/features/notifications/edit-submission/primary-contact/primary-contact.component.ts @@ -4,6 +4,7 @@ import { takeUntil } from 'rxjs'; import { NotificationSubmissionService } from '../../../../services/notification-submission/notification-submission.service'; import { EditNotificationSteps } from '../edit-submission.component'; import { StepComponent } from '../step.partial'; +import { strictEmailValidator } from '../../../../shared/validators/email-validator'; @Component({ selector: 'app-primary-contact', @@ -17,8 +18,8 @@ export class PrimaryContactComponent extends StepComponent implements OnInit, On lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); - confirmEmail = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); + confirmEmail = new FormControl('', [Validators.required, strictEmailValidator]); form = new FormGroup({ firstName: this.firstName, diff --git a/portal-frontend/src/app/features/notifications/edit-submission/success/success.component.html b/portal-frontend/src/app/features/notifications/edit-submission/success/success.component.html index 329fadb098..a238af42b8 100644 --- a/portal-frontend/src/app/features/notifications/edit-submission/success/success.component.html +++ b/portal-frontend/src/app/features/notifications/edit-submission/success/success.component.html @@ -8,7 +8,7 @@

Notification ID: {{ fileId }} Submitted!

The Primary Contact will receive an automated email shortly containing an attached PDF response which must be appended as an additional document to the LTSA SRW application package.

If the email is not received within an hour, please email your SRW ID to - ALC.Portal@gov.bc.ca request assistance. + ALC.Portal@gov.bc.ca request assistance. Please check junk and spam folders.

diff --git a/portal-frontend/src/app/features/notifications/edit-submission/transferees/transferee-dialog/transferee-dialog.component.ts b/portal-frontend/src/app/features/notifications/edit-submission/transferees/transferee-dialog/transferee-dialog.component.ts index b96bb4516d..87d12c0b72 100644 --- a/portal-frontend/src/app/features/notifications/edit-submission/transferees/transferee-dialog/transferee-dialog.component.ts +++ b/portal-frontend/src/app/features/notifications/edit-submission/transferees/transferee-dialog/transferee-dialog.component.ts @@ -9,6 +9,7 @@ import { } from '../../../../../services/notification-transferee/notification-transferee.dto'; import { NotificationTransfereeService } from '../../../../../services/notification-transferee/notification-transferee.service'; import { OWNER_TYPE } from '../../../../../shared/dto/owner.dto'; +import { strictEmailValidator } from '../../../../../shared/validators/email-validator'; @Component({ selector: 'app-transferee-dialog', @@ -22,7 +23,7 @@ export class TransfereeDialogComponent { lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); isEdit = false; isLoading = false; diff --git a/portal-frontend/src/app/features/notifications/view-submission/view-notification-submission.component.scss b/portal-frontend/src/app/features/notifications/view-submission/view-notification-submission.component.scss index 0c27210f48..77d79d4922 100644 --- a/portal-frontend/src/app/features/notifications/view-submission/view-notification-submission.component.scss +++ b/portal-frontend/src/app/features/notifications/view-submission/view-notification-submission.component.scss @@ -2,9 +2,7 @@ @use '../../../../styles/colors'; .navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } + margin-top: rem(18); } .content { diff --git a/portal-frontend/src/app/features/public/application/public-application.component.scss b/portal-frontend/src/app/features/public/application/public-application.component.scss index 8db0588869..5f77a14eed 100644 --- a/portal-frontend/src/app/features/public/application/public-application.component.scss +++ b/portal-frontend/src/app/features/public/application/public-application.component.scss @@ -1,12 +1,6 @@ @use '../../../../styles/functions' as *; @use '../../../../styles/colors'; -.navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } -} - .content { margin: rem(24) 0; } diff --git a/portal-frontend/src/app/features/public/notice-of-intent/public-notice-of-intent.component.scss b/portal-frontend/src/app/features/public/notice-of-intent/public-notice-of-intent.component.scss index 8db0588869..5f77a14eed 100644 --- a/portal-frontend/src/app/features/public/notice-of-intent/public-notice-of-intent.component.scss +++ b/portal-frontend/src/app/features/public/notice-of-intent/public-notice-of-intent.component.scss @@ -1,12 +1,6 @@ @use '../../../../styles/functions' as *; @use '../../../../styles/colors'; -.navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } -} - .content { margin: rem(24) 0; } diff --git a/portal-frontend/src/app/features/public/notification/public-notification.component.scss b/portal-frontend/src/app/features/public/notification/public-notification.component.scss index 8db0588869..5f77a14eed 100644 --- a/portal-frontend/src/app/features/public/notification/public-notification.component.scss +++ b/portal-frontend/src/app/features/public/notification/public-notification.component.scss @@ -1,12 +1,6 @@ @use '../../../../styles/functions' as *; @use '../../../../styles/colors'; -.navigation { - ::ng-deep .mdc-tab__text-label { - font-weight: bold; - } -} - .content { margin: rem(24) 0; } diff --git a/portal-frontend/src/app/features/public/search/application-search-table/application-search-table.component.html b/portal-frontend/src/app/features/public/search/application-search-table/application-search-table.component.html index c5683619ec..e5777b09ff 100644 --- a/portal-frontend/src/app/features/public/search/application-search-table/application-search-table.component.html +++ b/portal-frontend/src/app/features/public/search/application-search-table/application-search-table.component.html @@ -17,7 +17,7 @@ - Owner Name + Name {{ element.ownerName | emptyColumn }} diff --git a/portal-frontend/src/app/features/public/search/public-search.component.html b/portal-frontend/src/app/features/public/search/public-search.component.html index 22686c3fc2..06893bc671 100644 --- a/portal-frontend/src/app/features/public/search/public-search.component.html +++ b/portal-frontend/src/app/features/public/search/public-search.component.html @@ -10,7 +10,7 @@

Welcome to the ALC Public Search

Search by one or more of the following fields:

- +
diff --git a/portal-frontend/src/app/features/public/search/public-search.component.scss b/portal-frontend/src/app/features/public/search/public-search.component.scss index d01ac1cf6e..ee2dc1c10b 100644 --- a/portal-frontend/src/app/features/public/search/public-search.component.scss +++ b/portal-frontend/src/app/features/public/search/public-search.component.scss @@ -1,6 +1,14 @@ @use '../../../../styles/colors'; @use '../../../../styles/functions' as *; +h3 { + margin-bottom: rem(20) !important; + + @media screen and (min-width: $desktopBreakpoint) { + margin-bottom: rem(24) !important; + } +} + :host::ng-deep { .label { display: inline-block; diff --git a/portal-frontend/src/app/features/public/search/public-search.component.ts b/portal-frontend/src/app/features/public/search/public-search.component.ts index 14615fb9a1..e2a70dae2e 100644 --- a/portal-frontend/src/app/features/public/search/public-search.component.ts +++ b/portal-frontend/src/app/features/public/search/public-search.component.ts @@ -210,7 +210,7 @@ export class PublicSearchComponent implements OnInit, OnDestroy { setTimeout(() => { this.setActiveTab(); setTimeout(() => { - scrollToElement({ id: `results`, center: false }); + scrollToElement({ id: `searchResultsWrapper`, center: false }); }); }); } @@ -250,6 +250,12 @@ export class PublicSearchComponent implements OnInit, OnDestroy { } } + onEnter(event: KeyboardEvent) { + if (event.key === 'Enter') { + event.preventDefault(); + } + } + getSearchParams(): SearchRequestDto { const searchControls = this.searchForm.controls; diff --git a/portal-frontend/src/app/shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component.ts b/portal-frontend/src/app/shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component.ts index 112f9dcd36..c48236fb19 100644 --- a/portal-frontend/src/app/shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component.ts +++ b/portal-frontend/src/app/shared/owner-dialogs/crown-owner-dialog/crown-owner-dialog.component.ts @@ -15,6 +15,7 @@ import { import { NoticeOfIntentOwnerService } from '../../../services/notice-of-intent-owner/notice-of-intent-owner.service'; import { OWNER_TYPE } from '../../dto/owner.dto'; import { ConfirmationDialogService } from '../../confirmation-dialog/confirmation-dialog.service'; +import { strictEmailValidator } from '../../validators/email-validator'; @Component({ selector: 'app-crown-owner-dialog', @@ -26,7 +27,7 @@ export class CrownOwnerDialogComponent { firstName = new FormControl('', [Validators.required]); lastName = new FormControl('', [Validators.required]); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); crownLandOwnerType = new FormControl('', [Validators.required]); isEdit = false; @@ -52,7 +53,7 @@ export class CrownOwnerDialogComponent { parcelUuid?: string; ownerService: ApplicationOwnerService | NoticeOfIntentOwnerService; existingOwner?: ApplicationOwnerDto | NoticeOfIntentOwnerDto; - } + }, ) { if (data && data.existingOwner) { this.isEdit = true; diff --git a/portal-frontend/src/app/shared/owner-dialogs/owner-dialog/owner-dialog.component.ts b/portal-frontend/src/app/shared/owner-dialogs/owner-dialog/owner-dialog.component.ts index f57d2c84fd..5946c65b8e 100644 --- a/portal-frontend/src/app/shared/owner-dialogs/owner-dialog/owner-dialog.component.ts +++ b/portal-frontend/src/app/shared/owner-dialogs/owner-dialog/owner-dialog.component.ts @@ -20,6 +20,7 @@ import { DOCUMENT_SOURCE, DOCUMENT_TYPE, DocumentTypeDto } from '../../dto/docum import { OWNER_TYPE } from '../../dto/owner.dto'; import { FileHandle } from '../../file-drag-drop/drag-drop.directive'; import { openFileInline } from '../../utils/file'; +import { strictEmailValidator } from '../../validators/email-validator'; @Component({ selector: 'app-owner-dialog', @@ -33,7 +34,7 @@ export class OwnerDialogComponent { lastName = new FormControl('', [Validators.required]); organizationName = new FormControl(''); phoneNumber = new FormControl('', [Validators.required]); - email = new FormControl('', [Validators.required, Validators.email]); + email = new FormControl('', [Validators.required, strictEmailValidator]); corporateSummary = new FormControl(null); isEdit = false; diff --git a/portal-frontend/src/app/shared/validators/email-validator.ts b/portal-frontend/src/app/shared/validators/email-validator.ts new file mode 100644 index 0000000000..a367452967 --- /dev/null +++ b/portal-frontend/src/app/shared/validators/email-validator.ts @@ -0,0 +1,12 @@ +import { AbstractControl, ValidationErrors } from '@angular/forms'; +import validator from 'validator'; + +export const strictEmailValidator = (control: AbstractControl): ValidationErrors | null => { + return !control.value || (isString(control.value) && validator.isEmail(control.value, { allow_display_name: true })) + ? null + : { email: true }; +}; + +function isString(s: string) { + return Object.prototype.toString.call(s) === '[object String]'; +} diff --git a/portal-frontend/src/styles.scss b/portal-frontend/src/styles.scss index 2a3e27a0a9..9aff0133f8 100644 --- a/portal-frontend/src/styles.scss +++ b/portal-frontend/src/styles.scss @@ -4,6 +4,7 @@ @use 'styles/colors'; @use 'styles/buttons'; @use 'styles/form-controls'; +@use 'styles/tabs'; @use 'styles/dialog'; @use 'styles/functions' as *; @use 'styles/toast'; diff --git a/portal-frontend/src/styles/tabs.scss b/portal-frontend/src/styles/tabs.scss new file mode 100644 index 0000000000..1cd3a55f52 --- /dev/null +++ b/portal-frontend/src/styles/tabs.scss @@ -0,0 +1,60 @@ +@use 'colors'; +@use 'functions' as *; + +.mdc-tab { + --border-color: #e0e0e0; + + background: color-mix(in srgb, colors.$secondary-color-light, transparent 80%) !important; + border: 1px solid var(--border-color) !important; + + &:hover { + background: color-mix(in srgb, colors.$black, transparent 88%) !important; + } + + & .mdc-tab__text-label { + font-size: rem(15) !important; + font-weight: bold !important; + + @media screen and (min-width: $tabletBreakpoint) { + font-size: rem(18) !important; + } + } + + & .mat-ripple-element { + background-color: colors.$secondary-color !important; + } + + // Hack needed to prevent lingering green cast + & .mdc-tab__ripple::before { + background-color: white !important; + } + + &:not(:first-child) { + border-left: none !important; + } +} + +.mdc-tab--active { + background: white !important; + border-bottom: none !important; + + &:first-child { + border-left-color: white !important; + } + + &:last-child { + border-right-color: white !important; + } + + & .mdc-tab__text-label { + color: colors.$secondary-color !important; + } +} + +.mdc-tab-indicator__content--underline { + border: 0 !important; +} + +.mat-mdc-tab-body { + padding-top: rem(24) !important; +} diff --git a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.spec.ts b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.spec.ts index c0a4f19563..249b4691df 100644 --- a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.spec.ts +++ b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.spec.ts @@ -194,6 +194,46 @@ describe('ApplicationDecisionComponentService', () => { expect(result[0].applicationDecisionComponentTypeCode).toEqual('fake_code'); }); + it('should update only changed fields in DTO for a given UID', async() => { + mockApplicationDecisionComponentRepository.findOneOrFail.mockResolvedValue({ + uuid: 'fake', + applicationDecisionComponentTypeCode: 'fake_code', + alrArea: 1, + agCap: '2', + agCapSource: '3', + agCapMap: '4', + agCapConsultant: '5', + endDate: new Date(0), + } as ApplicationDecisionComponent); + + const mockDto = new CreateApplicationDecisionComponentDto(); + mockDto.uuid = 'fake'; + mockDto.alrArea = 10; + mockDto.applicationDecisionComponentTypeCode = 'should_not_beUpdated'; + + const result = await service.createOrUpdate([mockDto], false); + expect(result).toBeDefined(); + expect(result.length).toBe(1); + expect(mockApplicationDecisionComponentRepository.findOneOrFail).toHaveBeenCalledTimes(1); + expect(mockApplicationDecisionComponentRepository.findOneOrFail) + .toHaveBeenCalledWith({ + where: { uuid: 'fake' }, + relations: { + lots: true, + }, + }); + + expect(result[0].uuid).toEqual(mockDto.uuid); + expect(result[0].alrArea).toEqual(mockDto.alrArea); + expect(result[0].agCap).toEqual('2'); + expect(result[0].agCapSource).toEqual('3'); + expect(result[0].agCapMap).toEqual('4'); + expect(result[0].agCapConsultant).toEqual('5'); + expect(result[0].endDate).toEqual(new Date(0)); + expect(result[0].applicationDecisionComponentTypeCode).toEqual('fake_code'); + + }); + it('should persist entity if persist flag is true', async () => { mockApplicationDecisionComponentRepository.findOneOrFail.mockResolvedValue( {} as ApplicationDecisionComponent, diff --git a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.ts b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.ts index 9daf1d4651..bafe559735 100644 --- a/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.ts +++ b/services/apps/alcs/src/alcs/application-decision/application-decision-v2/application-decision/component/application-decision-component.service.ts @@ -9,6 +9,8 @@ import { CreateApplicationDecisionComponentDto, } from './application-decision-component.dto'; import { ApplicationDecisionComponent } from './application-decision-component.entity'; +import { filterUndefined } from '../../../../../utils/undefined'; +import { formatIncomingDate } from '../../../../../utils/incoming-date.formatter'; @Injectable() export class ApplicationDecisionComponentService { @@ -44,14 +46,30 @@ export class ApplicationDecisionComponentService { updateDto.applicationDecisionComponentTypeCode; } - component.alrArea = updateDto.alrArea; - component.agCap = updateDto.agCap; - component.agCapSource = updateDto.agCapSource; - component.agCapMap = updateDto.agCapMap; - component.agCapConsultant = updateDto.agCapConsultant; - component.endDate2 = updateDto.endDate2 - ? new Date(updateDto.endDate2) - : null; + component.alrArea = filterUndefined( + updateDto.alrArea, + component.alrArea + ); + component.agCap = filterUndefined( + updateDto.agCap, + component.agCap + ); + component.agCapSource = filterUndefined( + updateDto.agCapSource, + component.agCapSource + ); + component.agCapMap = filterUndefined( + updateDto.agCapMap, + component.agCapMap + ); + component.agCapConsultant = filterUndefined( + updateDto.agCapConsultant, + component.agCapConsultant + ); + component.endDate2 = filterUndefined( + formatIncomingDate(updateDto.endDate2), + component.endDate2 + ); this.patchNfuFields(component, updateDto); this.patchTurpFields(component, updateDto); @@ -65,9 +83,10 @@ export class ApplicationDecisionComponentService { //INCL / EXCL if (updateDto.inclExclApplicantType !== undefined) { component.inclExclApplicantType = updateDto.inclExclApplicantType; - component.expiryDate = updateDto.expiryDate - ? new Date(updateDto.expiryDate) - : null; + component.expiryDate = filterUndefined( + formatIncomingDate(updateDto.expiryDate), + component.expiryDate + ); } updatedComponents.push(component); @@ -138,56 +157,102 @@ export class ApplicationDecisionComponentService { component: ApplicationDecisionComponent, updateDto: CreateApplicationDecisionComponentDto, ) { - component.endDate = updateDto.endDate ? new Date(updateDto.endDate) : null; - component.nfuSubType = updateDto.nfuSubType; - component.nfuType = updateDto.nfuType; + component.endDate = filterUndefined( + formatIncomingDate(updateDto.endDate), + component.endDate + ); + component.nfuSubType = filterUndefined( + updateDto.nfuSubType, + component.nfuSubType + ); + component.nfuType = filterUndefined( + updateDto.nfuType, + component.nfuType + ); } private patchTurpFields( component: ApplicationDecisionComponent, updateDto: CreateApplicationDecisionComponentDto, ) { - component.expiryDate = updateDto.expiryDate - ? new Date(updateDto.expiryDate) - : null; + component.expiryDate = filterUndefined( + formatIncomingDate(updateDto.expiryDate), + component.expiryDate + ); } private patchPofoFields( component: ApplicationDecisionComponent, updateDto: CreateApplicationDecisionComponentDto, ) { - component.endDate = updateDto.endDate ? new Date(updateDto.endDate) : null; - component.soilFillTypeToPlace = updateDto.soilFillTypeToPlace ?? null; - component.soilToPlaceArea = updateDto.soilToPlaceArea ?? null; - component.soilToPlaceVolume = updateDto.soilToPlaceVolume ?? null; - component.soilToPlaceMaximumDepth = - updateDto.soilToPlaceMaximumDepth ?? null; - component.soilToPlaceAverageDepth = - updateDto.soilToPlaceAverageDepth ?? null; + component.endDate = filterUndefined( + formatIncomingDate(updateDto.endDate), + component.endDate + ); + component.soilFillTypeToPlace = filterUndefined( + updateDto.soilFillTypeToPlace, + component.soilFillTypeToPlace + ); + component.soilToPlaceArea = filterUndefined( + updateDto.soilToPlaceArea, + component.soilToPlaceArea + ); + component.soilToPlaceVolume = filterUndefined( + updateDto.soilToPlaceVolume, + component.soilToPlaceVolume + ); + component.soilToPlaceMaximumDepth = filterUndefined( + updateDto.soilToPlaceMaximumDepth, + component.soilToPlaceMaximumDepth + ); + component.soilToPlaceAverageDepth = filterUndefined( + updateDto.soilToPlaceAverageDepth, + component.soilToPlaceAverageDepth + ); } private patchRosoFields( component: ApplicationDecisionComponent, updateDto: CreateApplicationDecisionComponentDto, ) { - component.endDate = updateDto.endDate ? new Date(updateDto.endDate) : null; - component.soilTypeRemoved = updateDto.soilTypeRemoved ?? null; - component.soilToRemoveVolume = updateDto.soilToRemoveVolume ?? null; - component.soilToRemoveArea = updateDto.soilToRemoveArea ?? null; - component.soilToRemoveMaximumDepth = - updateDto.soilToRemoveMaximumDepth ?? null; - component.soilToRemoveAverageDepth = - updateDto.soilToRemoveAverageDepth ?? null; + component.endDate = filterUndefined( + formatIncomingDate(updateDto.endDate), + component.endDate + ); + component.soilTypeRemoved = filterUndefined( + updateDto.soilTypeRemoved, + component.soilTypeRemoved + ); + component.soilToRemoveVolume = filterUndefined( + updateDto.soilToRemoveVolume, + component.soilToRemoveVolume + ); + component.soilToRemoveArea = filterUndefined( + updateDto.soilToRemoveArea, + component.soilToRemoveArea + ); + component.soilToRemoveMaximumDepth = filterUndefined( + updateDto.soilToRemoveMaximumDepth, + component.soilToRemoveMaximumDepth + ); + component.soilToRemoveAverageDepth = filterUndefined( + updateDto.soilToRemoveAverageDepth, + component.soilToRemoveAverageDepth + ); } private patchNaruFields( component: ApplicationDecisionComponent, updateDto: CreateApplicationDecisionComponentDto, ) { - component.endDate = updateDto.endDate ? new Date(updateDto.endDate) : null; - component.expiryDate = updateDto.expiryDate - ? new Date(updateDto.expiryDate) - : null; + component.endDate = filterUndefined( + formatIncomingDate(updateDto.endDate), + component.endDate + ); + component.expiryDate = filterUndefined( + formatIncomingDate(updateDto.expiryDate), + component.expiryDate + ); component.naruSubtypeCode = updateDto.naruSubtypeCode; } diff --git a/services/apps/alcs/src/alcs/application/application-submission/application-submission.dto.ts b/services/apps/alcs/src/alcs/application/application-submission/application-submission.dto.ts index fe1f3728b7..6b9b71a6c7 100644 --- a/services/apps/alcs/src/alcs/application/application-submission/application-submission.dto.ts +++ b/services/apps/alcs/src/alcs/application/application-submission/application-submission.dto.ts @@ -9,4 +9,8 @@ export class AlcsApplicationSubmissionUpdateDto { @IsString() @IsOptional() returnComment?: string; + + @IsString() + @IsOptional() + applicant?: string; } diff --git a/services/apps/alcs/src/alcs/application/application-submission/application-submission.service.ts b/services/apps/alcs/src/alcs/application/application-submission/application-submission.service.ts index 202108a3b9..57922738fa 100644 --- a/services/apps/alcs/src/alcs/application/application-submission/application-submission.service.ts +++ b/services/apps/alcs/src/alcs/application/application-submission/application-submission.service.ts @@ -121,6 +121,10 @@ export class ApplicationSubmissionService { updateDto.returnComment, submission.returnedToLfngComment, ); + submission.applicant = filterUndefined( + updateDto.applicant, + submission.applicant, + ); await this.applicationSubmissionRepository.save(submission); } diff --git a/services/apps/alcs/src/alcs/notification/notification.service.spec.ts b/services/apps/alcs/src/alcs/notification/notification.service.spec.ts index 9cb71ada4b..9d5ebaa814 100644 --- a/services/apps/alcs/src/alcs/notification/notification.service.spec.ts +++ b/services/apps/alcs/src/alcs/notification/notification.service.spec.ts @@ -285,12 +285,5 @@ describe('NotificationService', () => { undefined, 'noti', ); - expect(mockSubtaskService.create).toHaveBeenCalledTimes(1); - expect(mockSubtaskService.create).toHaveBeenCalledWith( - new Card({ - typeCode: CARD_TYPE.NOTIFICATION, - }), - CARD_SUBTASK_TYPE.GIS, - ); }); }); diff --git a/services/apps/alcs/src/alcs/notification/notification.service.ts b/services/apps/alcs/src/alcs/notification/notification.service.ts index a9dabf3155..8119b5717c 100644 --- a/services/apps/alcs/src/alcs/notification/notification.service.ts +++ b/services/apps/alcs/src/alcs/notification/notification.service.ts @@ -329,11 +329,6 @@ export class NotificationService { const finalNotification = await this.getByFileNumber(createDto.fileNumber); - await this.subtaskService.create( - finalNotification.card!, - CARD_SUBTASK_TYPE.GIS, - ); - return finalNotification; } diff --git a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts index 17450524cc..d65c2ca7c9 100644 --- a/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts +++ b/services/apps/alcs/src/alcs/search/notice-of-intent/notice-of-intent-search-view.entity.ts @@ -54,7 +54,8 @@ export class SearchNoticeOfIntentSubmissionStatusType { LocalGovernment, 'localGovernment', 'nois.local_government_uuid = localGovernment.uuid', - ), + ) + .where(`nois.is_draft IS NOT TRUE`), }) export class NoticeOfIntentSubmissionSearchView { @ViewColumn() diff --git a/services/apps/alcs/src/portal/inbox/application/inbox-application-view.entity.ts b/services/apps/alcs/src/portal/inbox/application/inbox-application-view.entity.ts index 4acad2ba3a..5ec15a7d76 100644 --- a/services/apps/alcs/src/portal/inbox/application/inbox-application-view.entity.ts +++ b/services/apps/alcs/src/portal/inbox/application/inbox-application-view.entity.ts @@ -42,6 +42,7 @@ import { LinkedStatusType } from '../inbox.dto'; .from(ApplicationSubmissionToSubmissionStatus, 'status_link') .select('MAX("effective_date")', 'effective_date') .addSelect('submission_uuid', 'submission_uuid') + .where('effective_date <= NOW()') .groupBy('submission_uuid'), 'status_link', 'status_link."submission_uuid" = app_sub.uuid', @@ -52,6 +53,7 @@ import { LinkedStatusType } from '../inbox.dto'; .from(ApplicationDecision, 'decision_date') .select('MAX("date")', 'date') .addSelect('application_uuid', 'application_uuid') + .where('date <= NOW()') .groupBy('application_uuid'), 'decision_date', 'decision_date."application_uuid" = app.uuid', diff --git a/services/apps/alcs/src/portal/inbox/notice-of-intent/inbox-notice-of-intent-view.entity.ts b/services/apps/alcs/src/portal/inbox/notice-of-intent/inbox-notice-of-intent-view.entity.ts index c4357e32b6..100d861084 100644 --- a/services/apps/alcs/src/portal/inbox/notice-of-intent/inbox-notice-of-intent-view.entity.ts +++ b/services/apps/alcs/src/portal/inbox/notice-of-intent/inbox-notice-of-intent-view.entity.ts @@ -42,6 +42,7 @@ import { LinkedStatusType } from '../inbox.dto'; .from(NoticeOfIntentSubmissionToSubmissionStatus, 'status_link') .select('MAX("effective_date")', 'effective_date') .addSelect('submission_uuid', 'submission_uuid') + .where('effective_date <= NOW()') .groupBy('submission_uuid'), 'status_link', 'status_link."submission_uuid" = noi_sub.uuid', @@ -52,6 +53,7 @@ import { LinkedStatusType } from '../inbox.dto'; .from(NoticeOfIntentDecision, 'decision_date') .select('MAX("date")', 'date') .addSelect('notice_of_intent_uuid', 'notice_of_intent_uuid') + .where('date <= NOW()') .groupBy('notice_of_intent_uuid'), 'decision_date', 'decision_date."notice_of_intent_uuid" = noi.uuid', diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts index 4929787c7c..4b8f7c0bb6 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts @@ -422,6 +422,7 @@ export class NotificationSubmissionService { subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, parentType: PARENT_TYPE.NOTIFICATION, parentId: templateData.parentId, + triggerStatus: NOTIFICATION_STATUS.SUBMITTED_TO_ALC, cc: templateData.cc, attachments: [document.document], }); diff --git a/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts b/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts index 6f0a112b0d..51ef373d1e 100644 --- a/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts +++ b/services/apps/alcs/src/portal/public/search/application/public-application-search-view.entity.ts @@ -43,6 +43,7 @@ import { LinkedStatusType } from '../public-search.dto'; .from(ApplicationSubmissionToSubmissionStatus, 'status_link') .select('MAX("effective_date")', 'effective_date') .addSelect('submission_uuid', 'submission_uuid') + .where('effective_date <= NOW()') .groupBy('submission_uuid'), 'status_link', 'status_link."submission_uuid" = app_sub.uuid', @@ -66,6 +67,7 @@ import { LinkedStatusType } from '../public-search.dto'; 'dest_rank', ) .where('is_draft = FALSE') + .andWhere('date <= NOW()') .from(ApplicationDecision, 'decision') .getQuery(), 'decisions', diff --git a/services/apps/alcs/src/portal/public/search/notice-of-intent/public-notice-of-intent-search-view.entity.ts b/services/apps/alcs/src/portal/public/search/notice-of-intent/public-notice-of-intent-search-view.entity.ts index 5737844e66..01ec21224b 100644 --- a/services/apps/alcs/src/portal/public/search/notice-of-intent/public-notice-of-intent-search-view.entity.ts +++ b/services/apps/alcs/src/portal/public/search/notice-of-intent/public-notice-of-intent-search-view.entity.ts @@ -43,6 +43,7 @@ import { LinkedStatusType } from '../public-search.dto'; .from(NoticeOfIntentSubmissionToSubmissionStatus, 'status_link') .select('MAX("effective_date")', 'effective_date') .addSelect('submission_uuid', 'submission_uuid') + .where('effective_date <= NOW()') .groupBy('submission_uuid'), 'status_link', 'status_link."submission_uuid" = noi_sub.uuid', @@ -66,6 +67,7 @@ import { LinkedStatusType } from '../public-search.dto'; 'dest_rank', ) .where('is_draft = FALSE') + .andWhere('date <= NOW()') .from(NoticeOfIntentDecision, 'decision') .getQuery(), 'decisions', diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1717704842461-filter_draft_nois_in_search_view.ts b/services/apps/alcs/src/providers/typeorm/migrations/1717704842461-filter_draft_nois_in_search_view.ts new file mode 100644 index 0000000000..978683063a --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1717704842461-filter_draft_nois_in_search_view.ts @@ -0,0 +1,20 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FilterDraftNoisInSearchView1717704842461 implements MigrationInterface { + name = 'FilterDraftNoisInSearchView1717704842461' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notice_of_intent_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."notice_of_intent_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."notice_of_intent_submission_search_view" AS SELECT "nois"."uuid" AS "uuid", "nois"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noticeOfIntentType"."audit_deleted_date_at" AS "noticeOfIntentType_audit_deleted_date_at", "noticeOfIntentType"."audit_created_at" AS "noticeOfIntentType_audit_created_at", "noticeOfIntentType"."audit_updated_at" AS "noticeOfIntentType_audit_updated_at", "noticeOfIntentType"."audit_created_by" AS "noticeOfIntentType_audit_created_by", "noticeOfIntentType"."audit_updated_by" AS "noticeOfIntentType_audit_updated_by", "noticeOfIntentType"."label" AS "noticeOfIntentType_label", "noticeOfIntentType"."code" AS "noticeOfIntentType_code", "noticeOfIntentType"."description" AS "noticeOfIntentType_description", "noticeOfIntentType"."short_label" AS "noticeOfIntentType_short_label", "noticeOfIntentType"."background_color" AS "noticeOfIntentType_background_color", "noticeOfIntentType"."text_color" AS "noticeOfIntentType_text_color", "noticeOfIntentType"."html_description" AS "noticeOfIntentType_html_description", "noticeOfIntentType"."portal_label" AS "noticeOfIntentType_portal_label", "noticeOfIntentType"."alc_fee_amount" AS "noticeOfIntentType_alc_fee_amount", "noticeOfIntentType"."government_fee_amount" AS "noticeOfIntentType_government_fee_amount", "localGovernment"."name" AS "local_government_name", "nois"."file_number" AS "file_number", "nois"."local_government_uuid" AS "local_government_uuid", "nois"."type_code" AS "notice_of_intent_type_code", "nois"."is_draft" AS "is_draft", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", "noi"."legacy_id" AS "legacy_id", "noi"."decision_date" AS "decision_date", "noi"."region_code" AS "notice_of_intent_region_code", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("nois"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "nois" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "nois"."file_number" AND "noi"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notice_of_intent_type" "noticeOfIntentType" ON "nois"."type_code" = "noticeOfIntentType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "nois"."local_government_uuid" = "localGovernment"."uuid" WHERE "nois"."is_draft" IS NOT TRUE`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notice_of_intent_submission_search_view","SELECT \"nois\".\"uuid\" AS \"uuid\", \"nois\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noticeOfIntentType\".\"audit_deleted_date_at\" AS \"noticeOfIntentType_audit_deleted_date_at\", \"noticeOfIntentType\".\"audit_created_at\" AS \"noticeOfIntentType_audit_created_at\", \"noticeOfIntentType\".\"audit_updated_at\" AS \"noticeOfIntentType_audit_updated_at\", \"noticeOfIntentType\".\"audit_created_by\" AS \"noticeOfIntentType_audit_created_by\", \"noticeOfIntentType\".\"audit_updated_by\" AS \"noticeOfIntentType_audit_updated_by\", \"noticeOfIntentType\".\"label\" AS \"noticeOfIntentType_label\", \"noticeOfIntentType\".\"code\" AS \"noticeOfIntentType_code\", \"noticeOfIntentType\".\"description\" AS \"noticeOfIntentType_description\", \"noticeOfIntentType\".\"short_label\" AS \"noticeOfIntentType_short_label\", \"noticeOfIntentType\".\"background_color\" AS \"noticeOfIntentType_background_color\", \"noticeOfIntentType\".\"text_color\" AS \"noticeOfIntentType_text_color\", \"noticeOfIntentType\".\"html_description\" AS \"noticeOfIntentType_html_description\", \"noticeOfIntentType\".\"portal_label\" AS \"noticeOfIntentType_portal_label\", \"noticeOfIntentType\".\"alc_fee_amount\" AS \"noticeOfIntentType_alc_fee_amount\", \"noticeOfIntentType\".\"government_fee_amount\" AS \"noticeOfIntentType_government_fee_amount\", \"localGovernment\".\"name\" AS \"local_government_name\", \"nois\".\"file_number\" AS \"file_number\", \"nois\".\"local_government_uuid\" AS \"local_government_uuid\", \"nois\".\"type_code\" AS \"notice_of_intent_type_code\", \"nois\".\"is_draft\" AS \"is_draft\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noi\".\"legacy_id\" AS \"legacy_id\", \"noi\".\"decision_date\" AS \"decision_date\", \"noi\".\"region_code\" AS \"notice_of_intent_region_code\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"nois\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"nois\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"nois\".\"file_number\" AND \"noi\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notice_of_intent_type\" \"noticeOfIntentType\" ON \"nois\".\"type_code\" = \"noticeOfIntentType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"nois\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" WHERE \"nois\".\"is_draft\" IS NOT TRUE"]); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","notice_of_intent_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."notice_of_intent_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."notice_of_intent_submission_search_view" AS SELECT "nois"."uuid" AS "uuid", "nois"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noticeOfIntentType"."audit_deleted_date_at" AS "noticeOfIntentType_audit_deleted_date_at", "noticeOfIntentType"."audit_created_at" AS "noticeOfIntentType_audit_created_at", "noticeOfIntentType"."audit_updated_at" AS "noticeOfIntentType_audit_updated_at", "noticeOfIntentType"."audit_created_by" AS "noticeOfIntentType_audit_created_by", "noticeOfIntentType"."audit_updated_by" AS "noticeOfIntentType_audit_updated_by", "noticeOfIntentType"."label" AS "noticeOfIntentType_label", "noticeOfIntentType"."code" AS "noticeOfIntentType_code", "noticeOfIntentType"."description" AS "noticeOfIntentType_description", "noticeOfIntentType"."short_label" AS "noticeOfIntentType_short_label", "noticeOfIntentType"."background_color" AS "noticeOfIntentType_background_color", "noticeOfIntentType"."text_color" AS "noticeOfIntentType_text_color", "noticeOfIntentType"."html_description" AS "noticeOfIntentType_html_description", "noticeOfIntentType"."portal_label" AS "noticeOfIntentType_portal_label", "noticeOfIntentType"."alc_fee_amount" AS "noticeOfIntentType_alc_fee_amount", "noticeOfIntentType"."government_fee_amount" AS "noticeOfIntentType_government_fee_amount", "localGovernment"."name" AS "local_government_name", "nois"."file_number" AS "file_number", "nois"."local_government_uuid" AS "local_government_uuid", "nois"."type_code" AS "notice_of_intent_type_code", "nois"."is_draft" AS "is_draft", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", "noi"."legacy_id" AS "legacy_id", "noi"."decision_date" AS "decision_date", "noi"."region_code" AS "notice_of_intent_region_code", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("nois"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "nois" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "nois"."file_number" AND "noi"."audit_deleted_date_at" IS NULL INNER JOIN "alcs"."notice_of_intent_type" "noticeOfIntentType" ON "nois"."type_code" = "noticeOfIntentType"."code" LEFT JOIN "alcs"."local_government" "localGovernment" ON "nois"."local_government_uuid" = "localGovernment"."uuid"`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","notice_of_intent_submission_search_view","SELECT \"nois\".\"uuid\" AS \"uuid\", \"nois\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noticeOfIntentType\".\"audit_deleted_date_at\" AS \"noticeOfIntentType_audit_deleted_date_at\", \"noticeOfIntentType\".\"audit_created_at\" AS \"noticeOfIntentType_audit_created_at\", \"noticeOfIntentType\".\"audit_updated_at\" AS \"noticeOfIntentType_audit_updated_at\", \"noticeOfIntentType\".\"audit_created_by\" AS \"noticeOfIntentType_audit_created_by\", \"noticeOfIntentType\".\"audit_updated_by\" AS \"noticeOfIntentType_audit_updated_by\", \"noticeOfIntentType\".\"label\" AS \"noticeOfIntentType_label\", \"noticeOfIntentType\".\"code\" AS \"noticeOfIntentType_code\", \"noticeOfIntentType\".\"description\" AS \"noticeOfIntentType_description\", \"noticeOfIntentType\".\"short_label\" AS \"noticeOfIntentType_short_label\", \"noticeOfIntentType\".\"background_color\" AS \"noticeOfIntentType_background_color\", \"noticeOfIntentType\".\"text_color\" AS \"noticeOfIntentType_text_color\", \"noticeOfIntentType\".\"html_description\" AS \"noticeOfIntentType_html_description\", \"noticeOfIntentType\".\"portal_label\" AS \"noticeOfIntentType_portal_label\", \"noticeOfIntentType\".\"alc_fee_amount\" AS \"noticeOfIntentType_alc_fee_amount\", \"noticeOfIntentType\".\"government_fee_amount\" AS \"noticeOfIntentType_government_fee_amount\", \"localGovernment\".\"name\" AS \"local_government_name\", \"nois\".\"file_number\" AS \"file_number\", \"nois\".\"local_government_uuid\" AS \"local_government_uuid\", \"nois\".\"type_code\" AS \"notice_of_intent_type_code\", \"nois\".\"is_draft\" AS \"is_draft\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", \"noi\".\"legacy_id\" AS \"legacy_id\", \"noi\".\"decision_date\" AS \"decision_date\", \"noi\".\"region_code\" AS \"notice_of_intent_region_code\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"nois\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"nois\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"nois\".\"file_number\" AND \"noi\".\"audit_deleted_date_at\" IS NULL INNER JOIN \"alcs\".\"notice_of_intent_type\" \"noticeOfIntentType\" ON \"nois\".\"type_code\" = \"noticeOfIntentType\".\"code\" LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"nois\".\"local_government_uuid\" = \"localGovernment\".\"uuid\""]); + } + +} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1719348665533-add_notification_trigger_statuses.ts b/services/apps/alcs/src/providers/typeorm/migrations/1719348665533-add_notification_trigger_statuses.ts new file mode 100644 index 0000000000..07b5168d4b --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1719348665533-add_notification_trigger_statuses.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddNotificationTriggerStatuses1719348665533 + implements MigrationInterface +{ + public async up(queryRunner: QueryRunner): Promise { + queryRunner.query(` + UPDATE alcs.email_status es + SET trigger_status = 'SUBM' + WHERE es.parent_type = 'notification' + `); + } + + public async down(queryRunner: QueryRunner): Promise { + // N/A + } +} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1719506636796-remove_incomplete_gis_subtasks.ts b/services/apps/alcs/src/providers/typeorm/migrations/1719506636796-remove_incomplete_gis_subtasks.ts new file mode 100644 index 0000000000..de8ea74d4c --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1719506636796-remove_incomplete_gis_subtasks.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class RemoveIncompleteGisSubtasks1719506636796 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + queryRunner.query(` + DELETE FROM alcs.card_subtask + USING alcs.notification + WHERE alcs.card_subtask.card_uuid = alcs.notification.card_uuid + AND alcs.card_subtask.type_code = 'GIS' + AND alcs.card_subtask.completed_at IS NULL + AND alcs.card_subtask.audit_created_by = 'alcs-api'; + `); + } + + public async down(queryRunner: QueryRunner): Promise { + } +} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1720646632282-fix_public_search_status_date.ts b/services/apps/alcs/src/providers/typeorm/migrations/1720646632282-fix_public_search_status_date.ts new file mode 100644 index 0000000000..ce1ec84360 --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1720646632282-fix_public_search_status_date.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FixPublicSearchStatusDate1720646632282 implements MigrationInterface { + name = 'FixPublicSearchStatusDate1720646632282' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","public_notice_of_intent_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_notice_of_intent_submission_search_view"`); + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","public_application_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_application_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."public_notice_of_intent_submission_search_view" AS SELECT "noi_sub"."uuid" AS "uuid", "noi_sub"."applicant" AS "applicant", "localGovernment"."name" AS "local_government_name", "noi_sub"."file_number" AS "file_number", "noi_sub"."type_code" AS "notice_of_intent_type_code", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", decision_date.outcome AS "outcome", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "noi_sub" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "noi_sub"."file_number" AND "noi"."hide_from_portal" = FALSE AND "noi"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "noi_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."notice_of_intent_submission_to_submission_status" "status_link" WHERE effective_date <= NOW() GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "noi_sub"."uuid" LEFT JOIN (SELECT DISTINCT ON (notice_of_intentuuid) decisiondate AS "date", outcome AS "outcome", dest_rank AS "dest_rank", notice_of_intentuuid AS "notice_of_intent_uuid" FROM (SELECT outcome_code AS "outcome", date AS "decisiondate", notice_of_intent_uuid AS "notice_of_intentuuid", RANK() OVER (PARTITION BY notice_of_intent_uuid ORDER BY date DESC, audit_created_at DESC) AS "dest_rank" FROM "alcs"."notice_of_intent_decision" "decision" WHERE ( is_draft = FALSE AND date <= NOW() ) AND ( "decision"."audit_deleted_date_at" IS NULL )) "decisions" WHERE dest_rank = 1) "decision_date" ON decision_date."notice_of_intent_uuid" = "noi"."uuid" WHERE ( "noi_sub"."is_draft" = FALSE AND ("noi"."date_received_all_items" IS NOT NULL AND "noi"."date_received_all_items" <= NOW()) AND alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid")->>'status_type_code' != 'CANC' ) AND ( "noi_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","public_notice_of_intent_submission_search_view","SELECT \"noi_sub\".\"uuid\" AS \"uuid\", \"noi_sub\".\"applicant\" AS \"applicant\", \"localGovernment\".\"name\" AS \"local_government_name\", \"noi_sub\".\"file_number\" AS \"file_number\", \"noi_sub\".\"type_code\" AS \"notice_of_intent_type_code\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", decision_date.outcome AS \"outcome\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"noi_sub\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"noi_sub\".\"file_number\" AND \"noi\".\"hide_from_portal\" = FALSE AND \"noi\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"noi_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"notice_of_intent_submission_to_submission_status\" \"status_link\" WHERE effective_date <= NOW() GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"noi_sub\".\"uuid\" LEFT JOIN (SELECT DISTINCT ON (notice_of_intentuuid) decisiondate AS \"date\", outcome AS \"outcome\", dest_rank AS \"dest_rank\", notice_of_intentuuid AS \"notice_of_intent_uuid\" FROM (SELECT outcome_code AS \"outcome\", date AS \"decisiondate\", notice_of_intent_uuid AS \"notice_of_intentuuid\", RANK() OVER (PARTITION BY notice_of_intent_uuid ORDER BY date DESC, audit_created_at DESC) AS \"dest_rank\" FROM \"alcs\".\"notice_of_intent_decision\" \"decision\" WHERE ( is_draft = FALSE AND date <= NOW() ) AND ( \"decision\".\"audit_deleted_date_at\" IS NULL )) \"decisions\" WHERE dest_rank = 1) \"decision_date\" ON decision_date.\"notice_of_intent_uuid\" = \"noi\".\"uuid\" WHERE ( \"noi_sub\".\"is_draft\" = FALSE AND (\"noi\".\"date_received_all_items\" IS NOT NULL AND \"noi\".\"date_received_all_items\" <= NOW()) AND alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\")->>'status_type_code' != 'CANC' ) AND ( \"noi_sub\".\"audit_deleted_date_at\" IS NULL )"]); + await queryRunner.query(`CREATE VIEW "alcs"."public_application_submission_search_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "localGovernment"."name" AS "local_government_name", "app_sub"."file_number" AS "file_number", "app_sub"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", decision_date.outcome AS "outcome", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."hide_from_portal" = FALSE AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "app_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."application_submission_to_submission_status" "status_link" WHERE effective_date <= NOW() GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "app_sub"."uuid" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS "date", outcome AS "outcome", dest_rank AS "dest_rank", applicationuuid AS "application_uuid" FROM (SELECT outcome_code AS "outcome", date AS "decisiondate", application_uuid AS "applicationuuid", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS "dest_rank" FROM "alcs"."application_decision" "decision" WHERE ( is_draft = FALSE AND date <= NOW() ) AND ( "decision"."audit_deleted_date_at" IS NULL )) "decisions" WHERE dest_rank = 1) "decision_date" ON decision_date."application_uuid" = "app"."uuid" WHERE ( "app_sub"."is_draft" = FALSE AND ("app"."date_received_all_items" IS NOT NULL AND "app"."date_received_all_items" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid")->>'status_type_code' != 'CANC' ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","public_application_submission_search_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"localGovernment\".\"name\" AS \"local_government_name\", \"app_sub\".\"file_number\" AS \"file_number\", \"app_sub\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", decision_date.outcome AS \"outcome\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"hide_from_portal\" = FALSE AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"app_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"application_submission_to_submission_status\" \"status_link\" WHERE effective_date <= NOW() GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"app_sub\".\"uuid\" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS \"date\", outcome AS \"outcome\", dest_rank AS \"dest_rank\", applicationuuid AS \"application_uuid\" FROM (SELECT outcome_code AS \"outcome\", date AS \"decisiondate\", application_uuid AS \"applicationuuid\", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS \"dest_rank\" FROM \"alcs\".\"application_decision\" \"decision\" WHERE ( is_draft = FALSE AND date <= NOW() ) AND ( \"decision\".\"audit_deleted_date_at\" IS NULL )) \"decisions\" WHERE dest_rank = 1) \"decision_date\" ON decision_date.\"application_uuid\" = \"app\".\"uuid\" WHERE ( \"app_sub\".\"is_draft\" = FALSE AND (\"app\".\"date_received_all_items\" IS NOT NULL AND \"app\".\"date_received_all_items\" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\")->>'status_type_code' != 'CANC' ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","public_application_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_application_submission_search_view"`); + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","public_notice_of_intent_submission_search_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."public_notice_of_intent_submission_search_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."public_application_submission_search_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "localGovernment"."name" AS "local_government_name", "app_sub"."file_number" AS "file_number", "app_sub"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", decision_date.outcome AS "outcome", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."hide_from_portal" = FALSE AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "app_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."application_submission_to_submission_status" "status_link" GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "app_sub"."uuid" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS "date", outcome AS "outcome", dest_rank AS "dest_rank", applicationuuid AS "application_uuid" FROM (SELECT outcome_code AS "outcome", date AS "decisiondate", application_uuid AS "applicationuuid", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS "dest_rank" FROM "alcs"."application_decision" "decision" WHERE ( is_draft = FALSE ) AND ( "decision"."audit_deleted_date_at" IS NULL )) "decisions" WHERE dest_rank = 1) "decision_date" ON decision_date."application_uuid" = "app"."uuid" WHERE ( "app_sub"."is_draft" = FALSE AND ("app"."date_received_all_items" IS NOT NULL AND "app"."date_received_all_items" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid")->>'status_type_code' != 'CANC' ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","public_application_submission_search_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"localGovernment\".\"name\" AS \"local_government_name\", \"app_sub\".\"file_number\" AS \"file_number\", \"app_sub\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", decision_date.outcome AS \"outcome\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"hide_from_portal\" = FALSE AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"app_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"application_submission_to_submission_status\" \"status_link\" GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"app_sub\".\"uuid\" LEFT JOIN (SELECT DISTINCT ON (application_uuid) decisiondate AS \"date\", outcome AS \"outcome\", dest_rank AS \"dest_rank\", applicationuuid AS \"application_uuid\" FROM (SELECT outcome_code AS \"outcome\", date AS \"decisiondate\", application_uuid AS \"applicationuuid\", RANK() OVER (PARTITION BY application_uuid ORDER BY date DESC, audit_created_at DESC) AS \"dest_rank\" FROM \"alcs\".\"application_decision\" \"decision\" WHERE ( is_draft = FALSE ) AND ( \"decision\".\"audit_deleted_date_at\" IS NULL )) \"decisions\" WHERE dest_rank = 1) \"decision_date\" ON decision_date.\"application_uuid\" = \"app\".\"uuid\" WHERE ( \"app_sub\".\"is_draft\" = FALSE AND (\"app\".\"date_received_all_items\" IS NOT NULL AND \"app\".\"date_received_all_items\" <= NOW()) AND alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\")->>'status_type_code' != 'CANC' ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); + await queryRunner.query(`CREATE VIEW "alcs"."public_notice_of_intent_submission_search_view" AS SELECT "noi_sub"."uuid" AS "uuid", "noi_sub"."applicant" AS "applicant", "localGovernment"."name" AS "local_government_name", "noi_sub"."file_number" AS "file_number", "noi_sub"."type_code" AS "notice_of_intent_type_code", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", decision_date.outcome AS "outcome", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "noi_sub" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "noi_sub"."file_number" AND "noi"."hide_from_portal" = FALSE AND "noi"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."local_government" "localGovernment" ON "noi_sub"."local_government_uuid" = "localGovernment"."uuid" AND "localGovernment"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."notice_of_intent_submission_to_submission_status" "status_link" GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "noi_sub"."uuid" LEFT JOIN (SELECT DISTINCT ON (notice_of_intentuuid) decisiondate AS "date", outcome AS "outcome", dest_rank AS "dest_rank", notice_of_intentuuid AS "notice_of_intent_uuid" FROM (SELECT outcome_code AS "outcome", date AS "decisiondate", notice_of_intent_uuid AS "notice_of_intentuuid", RANK() OVER (PARTITION BY notice_of_intent_uuid ORDER BY date DESC, audit_created_at DESC) AS "dest_rank" FROM "alcs"."notice_of_intent_decision" "decision" WHERE ( is_draft = FALSE ) AND ( "decision"."audit_deleted_date_at" IS NULL )) "decisions" WHERE dest_rank = 1) "decision_date" ON decision_date."notice_of_intent_uuid" = "noi"."uuid" WHERE ( "noi_sub"."is_draft" = FALSE AND ("noi"."date_received_all_items" IS NOT NULL AND "noi"."date_received_all_items" <= NOW()) AND alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid")->>'status_type_code' != 'CANC' ) AND ( "noi_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","public_notice_of_intent_submission_search_view","SELECT \"noi_sub\".\"uuid\" AS \"uuid\", \"noi_sub\".\"applicant\" AS \"applicant\", \"localGovernment\".\"name\" AS \"local_government_name\", \"noi_sub\".\"file_number\" AS \"file_number\", \"noi_sub\".\"type_code\" AS \"notice_of_intent_type_code\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", decision_date.outcome AS \"outcome\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"noi_sub\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"noi_sub\".\"file_number\" AND \"noi\".\"hide_from_portal\" = FALSE AND \"noi\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"local_government\" \"localGovernment\" ON \"noi_sub\".\"local_government_uuid\" = \"localGovernment\".\"uuid\" AND \"localGovernment\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"notice_of_intent_submission_to_submission_status\" \"status_link\" GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"noi_sub\".\"uuid\" LEFT JOIN (SELECT DISTINCT ON (notice_of_intentuuid) decisiondate AS \"date\", outcome AS \"outcome\", dest_rank AS \"dest_rank\", notice_of_intentuuid AS \"notice_of_intent_uuid\" FROM (SELECT outcome_code AS \"outcome\", date AS \"decisiondate\", notice_of_intent_uuid AS \"notice_of_intentuuid\", RANK() OVER (PARTITION BY notice_of_intent_uuid ORDER BY date DESC, audit_created_at DESC) AS \"dest_rank\" FROM \"alcs\".\"notice_of_intent_decision\" \"decision\" WHERE ( is_draft = FALSE ) AND ( \"decision\".\"audit_deleted_date_at\" IS NULL )) \"decisions\" WHERE dest_rank = 1) \"decision_date\" ON decision_date.\"notice_of_intent_uuid\" = \"noi\".\"uuid\" WHERE ( \"noi_sub\".\"is_draft\" = FALSE AND (\"noi\".\"date_received_all_items\" IS NOT NULL AND \"noi\".\"date_received_all_items\" <= NOW()) AND alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\")->>'status_type_code' != 'CANC' ) AND ( \"noi_sub\".\"audit_deleted_date_at\" IS NULL )"]); + } + +} diff --git a/services/apps/alcs/src/providers/typeorm/migrations/1720653385375-fix_portal_inbox_status_date.ts b/services/apps/alcs/src/providers/typeorm/migrations/1720653385375-fix_portal_inbox_status_date.ts new file mode 100644 index 0000000000..8b1af7a3af --- /dev/null +++ b/services/apps/alcs/src/providers/typeorm/migrations/1720653385375-fix_portal_inbox_status_date.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class FixPortalInboxStatusDate1720653385375 implements MigrationInterface { + name = 'FixPortalInboxStatusDate1720653385375' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","inbox_application_submission_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."inbox_application_submission_view"`); + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","inbox_notice_of_intent_submission_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."inbox_notice_of_intent_submission_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."inbox_notice_of_intent_submission_view" AS SELECT "noi_sub"."uuid" AS "uuid", "noi_sub"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noi_sub"."file_number" AS "file_number", "noi_sub"."audit_created_at" AS "created_at", "noi_sub"."created_by_uuid" AS "created_by_uuid", "noi_sub"."local_government_uuid" AS "local_government_uuid", "user"."bceid_business_guid" AS "bceid_business_guid", "noi_sub"."type_code" AS "notice_of_intent_type_code", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "noi_sub" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "noi_sub"."file_number" AND "noi"."hide_from_portal" = false AND "noi"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."user" "user" ON "user"."uuid" = "noi_sub"."created_by_uuid" AND "user"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."notice_of_intent_submission_to_submission_status" "status_link" WHERE effective_date <= NOW() GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "noi_sub"."uuid" LEFT JOIN (SELECT MAX("date") AS "date", notice_of_intent_uuid AS "notice_of_intent_uuid" FROM "alcs"."notice_of_intent_decision" "decision_date" WHERE ( date <= NOW() ) AND ( "decision_date"."audit_deleted_date_at" IS NULL ) GROUP BY notice_of_intent_uuid) "decision_date" ON decision_date."notice_of_intent_uuid" = "noi"."uuid" WHERE ( "noi_sub"."is_draft" = FALSE ) AND ( "noi_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","inbox_notice_of_intent_submission_view","SELECT \"noi_sub\".\"uuid\" AS \"uuid\", \"noi_sub\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noi_sub\".\"file_number\" AS \"file_number\", \"noi_sub\".\"audit_created_at\" AS \"created_at\", \"noi_sub\".\"created_by_uuid\" AS \"created_by_uuid\", \"noi_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"user\".\"bceid_business_guid\" AS \"bceid_business_guid\", \"noi_sub\".\"type_code\" AS \"notice_of_intent_type_code\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"noi_sub\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"noi_sub\".\"file_number\" AND \"noi\".\"hide_from_portal\" = false AND \"noi\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"user\" \"user\" ON \"user\".\"uuid\" = \"noi_sub\".\"created_by_uuid\" AND \"user\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"notice_of_intent_submission_to_submission_status\" \"status_link\" WHERE effective_date <= NOW() GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"noi_sub\".\"uuid\" LEFT JOIN (SELECT MAX(\"date\") AS \"date\", notice_of_intent_uuid AS \"notice_of_intent_uuid\" FROM \"alcs\".\"notice_of_intent_decision\" \"decision_date\" WHERE ( date <= NOW() ) AND ( \"decision_date\".\"audit_deleted_date_at\" IS NULL ) GROUP BY notice_of_intent_uuid) \"decision_date\" ON decision_date.\"notice_of_intent_uuid\" = \"noi\".\"uuid\" WHERE ( \"noi_sub\".\"is_draft\" = FALSE ) AND ( \"noi_sub\".\"audit_deleted_date_at\" IS NULL )"]); + await queryRunner.query(`CREATE VIEW "alcs"."inbox_application_submission_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "app"."uuid" AS "application_uuid", "app_sub"."file_number" AS "file_number", "app_sub"."created_by_uuid" AS "created_by_uuid", "app_sub"."local_government_uuid" AS "local_government_uuid", "app_sub"."audit_created_at" AS "created_at", "user"."bceid_business_guid" AS "bceid_business_guid", "app_sub"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."hide_from_portal" = FALSE AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."user" "user" ON "user"."uuid" = "app_sub"."created_by_uuid" AND "user"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."application_submission_to_submission_status" "status_link" WHERE effective_date <= NOW() GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "app_sub"."uuid" LEFT JOIN (SELECT MAX("date") AS "date", application_uuid AS "application_uuid" FROM "alcs"."application_decision" "decision_date" WHERE ( date <= NOW() ) AND ( "decision_date"."audit_deleted_date_at" IS NULL ) GROUP BY application_uuid) "decision_date" ON decision_date."application_uuid" = "app"."uuid" WHERE ( "app_sub"."is_draft" = FALSE ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","inbox_application_submission_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"app\".\"uuid\" AS \"application_uuid\", \"app_sub\".\"file_number\" AS \"file_number\", \"app_sub\".\"created_by_uuid\" AS \"created_by_uuid\", \"app_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"app_sub\".\"audit_created_at\" AS \"created_at\", \"user\".\"bceid_business_guid\" AS \"bceid_business_guid\", \"app_sub\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"hide_from_portal\" = FALSE AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"user\" \"user\" ON \"user\".\"uuid\" = \"app_sub\".\"created_by_uuid\" AND \"user\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"application_submission_to_submission_status\" \"status_link\" WHERE effective_date <= NOW() GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"app_sub\".\"uuid\" LEFT JOIN (SELECT MAX(\"date\") AS \"date\", application_uuid AS \"application_uuid\" FROM \"alcs\".\"application_decision\" \"decision_date\" WHERE ( date <= NOW() ) AND ( \"decision_date\".\"audit_deleted_date_at\" IS NULL ) GROUP BY application_uuid) \"decision_date\" ON decision_date.\"application_uuid\" = \"app\".\"uuid\" WHERE ( \"app_sub\".\"is_draft\" = FALSE ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","inbox_application_submission_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."inbox_application_submission_view"`); + await queryRunner.query(`DELETE FROM "alcs"."typeorm_metadata" WHERE "type" = $1 AND "name" = $2 AND "schema" = $3`, ["VIEW","inbox_notice_of_intent_submission_view","alcs"]); + await queryRunner.query(`DROP VIEW "alcs"."inbox_notice_of_intent_submission_view"`); + await queryRunner.query(`CREATE VIEW "alcs"."inbox_notice_of_intent_submission_view" AS SELECT "noi_sub"."uuid" AS "uuid", "noi_sub"."applicant" AS "applicant", "noi"."uuid" AS "notice_of_intent_uuid", "noi_sub"."file_number" AS "file_number", "noi_sub"."audit_created_at" AS "created_at", "noi_sub"."created_by_uuid" AS "created_by_uuid", "noi_sub"."local_government_uuid" AS "local_government_uuid", "user"."bceid_business_guid" AS "bceid_business_guid", "noi_sub"."type_code" AS "notice_of_intent_type_code", "noi"."date_submitted_to_alc" AS "date_submitted_to_alc", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_notice_of_intent_submission_by_uuid("noi_sub"."uuid") AS "status" FROM "alcs"."notice_of_intent_submission" "noi_sub" INNER JOIN "alcs"."notice_of_intent" "noi" ON "noi"."file_number" = "noi_sub"."file_number" AND "noi"."hide_from_portal" = false AND "noi"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."user" "user" ON "user"."uuid" = "noi_sub"."created_by_uuid" AND "user"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."notice_of_intent_submission_to_submission_status" "status_link" GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "noi_sub"."uuid" LEFT JOIN (SELECT MAX("date") AS "date", notice_of_intent_uuid AS "notice_of_intent_uuid" FROM "alcs"."notice_of_intent_decision" "decision_date" WHERE "decision_date"."audit_deleted_date_at" IS NULL GROUP BY notice_of_intent_uuid) "decision_date" ON decision_date."notice_of_intent_uuid" = "noi"."uuid" WHERE ( "noi_sub"."is_draft" = FALSE ) AND ( "noi_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","inbox_notice_of_intent_submission_view","SELECT \"noi_sub\".\"uuid\" AS \"uuid\", \"noi_sub\".\"applicant\" AS \"applicant\", \"noi\".\"uuid\" AS \"notice_of_intent_uuid\", \"noi_sub\".\"file_number\" AS \"file_number\", \"noi_sub\".\"audit_created_at\" AS \"created_at\", \"noi_sub\".\"created_by_uuid\" AS \"created_by_uuid\", \"noi_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"user\".\"bceid_business_guid\" AS \"bceid_business_guid\", \"noi_sub\".\"type_code\" AS \"notice_of_intent_type_code\", \"noi\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_notice_of_intent_submission_by_uuid(\"noi_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"notice_of_intent_submission\" \"noi_sub\" INNER JOIN \"alcs\".\"notice_of_intent\" \"noi\" ON \"noi\".\"file_number\" = \"noi_sub\".\"file_number\" AND \"noi\".\"hide_from_portal\" = false AND \"noi\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"user\" \"user\" ON \"user\".\"uuid\" = \"noi_sub\".\"created_by_uuid\" AND \"user\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"notice_of_intent_submission_to_submission_status\" \"status_link\" GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"noi_sub\".\"uuid\" LEFT JOIN (SELECT MAX(\"date\") AS \"date\", notice_of_intent_uuid AS \"notice_of_intent_uuid\" FROM \"alcs\".\"notice_of_intent_decision\" \"decision_date\" WHERE \"decision_date\".\"audit_deleted_date_at\" IS NULL GROUP BY notice_of_intent_uuid) \"decision_date\" ON decision_date.\"notice_of_intent_uuid\" = \"noi\".\"uuid\" WHERE ( \"noi_sub\".\"is_draft\" = FALSE ) AND ( \"noi_sub\".\"audit_deleted_date_at\" IS NULL )"]); + await queryRunner.query(`CREATE VIEW "alcs"."inbox_application_submission_view" AS SELECT "app_sub"."uuid" AS "uuid", "app_sub"."applicant" AS "applicant", "app"."uuid" AS "application_uuid", "app_sub"."file_number" AS "file_number", "app_sub"."created_by_uuid" AS "created_by_uuid", "app_sub"."local_government_uuid" AS "local_government_uuid", "app_sub"."audit_created_at" AS "created_at", "user"."bceid_business_guid" AS "bceid_business_guid", "app_sub"."type_code" AS "application_type_code", "app"."date_submitted_to_alc" AS "date_submitted_to_alc", GREATEST(status_link.effective_date, decision_date.date) AS "last_update", alcs.get_current_status_for_application_submission_by_uuid("app_sub"."uuid") AS "status" FROM "alcs"."application_submission" "app_sub" INNER JOIN "alcs"."application" "app" ON "app"."file_number" = "app_sub"."file_number" AND "app"."hide_from_portal" = FALSE AND "app"."audit_deleted_date_at" IS NULL LEFT JOIN "alcs"."user" "user" ON "user"."uuid" = "app_sub"."created_by_uuid" AND "user"."audit_deleted_date_at" IS NULL LEFT JOIN (SELECT MAX("effective_date") AS "effective_date", submission_uuid AS "submission_uuid" FROM "alcs"."application_submission_to_submission_status" "status_link" GROUP BY submission_uuid) "status_link" ON status_link."submission_uuid" = "app_sub"."uuid" LEFT JOIN (SELECT MAX("date") AS "date", application_uuid AS "application_uuid" FROM "alcs"."application_decision" "decision_date" WHERE "decision_date"."audit_deleted_date_at" IS NULL GROUP BY application_uuid) "decision_date" ON decision_date."application_uuid" = "app"."uuid" WHERE ( "app_sub"."is_draft" = FALSE ) AND ( "app_sub"."audit_deleted_date_at" IS NULL )`); + await queryRunner.query(`INSERT INTO "alcs"."typeorm_metadata"("database", "schema", "table", "type", "name", "value") VALUES (DEFAULT, $1, DEFAULT, $2, $3, $4)`, ["alcs","VIEW","inbox_application_submission_view","SELECT \"app_sub\".\"uuid\" AS \"uuid\", \"app_sub\".\"applicant\" AS \"applicant\", \"app\".\"uuid\" AS \"application_uuid\", \"app_sub\".\"file_number\" AS \"file_number\", \"app_sub\".\"created_by_uuid\" AS \"created_by_uuid\", \"app_sub\".\"local_government_uuid\" AS \"local_government_uuid\", \"app_sub\".\"audit_created_at\" AS \"created_at\", \"user\".\"bceid_business_guid\" AS \"bceid_business_guid\", \"app_sub\".\"type_code\" AS \"application_type_code\", \"app\".\"date_submitted_to_alc\" AS \"date_submitted_to_alc\", GREATEST(status_link.effective_date, decision_date.date) AS \"last_update\", alcs.get_current_status_for_application_submission_by_uuid(\"app_sub\".\"uuid\") AS \"status\" FROM \"alcs\".\"application_submission\" \"app_sub\" INNER JOIN \"alcs\".\"application\" \"app\" ON \"app\".\"file_number\" = \"app_sub\".\"file_number\" AND \"app\".\"hide_from_portal\" = FALSE AND \"app\".\"audit_deleted_date_at\" IS NULL LEFT JOIN \"alcs\".\"user\" \"user\" ON \"user\".\"uuid\" = \"app_sub\".\"created_by_uuid\" AND \"user\".\"audit_deleted_date_at\" IS NULL LEFT JOIN (SELECT MAX(\"effective_date\") AS \"effective_date\", submission_uuid AS \"submission_uuid\" FROM \"alcs\".\"application_submission_to_submission_status\" \"status_link\" GROUP BY submission_uuid) \"status_link\" ON status_link.\"submission_uuid\" = \"app_sub\".\"uuid\" LEFT JOIN (SELECT MAX(\"date\") AS \"date\", application_uuid AS \"application_uuid\" FROM \"alcs\".\"application_decision\" \"decision_date\" WHERE \"decision_date\".\"audit_deleted_date_at\" IS NULL GROUP BY application_uuid) \"decision_date\" ON decision_date.\"application_uuid\" = \"app\".\"uuid\" WHERE ( \"app_sub\".\"is_draft\" = FALSE ) AND ( \"app_sub\".\"audit_deleted_date_at\" IS NULL )"]); + } + +} diff --git a/services/package-lock.json b/services/package-lock.json index 8f741db526..50392ae85b 100644 --- a/services/package-lock.json +++ b/services/package-lock.json @@ -1990,11 +1990,11 @@ "dev": true }, "node_modules/@grpc/grpc-js": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.6.tgz", - "integrity": "sha512-xP58G7wDQ4TCmN/cMUHh00DS7SRDv/+lC+xFLrTkMIN8h55X5NhZMLYbvy7dSELP15qlI6hPhNCRWVMtZMwqLA==", + "version": "1.10.10", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.10.tgz", + "integrity": "sha512-HPa/K5NX6ahMoeBv15njAc/sfF4/jmiXLar9UlC2UfHFKZzsCVLc3wbe7+7qua7w9VPh2/L6EBxyAV7/E8Wftg==", "dependencies": { - "@grpc/proto-loader": "^0.7.10", + "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { @@ -2002,13 +2002,13 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.12", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.12.tgz", - "integrity": "sha512-DCVwMxqYzpUCiDMl7hQ384FqP4T3DbNpXU8pt681l3UWCip1WUiD5JrkImUwCB9a7f2cq4CUTmi5r/xIMRPY1Q==", + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.2.4", + "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { @@ -5617,11 +5617,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -7825,9 +7825,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -12660,9 +12660,9 @@ } }, "node_modules/s3-streamlogger": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/s3-streamlogger/-/s3-streamlogger-1.9.2.tgz", - "integrity": "sha512-E3JHxX2wFDiT+KSYSKMjpUBi4dITS1hjmXIw0+Dfv1mP17mFRdwMBGuEgIGy5qsoU9c+M5hvtnW2WhJHTSmbEw==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/s3-streamlogger/-/s3-streamlogger-1.9.4.tgz", + "integrity": "sha512-d8o1x/wP/jIUWgcLzblNhsJknAaX8lpqlFqSejaKDXC15ZBoN3NXIk9Sssea6Ne3gSnTUk7yHQaCDpgiAnealg==", "dependencies": { "@aws-sdk/client-s3": "^3.353.0", "git-branch": "^2.0.1", diff --git a/services/templates/emails/partials/header.template.ts b/services/templates/emails/partials/header.template.ts index e49082c8a3..21b652a49d 100644 --- a/services/templates/emails/partials/header.template.ts +++ b/services/templates/emails/partials/header.template.ts @@ -4,7 +4,7 @@ export const header = ` {{ parentTypeLabel }} ID #{{fileNumber}} - Owner Name: {{applicantName}} + Name: {{applicantName}} Status: {{status}} diff --git a/services/templates/pdf/noi-submissions/noi-pfrs-submission-template.docx b/services/templates/pdf/noi-submissions/noi-pfrs-submission-template.docx index 4b534b728e..e048ee766e 100644 Binary files a/services/templates/pdf/noi-submissions/noi-pfrs-submission-template.docx and b/services/templates/pdf/noi-submissions/noi-pfrs-submission-template.docx differ diff --git a/services/templates/pdf/noi-submissions/noi-pofo-submission-template.docx b/services/templates/pdf/noi-submissions/noi-pofo-submission-template.docx index 3c7a9f1ca3..9c80b8e1cc 100644 Binary files a/services/templates/pdf/noi-submissions/noi-pofo-submission-template.docx and b/services/templates/pdf/noi-submissions/noi-pofo-submission-template.docx differ diff --git a/services/templates/pdf/noi-submissions/noi-roso-submission-template.docx b/services/templates/pdf/noi-submissions/noi-roso-submission-template.docx index afe1c1ad9b..61ea4ab335 100644 Binary files a/services/templates/pdf/noi-submissions/noi-roso-submission-template.docx and b/services/templates/pdf/noi-submissions/noi-roso-submission-template.docx differ diff --git a/services/templates/pdf/submission-fng-review-template.docx b/services/templates/pdf/submission-fng-review-template.docx index d54cbbfdb0..e97beaf756 100644 Binary files a/services/templates/pdf/submission-fng-review-template.docx and b/services/templates/pdf/submission-fng-review-template.docx differ diff --git a/services/templates/pdf/submission-lg-review-template.docx b/services/templates/pdf/submission-lg-review-template.docx index 829ff35747..5d921e41f8 100644 Binary files a/services/templates/pdf/submission-lg-review-template.docx and b/services/templates/pdf/submission-lg-review-template.docx differ diff --git a/services/templates/pdf/submissions/cove-submission-template.docx b/services/templates/pdf/submissions/cove-submission-template.docx index 89c40a7f38..a7d93b4ffc 100644 Binary files a/services/templates/pdf/submissions/cove-submission-template.docx and b/services/templates/pdf/submissions/cove-submission-template.docx differ diff --git a/services/templates/pdf/submissions/excl-submission-template.docx b/services/templates/pdf/submissions/excl-submission-template.docx index 7d16a70dbe..4fa99a8eee 100644 Binary files a/services/templates/pdf/submissions/excl-submission-template.docx and b/services/templates/pdf/submissions/excl-submission-template.docx differ diff --git a/services/templates/pdf/submissions/incl-submission-template.docx b/services/templates/pdf/submissions/incl-submission-template.docx index 6e5a33fcc1..9da0426aeb 100644 Binary files a/services/templates/pdf/submissions/incl-submission-template.docx and b/services/templates/pdf/submissions/incl-submission-template.docx differ diff --git a/services/templates/pdf/submissions/naru-submission-template.docx b/services/templates/pdf/submissions/naru-submission-template.docx index 82bd806c40..9c2e0866a6 100644 Binary files a/services/templates/pdf/submissions/naru-submission-template.docx and b/services/templates/pdf/submissions/naru-submission-template.docx differ diff --git a/services/templates/pdf/submissions/nfu-submission-template.docx b/services/templates/pdf/submissions/nfu-submission-template.docx index 1d1f335d51..429af6871b 100644 Binary files a/services/templates/pdf/submissions/nfu-submission-template.docx and b/services/templates/pdf/submissions/nfu-submission-template.docx differ diff --git a/services/templates/pdf/submissions/pfrs-submission-template.docx b/services/templates/pdf/submissions/pfrs-submission-template.docx index a51d5a9c01..004616c04c 100644 Binary files a/services/templates/pdf/submissions/pfrs-submission-template.docx and b/services/templates/pdf/submissions/pfrs-submission-template.docx differ diff --git a/services/templates/pdf/submissions/pofo-submission-template.docx b/services/templates/pdf/submissions/pofo-submission-template.docx index 29a6d35b5d..4ee51557db 100644 Binary files a/services/templates/pdf/submissions/pofo-submission-template.docx and b/services/templates/pdf/submissions/pofo-submission-template.docx differ diff --git a/services/templates/pdf/submissions/roso-submission-template.docx b/services/templates/pdf/submissions/roso-submission-template.docx index 1deb31525d..7bcb7fc66b 100644 Binary files a/services/templates/pdf/submissions/roso-submission-template.docx and b/services/templates/pdf/submissions/roso-submission-template.docx differ diff --git a/services/templates/pdf/submissions/subd-submission-template.docx b/services/templates/pdf/submissions/subd-submission-template.docx index b41d81db03..97007fdb69 100644 Binary files a/services/templates/pdf/submissions/subd-submission-template.docx and b/services/templates/pdf/submissions/subd-submission-template.docx differ diff --git a/services/templates/pdf/submissions/tur-submission-template.docx b/services/templates/pdf/submissions/tur-submission-template.docx index 17712ec7c6..7828408701 100644 Binary files a/services/templates/pdf/submissions/tur-submission-template.docx and b/services/templates/pdf/submissions/tur-submission-template.docx differ