From 012fd2cfeba6f3ecce8097b7db9c2e77d1db43f5 Mon Sep 17 00:00:00 2001
From: Son
Date: Thu, 16 Nov 2023 05:22:38 -0800
Subject: [PATCH 1/3] Added Migration and Replaced text editor in frontend
---
.../1700109002096-RichTextStoringPI.ts | 277 +++++++++++++++
.../section-contract.ts | 7 +-
.../section-controls.ts | 7 +-
.../section-storage.ts | 10 +-
.../section-track-access.ts | 7 +-
.../personal-information.ts | 7 +-
.../mocks/create-pia-intake.mock.ts | 14 +-
.../test/util/mocks/data/pia-intake.mock.ts | 14 +-
.../storingPersonalInformation/index.tsx | 325 ++++++++----------
.../storingPersonalInformation/interfaces.ts | 13 +-
10 files changed, 469 insertions(+), 212 deletions(-)
create mode 100644 src/backend/src/migrations/1700109002096-RichTextStoringPI.ts
diff --git a/src/backend/src/migrations/1700109002096-RichTextStoringPI.ts b/src/backend/src/migrations/1700109002096-RichTextStoringPI.ts
new file mode 100644
index 000000000..03338924a
--- /dev/null
+++ b/src/backend/src/migrations/1700109002096-RichTextStoringPI.ts
@@ -0,0 +1,277 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class RichTextStoringPI1700109002096 implements MigrationInterface {
+ public async up(queryRunner: QueryRunner): Promise {
+ // Add temporary columns to store the existing text
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_whereDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_disclosureDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_contractualTerms" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_enterpriseServiceAccessDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_unauthorizedAccessMeasures" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_trackAccessDetails" text`,
+ );
+
+ // Copy the data from the old columns to the temporary columns
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_whereDetails" = "storing_personal_information"->'personalInformation'->>'whereDetails'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_disclosureDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'storage'->>'disclosureDetails'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_contractualTerms" = "storing_personal_information"->'disclosuresOutsideCanada'->'storage'->>'contractualTerms'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_enterpriseServiceAccessDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'contract'->>'enterpriseServiceAccessDetails'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_unauthorizedAccessMeasures" = "storing_personal_information"->'disclosuresOutsideCanada'->'controls'->>'unauthorizedAccessMeasures'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_trackAccessDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'trackAccess'->>'trackAccessDetails'`,
+ );
+
+ // Change jsonb properties from type string to object
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{personalInformation, whereDetails}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, disclosureDetails}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, contractualTerms}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, contract, enterpriseServiceAccessDetails}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, controls, unauthorizedAccessMeasures}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, trackAccess, trackAccessDetails}',
+ '{"content": ""}'::jsonb
+ )`,
+ );
+
+ // Populate the jsonb with the data from the temporary columns
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{personalInformation, whereDetails, content}',
+ to_jsonb("temp_storingPI_whereDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, disclosureDetails, content}',
+ to_jsonb("temp_storingPI_disclosureDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, contractualTerms, content}',
+ to_jsonb("temp_storingPI_contractualTerms")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, contract, enterpriseServiceAccessDetails, content}',
+ to_jsonb("temp_storingPI_enterpriseServiceAccessDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, controls, unauthorizedAccessMeasures, content}',
+ to_jsonb("temp_storingPI_unauthorizedAccessMeasures")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, trackAccess, trackAccessDetails, content}',
+ to_jsonb("temp_storingPI_trackAccessDetails")
+ )`,
+ );
+
+ // Drop the temporary columns
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_whereDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_disclosureDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_contractualTerms"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_enterpriseServiceAccessDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_unauthorizedAccessMeasures"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_trackAccessDetails"`,
+ );
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ // Re-add temporary columns
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_whereDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_disclosureDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_contractualTerms" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_enterpriseServiceAccessDetails" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_unauthorizedAccessMeasures" text`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" ADD "temp_storingPI_trackAccessDetails" text`,
+ );
+
+ // Extract the content from JSONB and store in temporary columns
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_whereDetails" = "storing_personal_information"->'personalInformation'->'whereDetails'->>'content'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_disclosureDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'storage'->'disclosureDetails'->>'content'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_contractualTerms" = "storing_personal_information"->'disclosuresOutsideCanada'->'storage'->'contractualTerms'->>'content'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_enterpriseServiceAccessDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'contract'->'enterpriseServiceAccessDetails'->>'content'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_unauthorizedAccessMeasures" = "storing_personal_information"->'disclosuresOutsideCanada'->'controls'->'unauthorizedAccessMeasures'->>'content'`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake" SET "temp_storingPI_trackAccessDetails" = "storing_personal_information"->'disclosuresOutsideCanada'->'trackAccess'->'trackAccessDetails'->>'content'`,
+ );
+
+ // Revert the JSONB properties to type string using the temporary column values
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{personalInformation, whereDetails}',
+ to_jsonb("temp_storingPI_whereDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, disclosureDetails}',
+ to_jsonb("temp_storingPI_disclosureDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, storage, contractualTerms}',
+ to_jsonb("temp_storingPI_contractualTerms")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, contract, enterpriseServiceAccessDetails}',
+ to_jsonb("temp_storingPI_enterpriseServiceAccessDetails")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, controls, unauthorizedAccessMeasures}',
+ to_jsonb("temp_storingPI_unauthorizedAccessMeasures")
+ )`,
+ );
+ await queryRunner.query(
+ `UPDATE "pia-intake"
+ SET "storing_personal_information" = jsonb_set(
+ "storing_personal_information",
+ '{disclosuresOutsideCanada, trackAccess, trackAccessDetails}',
+ to_jsonb("temp_storingPI_trackAccessDetails")
+ )`,
+ );
+
+ // Drop the temporary columns
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_whereDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_disclosureDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_contractualTerms"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_enterpriseServiceAccessDetails"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_unauthorizedAccessMeasures"`,
+ );
+ await queryRunner.query(
+ `ALTER TABLE "pia-intake" DROP COLUMN "temp_storingPI_trackAccessDetails"`,
+ );
+ }
+}
diff --git a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-contract.ts b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-contract.ts
index 5273966c0..0c94193cf 100644
--- a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-contract.ts
+++ b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-contract.ts
@@ -1,12 +1,13 @@
-import { IsEnum, IsOptional, IsString } from '@nestjs/class-validator';
+import { IsEnum, IsObject, IsOptional } from '@nestjs/class-validator';
import { YesNoInput } from 'src/common/enums/yes-no-input.enum';
+import { RichTextContent } from '../../rich-text-content';
export class DisclosureContract {
@IsEnum(YesNoInput)
@IsOptional()
relyOnExistingContract?: YesNoInput;
- @IsString()
+ @IsObject()
@IsOptional()
- enterpriseServiceAccessDetails?: string;
+ enterpriseServiceAccessDetails?: RichTextContent;
}
diff --git a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-controls.ts b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-controls.ts
index 95a9a49f8..ecfab0c8b 100644
--- a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-controls.ts
+++ b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-controls.ts
@@ -1,7 +1,8 @@
-import { IsOptional, IsString } from '@nestjs/class-validator';
+import { IsObject, IsOptional } from '@nestjs/class-validator';
+import { RichTextContent } from '../../rich-text-content';
export class DisclosureControls {
- @IsString()
+ @IsObject()
@IsOptional()
- unauthorizedAccessMeasures?: string;
+ unauthorizedAccessMeasures?: RichTextContent;
}
diff --git a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-storage.ts b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-storage.ts
index 356a93d0a..e3937920e 100644
--- a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-storage.ts
+++ b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-storage.ts
@@ -1,12 +1,14 @@
import {
IsArray,
IsEnum,
+ IsObject,
IsOptional,
IsString,
ValidateNested,
} from '@nestjs/class-validator';
import { Type } from 'class-transformer';
import { YesNoInput } from 'src/common/enums/yes-no-input.enum';
+import { RichTextContent } from '../../rich-text-content';
class ServiceProviderDetails {
@IsString()
@@ -31,11 +33,11 @@ export class DisclosureStorage {
@Type(() => ServiceProviderDetails)
serviceProviderList: Array;
- @IsString()
+ @IsObject()
@IsOptional()
- disclosureDetails?: string;
+ disclosureDetails?: RichTextContent;
- @IsString()
+ @IsObject()
@IsOptional()
- contractualTerms?: string;
+ contractualTerms?: RichTextContent;
}
diff --git a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-track-access.ts b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-track-access.ts
index 362c3ad28..abffd8329 100644
--- a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-track-access.ts
+++ b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/disclosures-outside-canda/section-track-access.ts
@@ -1,7 +1,8 @@
-import { IsOptional, IsString } from '@nestjs/class-validator';
+import { IsObject, IsOptional } from '@nestjs/class-validator';
+import { RichTextContent } from '../../rich-text-content';
export class DisclosureTrackAccess {
- @IsString()
+ @IsObject()
@IsOptional()
- trackAccessDetails?: string;
+ trackAccessDetails?: RichTextContent;
}
diff --git a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/personal-information.ts b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/personal-information.ts
index ebd79ed0f..c6ceeb791 100644
--- a/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/personal-information.ts
+++ b/src/backend/src/modules/pia-intake/jsonb-classes/storing-personal-information/personal-information.ts
@@ -1,12 +1,13 @@
-import { IsEnum, IsOptional, IsString } from '@nestjs/class-validator';
+import { IsEnum, IsObject, IsOptional } from '@nestjs/class-validator';
import { YesNoInput } from 'src/common/enums/yes-no-input.enum';
+import { RichTextContent } from '../rich-text-content';
export class PersonalInformation {
@IsEnum(YesNoInput)
@IsOptional()
storedOutsideCanada?: YesNoInput;
- @IsString()
+ @IsObject()
@IsOptional()
- whereDetails?: string;
+ whereDetails?: RichTextContent;
}
diff --git a/src/backend/src/modules/pia-intake/mocks/create-pia-intake.mock.ts b/src/backend/src/modules/pia-intake/mocks/create-pia-intake.mock.ts
index 13ac0e627..d906dd06d 100644
--- a/src/backend/src/modules/pia-intake/mocks/create-pia-intake.mock.ts
+++ b/src/backend/src/modules/pia-intake/mocks/create-pia-intake.mock.ts
@@ -57,7 +57,7 @@ export const piaIntakeEntityMock: CreatePiaIntakeDto = {
storingPersonalInformation: {
personalInformation: {
storedOutsideCanada: YesNoInput.YES,
- whereDetails: 'USA',
+ whereDetails: { content: 'USA' },
},
sensitivePersonalInformation: {
doesInvolve: YesNoInput.YES,
@@ -73,18 +73,20 @@ export const piaIntakeEntityMock: CreatePiaIntakeDto = {
details: 'Stored in cloud',
},
],
- disclosureDetails: 'S3 storage in us-east-1: US East (N. Virginia)',
- contractualTerms: 'None',
+ disclosureDetails: {
+ content: 'S3 storage in us-east-1: US East (N. Virginia)',
+ },
+ contractualTerms: { content: 'None' },
},
contract: {
relyOnExistingContract: YesNoInput.YES,
- enterpriseServiceAccessDetails: 'S3',
+ enterpriseServiceAccessDetails: { content: 'S3' },
},
controls: {
- unauthorizedAccessMeasures: 'IAM rules are in effect',
+ unauthorizedAccessMeasures: { content: 'IAM rules are in effect' },
},
trackAccess: {
- trackAccessDetails: 'IAM',
+ trackAccessDetails: { content: 'IAM' },
},
risks: {
privacyRisks: [
diff --git a/src/backend/test/util/mocks/data/pia-intake.mock.ts b/src/backend/test/util/mocks/data/pia-intake.mock.ts
index 4573522c6..671d73657 100644
--- a/src/backend/test/util/mocks/data/pia-intake.mock.ts
+++ b/src/backend/test/util/mocks/data/pia-intake.mock.ts
@@ -64,7 +64,7 @@ const piaIntakeDataMock = {
storingPersonalInformation: {
personalInformation: {
storedOutsideCanada: YesNoInput.YES,
- whereDetails: 'USA',
+ whereDetails: { content: 'USA' },
},
sensitivePersonalInformation: {
doesInvolve: YesNoInput.YES,
@@ -80,18 +80,20 @@ const piaIntakeDataMock = {
details: 'Stored in cloud',
},
],
- disclosureDetails: 'S3 storage in us-east-1: US East (N. Virginia)',
- contractualTerms: 'None',
+ disclosureDetails: {
+ content: 'S3 storage in us-east-1: US East (N. Virginia)',
+ },
+ contractualTerms: { content: 'None' },
},
contract: {
relyOnExistingContract: YesNoInput.YES,
- enterpriseServiceAccessDetails: 'S3',
+ enterpriseServiceAccessDetails: { content: 'S3' },
},
controls: {
- unauthorizedAccessMeasures: 'IAM rules are in effect',
+ unauthorizedAccessMeasures: { content: 'IAM rules are in effect' },
},
trackAccess: {
- trackAccessDetails: 'IAM',
+ trackAccessDetails: { content: 'IAM' },
},
risks: {
privacyRisks: [
diff --git a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
index b616894d9..f2eac388f 100644
--- a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
+++ b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
@@ -1,4 +1,3 @@
-import MDEditor from '@uiw/react-md-editor';
import { useContext, useEffect, useMemo, useState } from 'react';
import { YesNoInput } from '../../../../types/enums/yes-no.enum';
import { isMPORole } from '../../../../utils/user';
@@ -21,6 +20,7 @@ import {
import ViewComments from '../../../common/ViewComment';
import { PiaSections } from '../../../../types/enums/pia-sections.enum';
import Callout from '../../../common/Callout';
+import { RichTextEditor } from '@bcgov/citz-imb-richtexteditor';
const StoringPersonalInformation = ({
showComments = true,
@@ -39,7 +39,7 @@ const StoringPersonalInformation = ({
const personalInformation = useMemo(
() => ({
storedOutsideCanada: YesNoInput.YES,
- whereDetails: '',
+ whereDetails: { content: '' },
}),
[],
);
@@ -57,18 +57,18 @@ const StoringPersonalInformation = ({
storage: {
sensitiveInfoStoredByServiceProvider: YesNoInput.YES,
serviceProviderList: [{ name: '', cloudInfraName: '', details: '' }],
- disclosureDetails: '',
- contractualTerms: '',
+ disclosureDetails: { content: '' },
+ contractualTerms: { content: '' },
},
contract: {
relyOnExistingContract: YesNoInput.YES,
- enterpriseServiceAccessDetails: '',
+ enterpriseServiceAccessDetails: { content: '' },
},
controls: {
- unauthorizedAccessMeasures: '',
+ unauthorizedAccessMeasures: { content: '' },
},
trackAccess: {
- trackAccessDetails: '',
+ trackAccessDetails: { content: '' },
},
risks: {
privacyRisks: [
@@ -111,15 +111,95 @@ const StoringPersonalInformation = ({
setNestedReactState(setStoringPersonalInformationForm, path, value);
};
- // passing updated data to parent for auto-save to work efficiently only if there are changes
+ // State for rich text editors.
+ const [whereDetails, setWhereDetails] = useState(
+ storingPersonalInformationForm?.personalInformation.whereDetails?.content ??
+ '',
+ );
+ const [disclosureDetails, setDisclosureDetails] = useState(
+ storingPersonalInformationForm?.disclosuresOutsideCanada?.storage
+ .disclosureDetails?.content ?? '',
+ );
+ const [contractualTerms, setContractualTerms] = useState(
+ storingPersonalInformationForm?.disclosuresOutsideCanada?.storage
+ .contractualTerms?.content ?? '',
+ );
+ const [enterpriseServiceAccessDetails, setEnterpriseServiceAccessDetails] =
+ useState(
+ storingPersonalInformationForm?.disclosuresOutsideCanada?.contract
+ .enterpriseServiceAccessDetails?.content ?? '',
+ );
+ const [unauthorizedAccessMeasures, setUnauthorizedAccessMeasures] = useState(
+ storingPersonalInformationForm?.disclosuresOutsideCanada?.controls
+ .unauthorizedAccessMeasures?.content ?? '',
+ );
+ const [trackAccessDetails, setTrackAccessDetails] = useState(
+ storingPersonalInformationForm?.disclosuresOutsideCanada?.trackAccess
+ .trackAccessDetails.content ?? '',
+ );
+
+ // Update form state on rich text editor changes.
useEffect(() => {
- if (!deepEqual(initialFormState, storingPersonalInformationForm)) {
- piaStateChangeHandler(
- storingPersonalInformationForm,
- 'storingPersonalInformation',
- );
- }
- }, [piaStateChangeHandler, storingPersonalInformationForm, initialFormState]);
+ stateChangeHandler(
+ whereDetails,
+ 'personalInformation.whereDetails.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [whereDetails]);
+ useEffect(() => {
+ stateChangeHandler(
+ disclosureDetails,
+ 'disclosuresOutsideCanada.storage.disclosureDetails.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [disclosureDetails]);
+ useEffect(() => {
+ stateChangeHandler(
+ contractualTerms,
+ 'disclosuresOutsideCanada.storage.contractualTerms.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [contractualTerms]);
+ useEffect(() => {
+ stateChangeHandler(
+ enterpriseServiceAccessDetails,
+ 'disclosuresOutsideCanada.contract.enterpriseServiceAccessDetails.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [enterpriseServiceAccessDetails]);
+ useEffect(() => {
+ stateChangeHandler(
+ unauthorizedAccessMeasures,
+ 'disclosuresOutsideCanada.controls.unauthorizedAccessMeasures.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [unauthorizedAccessMeasures]);
+ useEffect(() => {
+ stateChangeHandler(
+ trackAccessDetails,
+ 'disclosuresOutsideCanada.trackAccess.trackAccessDetails.content',
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [trackAccessDetails]);
+
+ // Show the editor unless isReadOnly and whereDetails is empty.
+ const showEditorWhereDetails = !(isReadOnly && whereDetails === '');
+ //Show the editor unless isReadOnly and disclosureDetails is empty.
+ const showEditorDisclosureDetails = !(isReadOnly && disclosureDetails === '');
+ // Show the editor unless isReadOnly and contractualTerm is empty.
+ const showEditorContractualTerms = !(isReadOnly && contractualTerms === '');
+ // Show the editor unless isReadOnly and EnterpriseServiceAccessDetail is empty.
+ const showEditorEnterpriseServiceAccessDetails = !(
+ isReadOnly && enterpriseServiceAccessDetails === ''
+ );
+ // Show the editor unless isReadOnly and disclosureDetails is empty.
+ const showEditorUnauthorizedAccessMeasures = !(
+ isReadOnly && unauthorizedAccessMeasures === ''
+ );
+ // Show the editor unless isReadOnly and disclosureDetails is empty.
+ const showEditorTrackAccessDetails = !(
+ isReadOnly && trackAccessDetails === ''
+ );
const disclosuresOutsideCanadaStorageServiceProviderListColumns: Array =
[
@@ -335,8 +415,18 @@ const StoringPersonalInformation = ({
},
];
+ // passing updated data to parent for auto-save to work efficiently only if there are changes
+ useEffect(() => {
+ if (!deepEqual(initialFormState, storingPersonalInformationForm)) {
+ piaStateChangeHandler(
+ storingPersonalInformationForm,
+ 'storingPersonalInformation',
+ );
+ }
+ }, [piaStateChangeHandler, storingPersonalInformationForm, initialFormState]);
+
return (
-
-
source={Messages.Risks.DescribePrivacyRisks.HelperText.en}
- />
+
>
) : (
{Messages.Risks.DescribePrivacyRisks.en}
@@ -1081,7 +1050,7 @@ const StoringPersonalInformation = ({
>
)}
-
+ >
);
};
diff --git a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/interfaces.ts b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/interfaces.ts
index a5ac66295..a42d421bb 100644
--- a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/interfaces.ts
+++ b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/interfaces.ts
@@ -1,4 +1,5 @@
import { YesNoInput } from '../../../../types/enums/yes-no.enum';
+import { RichTextContent } from '../types';
export type PrivacyRisk = {
risk: string;
@@ -18,7 +19,7 @@ export type ServiceProviderDetails = {
export interface IStoringPersonalInformation {
personalInformation: {
storedOutsideCanada: YesNoInput;
- whereDetails: string;
+ whereDetails: RichTextContent;
};
sensitivePersonalInformation: {
doesInvolve: YesNoInput;
@@ -28,18 +29,18 @@ export interface IStoringPersonalInformation {
storage: {
sensitiveInfoStoredByServiceProvider: YesNoInput;
serviceProviderList: Array;
- disclosureDetails: string;
- contractualTerms: string;
+ disclosureDetails: RichTextContent;
+ contractualTerms: RichTextContent;
};
contract: {
relyOnExistingContract: YesNoInput;
- enterpriseServiceAccessDetails: string;
+ enterpriseServiceAccessDetails: RichTextContent;
};
controls: {
- unauthorizedAccessMeasures: string;
+ unauthorizedAccessMeasures: RichTextContent;
};
trackAccess: {
- trackAccessDetails: string;
+ trackAccessDetails: RichTextContent;
};
risks: {
privacyRisks: Array;
From 83fd392a80b011f037d726a45d5d87abd24c6eb0 Mon Sep 17 00:00:00 2001
From: Son
Date: Thu, 16 Nov 2023 05:30:00 -0800
Subject: [PATCH 2/3] removed code related md-editor
---
.../_collectionUseAndDisclosure.scss | 3 ---
.../PIAFormTabs/collectionUseAndDisclosure/index.tsx | 11 -----------
src/frontend/src/sass/common.scss | 1 -
3 files changed, 15 deletions(-)
delete mode 100644 src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/_collectionUseAndDisclosure.scss
diff --git a/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/_collectionUseAndDisclosure.scss b/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/_collectionUseAndDisclosure.scss
deleted file mode 100644
index 38b7cccaf..000000000
--- a/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/_collectionUseAndDisclosure.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.w-md-editor-show-preview .w-md-editor-preview {
- background-color: #e9ecef !important;
-}
diff --git a/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/index.tsx b/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/index.tsx
index f73eb3e6a..95a81752e 100644
--- a/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/index.tsx
+++ b/src/frontend/src/components/public/PIAFormTabs/collectionUseAndDisclosure/index.tsx
@@ -125,17 +125,6 @@ const PIACollectionUseAndDisclosure = ({
'collectionUseAndDisclosure',
);
}
-
- // Disabled editor buttons if the user does not have the MPORole.
- // Select button elements inside #collectionNoticeMPO .w-md-editor-toolbar li.
- const buttons = document.querySelectorAll(
- '#collectionNoticeMPO .w-md-editor-toolbar li > button',
- );
-
- // Iterate over all button elements and set the 'disabled' attribute based on the user's role.
- buttons.forEach((button) => {
- button.disabled = !isMPORole() ? true : false;
- });
}, [piaStateChangeHandler, collectionUseAndDisclosureForm, initialFormState]);
return (
diff --git a/src/frontend/src/sass/common.scss b/src/frontend/src/sass/common.scss
index 7dee55ea8..93874ffe3 100644
--- a/src/frontend/src/sass/common.scss
+++ b/src/frontend/src/sass/common.scss
@@ -39,4 +39,3 @@
@import './collapsible';
@import './printPreview';
@import './comment_sidebar';
-@import '../components/public/PIAFormTabs/collectionUseAndDisclosure/collectionUseAndDisclosure';
From 866af2b5aa7bee844370d3452462dce6dd92658f Mon Sep 17 00:00:00 2001
From: Son
Date: Thu, 16 Nov 2023 09:20:47 -0800
Subject: [PATCH 3/3] added condition for mpo role
---
.../public/PIAFormTabs/storingPersonalInformation/index.tsx | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
index f2eac388f..eb7f9e018 100644
--- a/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
+++ b/src/frontend/src/components/public/PIAFormTabs/storingPersonalInformation/index.tsx
@@ -717,12 +717,11 @@ const StoringPersonalInformation = ({
{Messages.AssessmentOfDisclosures.DisclosureDetails.en}
)}
- {/* TODO: Implement logic to enable writing in the RichTextEditor only when the user has the MPO role. */}
- {showEditorDisclosureDetails && isMPORole() ? (
+ {showEditorDisclosureDetails ? (
) : (