From 958d1a93ac80e5e32274582e83c183830b131852 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 16 May 2024 21:08:01 -0400 Subject: [PATCH 01/40] UI changes for the Data deletion --- app/_locales/en/messages.json | 22 +++ .../ClearMetaMetricsData.tsx | 134 ++++++++++++++++++ .../app/clear-metametrics-data/index.ts | 1 + ui/ducks/app/app.ts | 24 ++++ .../security-tab/security-tab.component.js | 75 +++++++++- .../security-tab/security-tab.container.js | 18 ++- ui/selectors/selectors.js | 20 +++ ui/store/actionConstants.ts | 4 + 8 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx create mode 100644 ui/components/app/clear-metametrics-data/index.ts diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 1ddcd1c05a6b..7494fa24ba93 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1569,6 +1569,12 @@ "deleteContact": { "message": "Delete contact" }, + "deleteMetaMetricsDataModalDesc": { + "message": "We are about to remove all your MetaMetrics data. Are you sure?" + }, + "deleteMetaMetricsDataModalTitle": { + "message": "Delete MetaMetrics data?" + }, "deleteNetworkIntro": { "message": "If you delete this network, you will need to add it again to view your assets in this network" }, @@ -6687,5 +6693,21 @@ }, "zeroGasPriceOnSpeedUpError": { "message": "Zero gas price on speed up" + }, + "deleteMetaMetricsData": { + "message": "Delete MetaMetrics data" + }, + "deleteMetaMetricsDataDescription": { + "message": "This will delete historical MetaMetrics data associated with your wallet. $1 Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 60 days. View the $2", + "description": "$1 will have the text with bold font (deleteMetaMetricsDataDescriptionBold) regarding metametrics and $2 will have text saying Consensys Privacy Policy " + }, + "deleteMetaMetricsDataDescriptionBold": { + "message": "MetaMetrics data is anonymized usage and diagnostic data." + }, + "consensysPrivacyPolicy": { + "message": "Consensys Privacy Policy" + }, + "deleteMetaMetricsDataRequestedDescription": { + "message": "You initiated this action on $1. This process can take up to 60 days. View the $2" } } diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx new file mode 100644 index 000000000000..6ac36e647e72 --- /dev/null +++ b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx @@ -0,0 +1,134 @@ +import React, { useContext } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { hideDeleteMetaMetricsDataModal } from '../../../ducks/app/app'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { + Box, + Button, + ButtonSize, + ButtonVariant, + Modal, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Text, +} from '../../component-library'; +import { + AlignItems, + BlockSize, + Display, + FlexDirection, + JustifyContent, + TextVariant, +} from '../../../helpers/constants/design-system'; +import { createMetaMetricsDataDeletionTask } from '../../../store/actions'; +import { + DataDeletionResponse, + responseStatus, +} from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; +import { + getMetaMetricsDataDeletionDate, + getMetaMetricsDataDeletionId, + getParticipateInMetaMetrics, +} from '../../../selectors'; +import { MetaMetricsContext } from '../../../contexts/metametrics'; +import { + MetaMetricsEventCategory, + MetaMetricsEventName, +} from '../../../../shared/constants/metametrics'; + +export default function ClearMetaMetricsData() { + const t = useI18nContext(); + const dispatch = useDispatch(); + const trackEvent = useContext(MetaMetricsContext); + + const participateInMetaMetrics = useSelector(getParticipateInMetaMetrics); + const id = useSelector(getMetaMetricsDataDeletionId); + const date = useSelector(getMetaMetricsDataDeletionDate); + + function closeModal() { + dispatch(hideDeleteMetaMetricsDataModal()); + } + + async function deleteMetaMetricsData() { + try { + const deleteResponse: DataDeletionResponse = (await dispatch( + createMetaMetricsDataDeletionTask(), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + )) as any; + + if (responseStatus.ok === deleteResponse?.status) { + console.log(`${deleteResponse}---${id}----${date}`); + if (participateInMetaMetrics) { + trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.MetricsDataDeletionRequest, + }); + } + } + } catch (error: unknown) { + // ignore + } finally { + dispatch(hideDeleteMetaMetricsDataModal()); + } + } + + return ( + + + + + + + {t('deleteMetaMetricsDataModalTitle')} + + + + + + {t('deleteMetaMetricsDataModalDesc')} + + + + + + + + + + + ); +} diff --git a/ui/components/app/clear-metametrics-data/index.ts b/ui/components/app/clear-metametrics-data/index.ts new file mode 100644 index 000000000000..1f7146583f5b --- /dev/null +++ b/ui/components/app/clear-metametrics-data/index.ts @@ -0,0 +1 @@ +export { default } from './ClearMetaMetricsData'; diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index 182ba426a3d7..99599b339868 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -100,6 +100,7 @@ type AppState = { customTokenAmount: string; txId: string | null; accountDetailsAddress: string; + showDeleteMetaMetricsDataModal: boolean; snapsInstallPrivacyWarningShown: boolean; isAddingNewNetwork: boolean; isMultiRpcOnboarding: boolean; @@ -185,6 +186,7 @@ const initialState: AppState = { scrollToBottom: true, txId: null, accountDetailsAddress: '', + showDeleteMetaMetricsDataModal: false, snapsInstallPrivacyWarningShown: false, isAddingNewNetwork: false, isMultiRpcOnboarding: false, @@ -608,6 +610,16 @@ export default function reduceApp( isAddingNewNetwork: Boolean(action.payload?.isAddingNewNetwork), isMultiRpcOnboarding: Boolean(action.payload?.isMultiRpcOnboarding), }; + case actionConstants.DELETE_METAMETRICS_DATA_MODAL_OPEN: + return { + ...appState, + showDeleteMetaMetricsDataModal: true, + }; + case actionConstants.DELETE_METAMETRICS_DATA_MODAL_CLOSE: + return { + ...appState, + showDeleteMetaMetricsDataModal: false, + }; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) case actionConstants.SHOW_KEYRING_SNAP_REMOVAL_RESULT: return { @@ -717,3 +729,15 @@ export function getLedgerWebHidConnectedStatus( export function getLedgerTransportStatus(state: AppSliceState): string | null { return state.appState.ledgerTransportStatus; } + +export function openDeleteMetaMetricsDataModal(): Action { + return { + type: actionConstants.DELETE_METAMETRICS_DATA_MODAL_OPEN, + }; +} + +export function hideDeleteMetaMetricsDataModal(): Action { + return { + type: actionConstants.DELETE_METAMETRICS_DATA_MODAL_CLOSE, + }; +} diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index f6da9fe2367f..b6c1f27a6cfa 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -32,6 +32,7 @@ import { IconName, Box, Text, + ButtonPrimary, } from '../../../components/component-library'; import TextField from '../../../components/ui/text-field'; import ToggleButton from '../../../components/ui/toggle-button'; @@ -54,6 +55,11 @@ import { import IncomingTransactionToggle from '../../../components/app/incoming-trasaction-toggle/incoming-transaction-toggle'; import ProfileSyncToggle from './profile-sync-toggle'; import MetametricsToggle from './metametrics-toggle'; +import ClearMetametricsData from '../../../components/app/clear-metametrics-data'; +import { + DeleteRegulationStatus, +} from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; +import { checkDataDeletionTaskStatus } from '../../../store/actions'; export default class SecurityTab extends PureComponent { static contextTypes = { @@ -101,6 +107,10 @@ export default class SecurityTab extends PureComponent { securityAlertsEnabled: PropTypes.bool, useExternalServices: PropTypes.bool, toggleExternalServices: PropTypes.func.isRequired, + showDeleteMetaMetricsDataModal: PropTypes.bool.isRequired, + setDeleteMetaMetricsDataModalOpen: PropTypes.func.isRequired, + metaMetricsDataDeletionStatus: PropTypes.string, + metaMetricsDataDeletionDate: PropTypes.string, setSecurityAlertsEnabled: PropTypes.func, }; @@ -138,9 +148,10 @@ export default class SecurityTab extends PureComponent { } } - componentDidMount() { + async componentDidMount() { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); + await checkDataDeletionTaskStatus(); } toggleSetting(value, eventName, eventAction, toggleMethod) { @@ -399,6 +410,67 @@ export default class SecurityTab extends PureComponent { ); } + renderDeleteMetaMetricsData() { + const { t } = this.context; + const { + metaMetricsDataDeletionStatus, + metaMetricsDataDeletionDate, + participateInMetaMetrics, + } = this.props; + let dataDeletionButtonDisabled = false; + if (metaMetricsDataDeletionStatus) { + dataDeletionButtonDisabled = + [ + DeleteRegulationStatus.INITIALIZED, + DeleteRegulationStatus.RUNNING, + DeleteRegulationStatus.FINISHED, + ].includes(metaMetricsDataDeletionStatus) && !participateInMetaMetrics; + } + return ( + <> + +
+ {t('deleteMetaMetricsData')} +
+ {t('deleteMetaMetricsDataDescription', [ + + {t('deleteMetaMetricsDataDescriptionBold')} + , + + {t('consensysPrivacyPolicy')} + , + ])} +
+
+
+ { + event.preventDefault(); + this.props.setDeleteMetaMetricsDataModalOpen(); + }} + disabled={dataDeletionButtonDisabled} + > + {t('deleteMetaMetricsData')} + +
+
+ {this.props.showDeleteMetaMetricsDataModal && } + + ); + } + renderChooseYourNetworkButton() { const { t } = this.context; @@ -1222,6 +1294,7 @@ export default class SecurityTab extends PureComponent { setDataCollectionForMarketing={setDataCollectionForMarketing} /> {this.renderDataCollectionForMarketing()} + {this.renderDeleteMetaMetricsData()} ); diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 747e3738fe3f..0d5d287c9ba7 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -20,13 +20,20 @@ import { setUseExternalNameSources, setUseTransactionSimulations, setSecurityAlertsEnabled, + checkDataDeletionTaskStatus, } from '../../../store/actions'; import { getIsSecurityAlertsEnabled, getNetworkConfigurationsByChainId, + getMetaMetricsDataDeletionDate, + getMetaMetricsDataDeletionStatus, getPetnamesEnabled, + getShowDeleteMetaMetricsDataModal, } from '../../../selectors'; -import { openBasicFunctionalityModal } from '../../../ducks/app/app'; +import { + openBasicFunctionalityModal, + openDeleteMetaMetricsDataModal, +} from '../../../ducks/app/app'; import SecurityTab from './security-tab.component'; const mapStateToProps = (state) => { @@ -78,6 +85,9 @@ const mapStateToProps = (state) => { petnamesEnabled, securityAlertsEnabled: getIsSecurityAlertsEnabled(state), useTransactionSimulations: metamask.useTransactionSimulations, + showDeleteMetaMetricsDataModal: getShowDeleteMetaMetricsDataModal(state), + metaMetricsDataDeletionStatus: getMetaMetricsDataDeletionStatus(state), + metaMetricsDataDeletionDate: getMetaMetricsDataDeletionDate(state), }; }; @@ -116,6 +126,12 @@ const mapDispatchToProps = (dispatch) => { setUseTransactionSimulations: (value) => { return dispatch(setUseTransactionSimulations(value)); }, + setDeleteMetaMetricsDataModalOpen: () => { + return dispatch(openDeleteMetaMetricsDataModal()); + }, + checkDataDeletionTaskStatus: () => { + return dispatch(checkDataDeletionTaskStatus()); + }, setSecurityAlertsEnabled: (value) => setSecurityAlertsEnabled(value), }; }; diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index fac2f9f52c31..b4f00bc18dfc 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -2561,6 +2561,26 @@ export function getNameSources(state) { return state.metamask.nameSources || {}; } +export function getShowDeleteMetaMetricsDataModal(state) { + return state.appState.showDeleteMetaMetricsDataModal; +} + +export function getParticipateInMetaMetrics(state) { + return state.metamask.participateInMetaMetrics; +} + +export function getMetaMetricsDataDeletionId(state) { + return state.metamask.metaMetricsDataDeletionId; +} + +export function getMetaMetricsDataDeletionDate(state) { + return state.metamask.metaMetricsDataDeletionDate; +} + +export function getMetaMetricsDataDeletionStatus(state) { + return state.metamask.metaMetricsDataDeletionStatus; +} + /** * To get all installed snaps with proper metadata * diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 074568cfbf1d..16715702e0e2 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -99,6 +99,10 @@ export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE'; export const SET_PARTICIPATE_IN_METAMETRICS = 'SET_PARTICIPATE_IN_METAMETRICS'; export const SET_DATA_COLLECTION_FOR_MARKETING = 'SET_DATA_COLLECTION_FOR_MARKETING'; +export const DELETE_METAMETRICS_DATA_MODAL_OPEN = + 'DELETE_METAMETRICS_DATA_MODAL_OPEN'; +export const DELETE_METAMETRICS_DATA_MODAL_CLOSE = + 'DELETE_METAMETRICS_DATA_MODAL_CLOSE'; // locale export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE'; From ec0ff649eb386cac0bdd94b574386ee5ff3768b2 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Wed, 22 May 2024 15:11:01 -0400 Subject: [PATCH 02/40] updating the status changes --- app/_locales/en/messages.json | 27 ++++------ shared/constants/metametrics.ts | 1 + .../ClearMetaMetricsData.tsx | 42 ++++++--------- ui/ducks/app/app.ts | 48 +++++++++++++++++ .../security-tab/security-tab.component.js | 54 ++++++++++++------- .../security-tab/security-tab.container.js | 12 +++++ ui/selectors/selectors.js | 8 +++ ui/store/actionConstants.ts | 6 +++ 8 files changed, 138 insertions(+), 60 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 7494fa24ba93..543be1ab06a4 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1569,12 +1569,23 @@ "deleteContact": { "message": "Delete contact" }, + "deleteMetaMetricsData": { + "message": "Delete MetaMetrics data" + }, + "deleteMetaMetricsDataDescription": { + "message": "This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our $1.", + "description": "$1 will have text saying Privacy Policy " + }, "deleteMetaMetricsDataModalDesc": { "message": "We are about to remove all your MetaMetrics data. Are you sure?" }, "deleteMetaMetricsDataModalTitle": { "message": "Delete MetaMetrics data?" }, + "deleteMetaMetricsDataRequestedDescription": { + "message": "You initiated this action on $1. This process can take up to 30 days. View the $2", + "description": "$1 will be the date on which teh deletion is requested and $2 will have text saying Privacy Policy " + }, "deleteNetworkIntro": { "message": "If you delete this network, you will need to add it again to view your assets in this network" }, @@ -6693,21 +6704,5 @@ }, "zeroGasPriceOnSpeedUpError": { "message": "Zero gas price on speed up" - }, - "deleteMetaMetricsData": { - "message": "Delete MetaMetrics data" - }, - "deleteMetaMetricsDataDescription": { - "message": "This will delete historical MetaMetrics data associated with your wallet. $1 Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 60 days. View the $2", - "description": "$1 will have the text with bold font (deleteMetaMetricsDataDescriptionBold) regarding metametrics and $2 will have text saying Consensys Privacy Policy " - }, - "deleteMetaMetricsDataDescriptionBold": { - "message": "MetaMetrics data is anonymized usage and diagnostic data." - }, - "consensysPrivacyPolicy": { - "message": "Consensys Privacy Policy" - }, - "deleteMetaMetricsDataRequestedDescription": { - "message": "You initiated this action on $1. This process can take up to 60 days. View the $2" } } diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index 945af5416057..c1b464039eac 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -552,6 +552,7 @@ export enum MetaMetricsEventName { MarkAllNotificationsRead = 'Notifications Marked All as Read', MetricsOptIn = 'Metrics Opt In', MetricsOptOut = 'Metrics Opt Out', + MetricsDataDeletionRequest = 'Delete MetaMetrics Data Request Submitted', NavAccountMenuOpened = 'Account Menu Opened', NavConnectedSitesOpened = 'Connected Sites Opened', NavMainMenuOpened = 'Main Menu Opened', diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx index 6ac36e647e72..b9485ee51cbf 100644 --- a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx +++ b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx @@ -1,6 +1,11 @@ import React, { useContext } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { hideDeleteMetaMetricsDataModal } from '../../../ducks/app/app'; +import { + hideDeleteMetaMetricsDataModal, + markingMetaMetricsDataDeletion, + continueRecordingMetaMetricsData, + stopRecordingMetaMetricsData, +} from '../../../ducks/app/app'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { Box, @@ -23,15 +28,7 @@ import { TextVariant, } from '../../../helpers/constants/design-system'; import { createMetaMetricsDataDeletionTask } from '../../../store/actions'; -import { - DataDeletionResponse, - responseStatus, -} from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; -import { - getMetaMetricsDataDeletionDate, - getMetaMetricsDataDeletionId, - getParticipateInMetaMetrics, -} from '../../../selectors'; +import { getParticipateInMetaMetrics } from '../../../selectors'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsEventCategory, @@ -44,8 +41,6 @@ export default function ClearMetaMetricsData() { const trackEvent = useContext(MetaMetricsContext); const participateInMetaMetrics = useSelector(getParticipateInMetaMetrics); - const id = useSelector(getMetaMetricsDataDeletionId); - const date = useSelector(getMetaMetricsDataDeletionDate); function closeModal() { dispatch(hideDeleteMetaMetricsDataModal()); @@ -53,19 +48,16 @@ export default function ClearMetaMetricsData() { async function deleteMetaMetricsData() { try { - const deleteResponse: DataDeletionResponse = (await dispatch( - createMetaMetricsDataDeletionTask(), - // eslint-disable-next-line @typescript-eslint/no-explicit-any - )) as any; - - if (responseStatus.ok === deleteResponse?.status) { - console.log(`${deleteResponse}---${id}----${date}`); - if (participateInMetaMetrics) { - trackEvent({ - category: MetaMetricsEventCategory.Settings, - event: MetaMetricsEventName.MetricsDataDeletionRequest, - }); - } + await dispatch(createMetaMetricsDataDeletionTask()); + dispatch(markingMetaMetricsDataDeletion()); + if (participateInMetaMetrics) { + dispatch(continueRecordingMetaMetricsData()); + trackEvent({ + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.MetricsDataDeletionRequest, + }); + } else { + dispatch(stopRecordingMetaMetricsData()); } } catch (error: unknown) { // ignore diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index 99599b339868..972f54228201 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -101,6 +101,8 @@ type AppState = { txId: string | null; accountDetailsAddress: string; showDeleteMetaMetricsDataModal: boolean; + metaMetricsDataDeletionMarked: boolean; + hasRecordedMetricsSinceDeletion: boolean; snapsInstallPrivacyWarningShown: boolean; isAddingNewNetwork: boolean; isMultiRpcOnboarding: boolean; @@ -187,6 +189,8 @@ const initialState: AppState = { txId: null, accountDetailsAddress: '', showDeleteMetaMetricsDataModal: false, + metaMetricsDataDeletionMarked: false, + hasRecordedMetricsSinceDeletion: false, snapsInstallPrivacyWarningShown: false, isAddingNewNetwork: false, isMultiRpcOnboarding: false, @@ -620,6 +624,26 @@ export default function reduceApp( ...appState, showDeleteMetaMetricsDataModal: false, }; + case actionConstants.METAMETRICS_DATA_DELETION_MARKED: + return { + ...appState, + metaMetricsDataDeletionMarked: true, + }; + case actionConstants.METAMETRICS_DATA_DELETION_UNMARKED: + return { + ...appState, + metaMetricsDataDeletionMarked: false, + }; + case actionConstants.METAMETRICS_DATA_RECORDING: + return { + ...appState, + hasRecordedMetricsSinceDeletion: true, + }; + case actionConstants.METAMETRICS_DATA_NOT_RECORDING: + return { + ...appState, + hasRecordedMetricsSinceDeletion: false, + }; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) case actionConstants.SHOW_KEYRING_SNAP_REMOVAL_RESULT: return { @@ -741,3 +765,27 @@ export function hideDeleteMetaMetricsDataModal(): Action { type: actionConstants.DELETE_METAMETRICS_DATA_MODAL_CLOSE, }; } + +export function markingMetaMetricsDataDeletion(): Action { + return { + type: actionConstants.METAMETRICS_DATA_DELETION_MARKED, + }; +} + +export function unMarkingMetaMetricsDataDeletion(): Action { + return { + type: actionConstants.METAMETRICS_DATA_DELETION_UNMARKED, + }; +} + +export function continueRecordingMetaMetricsData(): Action { + return { + type: actionConstants.METAMETRICS_DATA_RECORDING, + }; +} + +export function stopRecordingMetaMetricsData(): Action { + return { + type: actionConstants.METAMETRICS_DATA_NOT_RECORDING, + }; +} diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index b6c1f27a6cfa..764a54d2dc06 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -56,9 +56,7 @@ import IncomingTransactionToggle from '../../../components/app/incoming-trasacti import ProfileSyncToggle from './profile-sync-toggle'; import MetametricsToggle from './metametrics-toggle'; import ClearMetametricsData from '../../../components/app/clear-metametrics-data'; -import { - DeleteRegulationStatus, -} from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; +import { DeleteRegulationStatus } from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; import { checkDataDeletionTaskStatus } from '../../../store/actions'; export default class SecurityTab extends PureComponent { @@ -111,6 +109,10 @@ export default class SecurityTab extends PureComponent { setDeleteMetaMetricsDataModalOpen: PropTypes.func.isRequired, metaMetricsDataDeletionStatus: PropTypes.string, metaMetricsDataDeletionDate: PropTypes.string, + metaMetricsDataDeletionMarked: PropTypes.bool.isRequired, + unMarkingMetaMetricsDataDeletion: PropTypes.func.isRequired, + hasRecordedMetricsSinceDeletion: PropTypes.bool.isRequired, + continueRecordingMetaMetricsData: PropTypes.func.isRequired, setSecurityAlertsEnabled: PropTypes.func, }; @@ -152,6 +154,13 @@ export default class SecurityTab extends PureComponent { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); await checkDataDeletionTaskStatus(); + if (this.props.participateInMetaMetrics) { + this.props.continueRecordingMetaMetricsData(); + } + } + + componentWillUnmount() { + this.props.unMarkingMetaMetricsDataDeletion(); } toggleSetting(value, eventName, eventAction, toggleMethod) { @@ -415,17 +424,31 @@ export default class SecurityTab extends PureComponent { const { metaMetricsDataDeletionStatus, metaMetricsDataDeletionDate, - participateInMetaMetrics, + metaMetricsDataDeletionMarked, + hasRecordedMetricsSinceDeletion, } = this.props; + let dataDeletionButtonDisabled = false; if (metaMetricsDataDeletionStatus) { dataDeletionButtonDisabled = - [ + metaMetricsDataDeletionMarked || + ([ DeleteRegulationStatus.INITIALIZED, DeleteRegulationStatus.RUNNING, DeleteRegulationStatus.FINISHED, - ].includes(metaMetricsDataDeletionStatus) && !participateInMetaMetrics; + ].includes(metaMetricsDataDeletionStatus) && + !hasRecordedMetricsSinceDeletion); } + const privacyPolicyLink = ( + + {t('privacyMsg')} + + ); return ( <> {t('deleteMetaMetricsData')}
- {t('deleteMetaMetricsDataDescription', [ - - {t('deleteMetaMetricsDataDescriptionBold')} - , - - {t('consensysPrivacyPolicy')} - , - ])} + {dataDeletionButtonDisabled + ? t('deleteMetaMetricsDataRequestedDescription', [ + metaMetricsDataDeletionDate, + privacyPolicyLink, + ]) + : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])}
diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 0d5d287c9ba7..3f6d685741c5 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -29,10 +29,14 @@ import { getMetaMetricsDataDeletionStatus, getPetnamesEnabled, getShowDeleteMetaMetricsDataModal, + isMetaMetricsDataDeletionMarked, + hasRecordedMetricsSinceDeletion, } from '../../../selectors'; import { + continueRecordingMetaMetricsData, openBasicFunctionalityModal, openDeleteMetaMetricsDataModal, + unMarkingMetaMetricsDataDeletion, } from '../../../ducks/app/app'; import SecurityTab from './security-tab.component'; @@ -88,6 +92,8 @@ const mapStateToProps = (state) => { showDeleteMetaMetricsDataModal: getShowDeleteMetaMetricsDataModal(state), metaMetricsDataDeletionStatus: getMetaMetricsDataDeletionStatus(state), metaMetricsDataDeletionDate: getMetaMetricsDataDeletionDate(state), + metaMetricsDataDeletionMarked: isMetaMetricsDataDeletionMarked(state), + hasRecordedMetricsSinceDeletion: hasRecordedMetricsSinceDeletion(state), }; }; @@ -132,6 +138,12 @@ const mapDispatchToProps = (dispatch) => { checkDataDeletionTaskStatus: () => { return dispatch(checkDataDeletionTaskStatus()); }, + unMarkingMetaMetricsDataDeletion: () => { + return dispatch(unMarkingMetaMetricsDataDeletion()); + }, + continueRecordingMetaMetricsData: () => { + return dispatch(continueRecordingMetaMetricsData()); + }, setSecurityAlertsEnabled: (value) => setSecurityAlertsEnabled(value), }; }; diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index b4f00bc18dfc..981bc55cc0bb 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -2581,6 +2581,14 @@ export function getMetaMetricsDataDeletionStatus(state) { return state.metamask.metaMetricsDataDeletionStatus; } +export function isMetaMetricsDataDeletionMarked(state) { + return state.appState.metaMetricsDataDeletionMarked; +} + +export function hasRecordedMetricsSinceDeletion(state) { + return state.appState.hasRecordedMetricsSinceDeletion; +} + /** * To get all installed snaps with proper metadata * diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 16715702e0e2..648ace33d048 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -103,6 +103,12 @@ export const DELETE_METAMETRICS_DATA_MODAL_OPEN = 'DELETE_METAMETRICS_DATA_MODAL_OPEN'; export const DELETE_METAMETRICS_DATA_MODAL_CLOSE = 'DELETE_METAMETRICS_DATA_MODAL_CLOSE'; +export const METAMETRICS_DATA_DELETION_MARKED = + 'METAMETRICS_DATA_DELETION_MARKED'; +export const METAMETRICS_DATA_DELETION_UNMARKED = + 'METAMETRICS_DATA_DELETION_UNMARKED'; +export const METAMETRICS_DATA_RECORDING = 'METAMETRICS_DATA_RECORDING'; +export const METAMETRICS_DATA_NOT_RECORDING = 'METAMETRICS_DATA_NOT_RECORDING'; // locale export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE'; From 036d91443fae6dd0a1504582af1db6517179b04a Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Wed, 22 May 2024 16:53:51 -0400 Subject: [PATCH 03/40] adding teh error modal --- app/_locales/en/messages.json | 6 ++ .../ClearMetaMetricsData.tsx | 3 +- .../DataDeletionErrorModal.tsx | 99 +++++++++++++++++++ ui/ducks/app/app.ts | 24 +++++ .../security-tab/security-tab.component.js | 12 ++- .../security-tab/security-tab.container.js | 2 + ui/selectors/selectors.js | 4 + ui/store/actionConstants.ts | 4 + 8 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 543be1ab06a4..5e88610c8e44 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1576,6 +1576,12 @@ "message": "This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our $1.", "description": "$1 will have text saying Privacy Policy " }, + "deleteMetaMetricsDataErrorDesc": { + "message": "This request can't be completed right now due to an analytics system server issue, please try again later" + }, + "deleteMetaMetricsDataErrorTitle": { + "message": "We are unable to delete this data right now" + }, "deleteMetaMetricsDataModalDesc": { "message": "We are about to remove all your MetaMetrics data. Are you sure?" }, diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx index b9485ee51cbf..40779a406790 100644 --- a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx +++ b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx @@ -5,6 +5,7 @@ import { markingMetaMetricsDataDeletion, continueRecordingMetaMetricsData, stopRecordingMetaMetricsData, + openDataDeletionErrorModal, } from '../../../ducks/app/app'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { @@ -60,7 +61,7 @@ export default function ClearMetaMetricsData() { dispatch(stopRecordingMetaMetricsData()); } } catch (error: unknown) { - // ignore + dispatch(openDataDeletionErrorModal()); } finally { dispatch(hideDeleteMetaMetricsDataModal()); } diff --git a/ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx b/ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx new file mode 100644 index 000000000000..ae89412e2203 --- /dev/null +++ b/ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx @@ -0,0 +1,99 @@ +import React from 'react'; +import { useDispatch } from 'react-redux'; +import { + Display, + FlexDirection, + AlignItems, + JustifyContent, + TextVariant, + BlockSize, + IconColor, + TextAlign, +} from '../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import { + ModalOverlay, + ModalContent, + ModalHeader, + Modal, + Box, + Text, + ModalFooter, + Button, + IconName, + ButtonVariant, + Icon, + IconSize, + ButtonSize, +} from '../../component-library'; +import { hideDataDeletionErrorModal } from '../../../ducks/app/app'; + +export function DataDeletionErrorModal() { + const t = useI18nContext(); + const dispatch = useDispatch(); + + function closeModal() { + dispatch(hideDataDeletionErrorModal()); + } + + return ( + + + + + + + + {t('deleteMetaMetricsDataErrorTitle')} + + + + + + + {t('deleteMetaMetricsDataErrorDesc')} + + + + + + + + + + + ); +} diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index 972f54228201..b3f540b3d740 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -101,6 +101,7 @@ type AppState = { txId: string | null; accountDetailsAddress: string; showDeleteMetaMetricsDataModal: boolean; + showDataDeletionErrorModal: boolean; metaMetricsDataDeletionMarked: boolean; hasRecordedMetricsSinceDeletion: boolean; snapsInstallPrivacyWarningShown: boolean; @@ -189,6 +190,7 @@ const initialState: AppState = { txId: null, accountDetailsAddress: '', showDeleteMetaMetricsDataModal: false, + showDataDeletionErrorModal: false, metaMetricsDataDeletionMarked: false, hasRecordedMetricsSinceDeletion: false, snapsInstallPrivacyWarningShown: false, @@ -624,6 +626,16 @@ export default function reduceApp( ...appState, showDeleteMetaMetricsDataModal: false, }; + case actionConstants.DATA_DELETION_ERROR_MODAL_OPEN: + return { + ...appState, + showDataDeletionErrorModal: true, + }; + case actionConstants.DATA_DELETION_ERROR_MODAL_CLOSE: + return { + ...appState, + showDataDeletionErrorModal: false, + }; case actionConstants.METAMETRICS_DATA_DELETION_MARKED: return { ...appState, @@ -766,6 +778,18 @@ export function hideDeleteMetaMetricsDataModal(): Action { }; } +export function openDataDeletionErrorModal(): Action { + return { + type: actionConstants.DATA_DELETION_ERROR_MODAL_OPEN, + }; +} + +export function hideDataDeletionErrorModal(): Action { + return { + type: actionConstants.DATA_DELETION_ERROR_MODAL_CLOSE, + }; +} + export function markingMetaMetricsDataDeletion(): Action { return { type: actionConstants.METAMETRICS_DATA_DELETION_MARKED, diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index 764a54d2dc06..70d95951939c 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -58,6 +58,7 @@ import MetametricsToggle from './metametrics-toggle'; import ClearMetametricsData from '../../../components/app/clear-metametrics-data'; import { DeleteRegulationStatus } from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; import { checkDataDeletionTaskStatus } from '../../../store/actions'; +import { DataDeletionErrorModal } from '../../../components/app/clear-metametrics-data/DataDeletionErrorModal'; export default class SecurityTab extends PureComponent { static contextTypes = { @@ -107,6 +108,7 @@ export default class SecurityTab extends PureComponent { toggleExternalServices: PropTypes.func.isRequired, showDeleteMetaMetricsDataModal: PropTypes.bool.isRequired, setDeleteMetaMetricsDataModalOpen: PropTypes.func.isRequired, + showDataDeletionErrorModal: PropTypes.bool.isRequired, metaMetricsDataDeletionStatus: PropTypes.string, metaMetricsDataDeletionDate: PropTypes.string, metaMetricsDataDeletionMarked: PropTypes.bool.isRequired, @@ -422,10 +424,13 @@ export default class SecurityTab extends PureComponent { renderDeleteMetaMetricsData() { const { t } = this.context; const { + hasRecordedMetricsSinceDeletion, metaMetricsDataDeletionStatus, metaMetricsDataDeletionDate, metaMetricsDataDeletionMarked, - hasRecordedMetricsSinceDeletion, + setDeleteMetaMetricsDataModalOpen, + showDeleteMetaMetricsDataModal, + showDataDeletionErrorModal, } = this.props; let dataDeletionButtonDisabled = false; @@ -474,7 +479,7 @@ export default class SecurityTab extends PureComponent { className="settings-page__button" onClick={(event) => { event.preventDefault(); - this.props.setDeleteMetaMetricsDataModalOpen(); + setDeleteMetaMetricsDataModalOpen(); }} disabled={dataDeletionButtonDisabled} > @@ -482,7 +487,8 @@ export default class SecurityTab extends PureComponent {
- {this.props.showDeleteMetaMetricsDataModal && } + {showDeleteMetaMetricsDataModal && } + {showDataDeletionErrorModal && } ); } diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 3f6d685741c5..ed265d028eef 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -31,6 +31,7 @@ import { getShowDeleteMetaMetricsDataModal, isMetaMetricsDataDeletionMarked, hasRecordedMetricsSinceDeletion, + getShowDataDeletionErrorModal, } from '../../../selectors'; import { continueRecordingMetaMetricsData, @@ -90,6 +91,7 @@ const mapStateToProps = (state) => { securityAlertsEnabled: getIsSecurityAlertsEnabled(state), useTransactionSimulations: metamask.useTransactionSimulations, showDeleteMetaMetricsDataModal: getShowDeleteMetaMetricsDataModal(state), + showDataDeletionErrorModal: getShowDataDeletionErrorModal(state), metaMetricsDataDeletionStatus: getMetaMetricsDataDeletionStatus(state), metaMetricsDataDeletionDate: getMetaMetricsDataDeletionDate(state), metaMetricsDataDeletionMarked: isMetaMetricsDataDeletionMarked(state), diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 981bc55cc0bb..81c9a0c051a2 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -2565,6 +2565,10 @@ export function getShowDeleteMetaMetricsDataModal(state) { return state.appState.showDeleteMetaMetricsDataModal; } +export function getShowDataDeletionErrorModal(state) { + return state.appState.showDataDeletionErrorModal; +} + export function getParticipateInMetaMetrics(state) { return state.metamask.participateInMetaMetrics; } diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 648ace33d048..7078f5963aa6 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -103,6 +103,10 @@ export const DELETE_METAMETRICS_DATA_MODAL_OPEN = 'DELETE_METAMETRICS_DATA_MODAL_OPEN'; export const DELETE_METAMETRICS_DATA_MODAL_CLOSE = 'DELETE_METAMETRICS_DATA_MODAL_CLOSE'; +export const DATA_DELETION_ERROR_MODAL_OPEN = + 'DELETE_METAMETRICS_DATA_ERROR_MODAL_OPEN'; +export const DATA_DELETION_ERROR_MODAL_CLOSE = + 'DELETE_METAMETRICS_DATA_ERROR_MODAL_CLOSE'; export const METAMETRICS_DATA_DELETION_MARKED = 'METAMETRICS_DATA_DELETION_MARKED'; export const METAMETRICS_DATA_DELETION_UNMARKED = From 337ab3c3ce7ea7368950f6913212692947660cd3 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Wed, 22 May 2024 17:23:14 -0400 Subject: [PATCH 04/40] updating the method name to updateDataDeletionTaskStatus --- ui/pages/settings/security-tab/security-tab.component.js | 4 ++-- ui/pages/settings/security-tab/security-tab.container.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index 70d95951939c..fb3c562e628f 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -57,7 +57,7 @@ import ProfileSyncToggle from './profile-sync-toggle'; import MetametricsToggle from './metametrics-toggle'; import ClearMetametricsData from '../../../components/app/clear-metametrics-data'; import { DeleteRegulationStatus } from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; -import { checkDataDeletionTaskStatus } from '../../../store/actions'; +import { updateDataDeletionTaskStatus } from '../../../store/actions'; import { DataDeletionErrorModal } from '../../../components/app/clear-metametrics-data/DataDeletionErrorModal'; export default class SecurityTab extends PureComponent { @@ -155,7 +155,7 @@ export default class SecurityTab extends PureComponent { async componentDidMount() { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); - await checkDataDeletionTaskStatus(); + await updateDataDeletionTaskStatus(); if (this.props.participateInMetaMetrics) { this.props.continueRecordingMetaMetricsData(); } diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index ed265d028eef..b3968f533675 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -20,7 +20,7 @@ import { setUseExternalNameSources, setUseTransactionSimulations, setSecurityAlertsEnabled, - checkDataDeletionTaskStatus, + updateDataDeletionTaskStatus, } from '../../../store/actions'; import { getIsSecurityAlertsEnabled, @@ -137,8 +137,8 @@ const mapDispatchToProps = (dispatch) => { setDeleteMetaMetricsDataModalOpen: () => { return dispatch(openDeleteMetaMetricsDataModal()); }, - checkDataDeletionTaskStatus: () => { - return dispatch(checkDataDeletionTaskStatus()); + updateDataDeletionTaskStatus: () => { + return dispatch(updateDataDeletionTaskStatus()); }, unMarkingMetaMetricsDataDeletion: () => { return dispatch(unMarkingMetaMetricsDataDeletion()); From ea06cad30e49bee070abf8a8b9452abfddf01e93 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Mon, 27 May 2024 14:28:59 -0400 Subject: [PATCH 05/40] refactoring the new delete metametrics entry to a functional componenet --- .../ClearMetaMetricsData.tsx | 8 +- .../DataDeletionErrorModal.tsx | 2 +- .../app/data-deletion-error-modal/index.ts | 1 + .../delete-metametrics-data-toggle.tsx | 106 ++++++++++++++++++ .../delete-metametrics-data-toggle/index.ts | 1 + .../metametrics-toggle/metametrics-toggle.tsx | 5 +- .../security-tab/security-tab.component.js | 93 +-------------- .../security-tab/security-tab.container.js | 16 --- 8 files changed, 123 insertions(+), 109 deletions(-) rename ui/components/app/{clear-metametrics-data => data-deletion-error-modal}/DataDeletionErrorModal.tsx (97%) create mode 100644 ui/components/app/data-deletion-error-modal/index.ts create mode 100644 ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx create mode 100644 ui/pages/settings/security-tab/delete-metametrics-data-toggle/index.ts diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx index 40779a406790..30d94e80c148 100644 --- a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx +++ b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx @@ -43,11 +43,11 @@ export default function ClearMetaMetricsData() { const participateInMetaMetrics = useSelector(getParticipateInMetaMetrics); - function closeModal() { + const closeModal = () => { dispatch(hideDeleteMetaMetricsDataModal()); - } + }; - async function deleteMetaMetricsData() { + const deleteMetaMetricsData = async () => { try { await dispatch(createMetaMetricsDataDeletionTask()); dispatch(markingMetaMetricsDataDeletion()); @@ -65,7 +65,7 @@ export default function ClearMetaMetricsData() { } finally { dispatch(hideDeleteMetaMetricsDataModal()); } - } + }; return ( diff --git a/ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx b/ui/components/app/data-deletion-error-modal/DataDeletionErrorModal.tsx similarity index 97% rename from ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx rename to ui/components/app/data-deletion-error-modal/DataDeletionErrorModal.tsx index ae89412e2203..0b6be4fa782b 100644 --- a/ui/components/app/clear-metametrics-data/DataDeletionErrorModal.tsx +++ b/ui/components/app/data-deletion-error-modal/DataDeletionErrorModal.tsx @@ -28,7 +28,7 @@ import { } from '../../component-library'; import { hideDataDeletionErrorModal } from '../../../ducks/app/app'; -export function DataDeletionErrorModal() { +export default function DataDeletionErrorModal() { const t = useI18nContext(); const dispatch = useDispatch(); diff --git a/ui/components/app/data-deletion-error-modal/index.ts b/ui/components/app/data-deletion-error-modal/index.ts new file mode 100644 index 000000000000..f8f03f6c09bf --- /dev/null +++ b/ui/components/app/data-deletion-error-modal/index.ts @@ -0,0 +1 @@ +export { default } from './DataDeletionErrorModal'; diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx new file mode 100644 index 000000000000..22c4db820d60 --- /dev/null +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx @@ -0,0 +1,106 @@ +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { CONSENSYS_PRIVACY_LINK } from '../../../../../shared/lib/ui-utils'; +import ClearMetametricsData from '../../../../components/app/clear-metametrics-data'; +import { Box, ButtonPrimary } from '../../../../components/component-library'; +import { + Display, + FlexDirection, +} from '../../../../helpers/constants/design-system'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +import { + getMetaMetricsDataDeletionDate, + getMetaMetricsDataDeletionStatus, + getShowDataDeletionErrorModal, + getShowDeleteMetaMetricsDataModal, + hasRecordedMetricsSinceDeletion, + isMetaMetricsDataDeletionMarked, +} from '../../../../selectors'; +import { DeleteRegulationStatus } from '../../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; +import { openDeleteMetaMetricsDataModal } from '../../../../ducks/app/app'; +import DataDeletionErrorModal from '../../../../components/app/data-deletion-error-modal'; + +const DeleteMetaMetricsDataToggle = () => { + const t = useI18nContext(); + const dispatch = useDispatch(); + + const hasMetricsDataRecordedAfterLastDeletion = useSelector( + hasRecordedMetricsSinceDeletion, + ); + const metaMetricsDataDeletionStatus = useSelector( + getMetaMetricsDataDeletionStatus, + ); + const metaMetricsDataDeletionDate = useSelector( + getMetaMetricsDataDeletionDate, + ); + const metaMetricsDataDeletionMarked = useSelector( + isMetaMetricsDataDeletionMarked, + ); + const showDeleteMetaMetricsDataModal = useSelector( + getShowDeleteMetaMetricsDataModal, + ); + const showDataDeletionErrorModal = useSelector(getShowDataDeletionErrorModal); + console.log(showDataDeletionErrorModal); + + let dataDeletionButtonDisabled = false; + if (metaMetricsDataDeletionStatus) { + dataDeletionButtonDisabled = + metaMetricsDataDeletionMarked || + ([ + DeleteRegulationStatus.INITIALIZED, + DeleteRegulationStatus.RUNNING, + DeleteRegulationStatus.FINISHED, + ].includes(metaMetricsDataDeletionStatus) && + !hasMetricsDataRecordedAfterLastDeletion); + } + + const privacyPolicyLink = ( + + {t('privacyMsg')} + + ); + return ( + <> + +
+ {t('deleteMetaMetricsData')} +
+ {dataDeletionButtonDisabled + ? t('deleteMetaMetricsDataRequestedDescription', [ + metaMetricsDataDeletionDate, + privacyPolicyLink, + ]) + : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])} +
+
+
+ { + // event.preventDefault(); + dispatch(openDeleteMetaMetricsDataModal()); + }} + disabled={dataDeletionButtonDisabled} + > + {t('deleteMetaMetricsData')} + +
+
+ {showDeleteMetaMetricsDataModal && } + {showDataDeletionErrorModal && } + + ); +}; + +export default DeleteMetaMetricsDataToggle; diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/index.ts b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/index.ts new file mode 100644 index 000000000000..88bbefe41a5b --- /dev/null +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/index.ts @@ -0,0 +1 @@ +export { default } from './delete-metametrics-data-toggle'; diff --git a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx index 661dd7f974b4..e08101a61d21 100644 --- a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx +++ b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx @@ -1,5 +1,5 @@ import React, { useContext } from 'react'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import { MetaMetricsContext } from '../../../../contexts/metametrics'; import { @@ -21,6 +21,7 @@ import { TextColor, TextVariant, } from '../../../../helpers/constants/design-system'; +import { continueRecordingMetaMetricsData } from '../../../../ducks/app/app'; const MetametricsToggle = ({ dataCollectionForMarketing, @@ -30,6 +31,7 @@ const MetametricsToggle = ({ setDataCollectionForMarketing: (value: boolean) => void; }) => { const t = useI18nContext(); + const dispatch = useDispatch(); const trackEvent = useContext(MetaMetricsContext); const { enableMetametrics, error: enableMetametricsError } = useEnableMetametrics(); @@ -72,6 +74,7 @@ const MetametricsToggle = ({ participateInMetaMetrics, }, }); + dispatch(continueRecordingMetaMetricsData()); } if (dataCollectionForMarketing) { diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index fb3c562e628f..5b9100df2787 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -32,7 +32,6 @@ import { IconName, Box, Text, - ButtonPrimary, } from '../../../components/component-library'; import TextField from '../../../components/ui/text-field'; import ToggleButton from '../../../components/ui/toggle-button'; @@ -53,12 +52,10 @@ import { } from '../../../helpers/utils/settings-search'; import IncomingTransactionToggle from '../../../components/app/incoming-trasaction-toggle/incoming-transaction-toggle'; -import ProfileSyncToggle from './profile-sync-toggle'; -import MetametricsToggle from './metametrics-toggle'; -import ClearMetametricsData from '../../../components/app/clear-metametrics-data'; -import { DeleteRegulationStatus } from '../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; import { updateDataDeletionTaskStatus } from '../../../store/actions'; -import { DataDeletionErrorModal } from '../../../components/app/clear-metametrics-data/DataDeletionErrorModal'; +import MetametricsToggle from './metametrics-toggle'; +import ProfileSyncToggle from './profile-sync-toggle'; +import DeleteMetametricsDataToggle from './delete-metametrics-data-toggle'; export default class SecurityTab extends PureComponent { static contextTypes = { @@ -106,15 +103,9 @@ export default class SecurityTab extends PureComponent { securityAlertsEnabled: PropTypes.bool, useExternalServices: PropTypes.bool, toggleExternalServices: PropTypes.func.isRequired, - showDeleteMetaMetricsDataModal: PropTypes.bool.isRequired, - setDeleteMetaMetricsDataModalOpen: PropTypes.func.isRequired, - showDataDeletionErrorModal: PropTypes.bool.isRequired, - metaMetricsDataDeletionStatus: PropTypes.string, - metaMetricsDataDeletionDate: PropTypes.string, - metaMetricsDataDeletionMarked: PropTypes.bool.isRequired, - unMarkingMetaMetricsDataDeletion: PropTypes.func.isRequired, - hasRecordedMetricsSinceDeletion: PropTypes.bool.isRequired, + participateInMetaMetrics: PropTypes.bool.isRequired, continueRecordingMetaMetricsData: PropTypes.func.isRequired, + unMarkingMetaMetricsDataDeletion: PropTypes.func.isRequired, setSecurityAlertsEnabled: PropTypes.func, }; @@ -421,78 +412,6 @@ export default class SecurityTab extends PureComponent { ); } - renderDeleteMetaMetricsData() { - const { t } = this.context; - const { - hasRecordedMetricsSinceDeletion, - metaMetricsDataDeletionStatus, - metaMetricsDataDeletionDate, - metaMetricsDataDeletionMarked, - setDeleteMetaMetricsDataModalOpen, - showDeleteMetaMetricsDataModal, - showDataDeletionErrorModal, - } = this.props; - - let dataDeletionButtonDisabled = false; - if (metaMetricsDataDeletionStatus) { - dataDeletionButtonDisabled = - metaMetricsDataDeletionMarked || - ([ - DeleteRegulationStatus.INITIALIZED, - DeleteRegulationStatus.RUNNING, - DeleteRegulationStatus.FINISHED, - ].includes(metaMetricsDataDeletionStatus) && - !hasRecordedMetricsSinceDeletion); - } - const privacyPolicyLink = ( - - {t('privacyMsg')} - - ); - return ( - <> - -
- {t('deleteMetaMetricsData')} -
- {dataDeletionButtonDisabled - ? t('deleteMetaMetricsDataRequestedDescription', [ - metaMetricsDataDeletionDate, - privacyPolicyLink, - ]) - : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])} -
-
-
- { - event.preventDefault(); - setDeleteMetaMetricsDataModalOpen(); - }} - disabled={dataDeletionButtonDisabled} - > - {t('deleteMetaMetricsData')} - -
-
- {showDeleteMetaMetricsDataModal && } - {showDataDeletionErrorModal && } - - ); - } - renderChooseYourNetworkButton() { const { t } = this.context; @@ -1316,7 +1235,7 @@ export default class SecurityTab extends PureComponent { setDataCollectionForMarketing={setDataCollectionForMarketing} /> {this.renderDataCollectionForMarketing()} - {this.renderDeleteMetaMetricsData()} + ); diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index b3968f533675..78987cd1852e 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -25,18 +25,11 @@ import { import { getIsSecurityAlertsEnabled, getNetworkConfigurationsByChainId, - getMetaMetricsDataDeletionDate, - getMetaMetricsDataDeletionStatus, getPetnamesEnabled, - getShowDeleteMetaMetricsDataModal, - isMetaMetricsDataDeletionMarked, - hasRecordedMetricsSinceDeletion, - getShowDataDeletionErrorModal, } from '../../../selectors'; import { continueRecordingMetaMetricsData, openBasicFunctionalityModal, - openDeleteMetaMetricsDataModal, unMarkingMetaMetricsDataDeletion, } from '../../../ducks/app/app'; import SecurityTab from './security-tab.component'; @@ -90,12 +83,6 @@ const mapStateToProps = (state) => { petnamesEnabled, securityAlertsEnabled: getIsSecurityAlertsEnabled(state), useTransactionSimulations: metamask.useTransactionSimulations, - showDeleteMetaMetricsDataModal: getShowDeleteMetaMetricsDataModal(state), - showDataDeletionErrorModal: getShowDataDeletionErrorModal(state), - metaMetricsDataDeletionStatus: getMetaMetricsDataDeletionStatus(state), - metaMetricsDataDeletionDate: getMetaMetricsDataDeletionDate(state), - metaMetricsDataDeletionMarked: isMetaMetricsDataDeletionMarked(state), - hasRecordedMetricsSinceDeletion: hasRecordedMetricsSinceDeletion(state), }; }; @@ -134,9 +121,6 @@ const mapDispatchToProps = (dispatch) => { setUseTransactionSimulations: (value) => { return dispatch(setUseTransactionSimulations(value)); }, - setDeleteMetaMetricsDataModalOpen: () => { - return dispatch(openDeleteMetaMetricsDataModal()); - }, updateDataDeletionTaskStatus: () => { return dispatch(updateDataDeletionTaskStatus()); }, From d125e386f218eed3c3569676b321c90ded391799 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 30 May 2024 15:49:26 -0400 Subject: [PATCH 06/40] moving hasDataRecorded to controller state and managing the case where metametricsId is null --- .../ClearMetaMetricsData.tsx | 11 +++++---- ui/ducks/app/app.ts | 24 ------------------- .../delete-metametrics-data-toggle.tsx | 21 +++++++++------- .../metametrics-toggle/metametrics-toggle.tsx | 4 ++-- .../security-tab/security-tab.component.js | 5 ---- .../security-tab/security-tab.container.js | 4 ---- ui/selectors/selectors.js | 2 +- ui/store/actionConstants.ts | 2 -- 8 files changed, 21 insertions(+), 52 deletions(-) diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx index 30d94e80c148..26d4443a9e03 100644 --- a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx +++ b/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx @@ -3,8 +3,6 @@ import { useDispatch, useSelector } from 'react-redux'; import { hideDeleteMetaMetricsDataModal, markingMetaMetricsDataDeletion, - continueRecordingMetaMetricsData, - stopRecordingMetaMetricsData, openDataDeletionErrorModal, } from '../../../ducks/app/app'; import { useI18nContext } from '../../../hooks/useI18nContext'; @@ -28,7 +26,10 @@ import { JustifyContent, TextVariant, } from '../../../helpers/constants/design-system'; -import { createMetaMetricsDataDeletionTask } from '../../../store/actions'; +import { + createMetaMetricsDataDeletionTask, + setHasMetaMetricsDataRecorded, +} from '../../../store/actions'; import { getParticipateInMetaMetrics } from '../../../selectors'; import { MetaMetricsContext } from '../../../contexts/metametrics'; import { @@ -52,13 +53,13 @@ export default function ClearMetaMetricsData() { await dispatch(createMetaMetricsDataDeletionTask()); dispatch(markingMetaMetricsDataDeletion()); if (participateInMetaMetrics) { - dispatch(continueRecordingMetaMetricsData()); + dispatch(setHasMetaMetricsDataRecorded(true)); trackEvent({ category: MetaMetricsEventCategory.Settings, event: MetaMetricsEventName.MetricsDataDeletionRequest, }); } else { - dispatch(stopRecordingMetaMetricsData()); + dispatch(setHasMetaMetricsDataRecorded(false)); } } catch (error: unknown) { dispatch(openDataDeletionErrorModal()); diff --git a/ui/ducks/app/app.ts b/ui/ducks/app/app.ts index b3f540b3d740..ccd384f39040 100644 --- a/ui/ducks/app/app.ts +++ b/ui/ducks/app/app.ts @@ -103,7 +103,6 @@ type AppState = { showDeleteMetaMetricsDataModal: boolean; showDataDeletionErrorModal: boolean; metaMetricsDataDeletionMarked: boolean; - hasRecordedMetricsSinceDeletion: boolean; snapsInstallPrivacyWarningShown: boolean; isAddingNewNetwork: boolean; isMultiRpcOnboarding: boolean; @@ -192,7 +191,6 @@ const initialState: AppState = { showDeleteMetaMetricsDataModal: false, showDataDeletionErrorModal: false, metaMetricsDataDeletionMarked: false, - hasRecordedMetricsSinceDeletion: false, snapsInstallPrivacyWarningShown: false, isAddingNewNetwork: false, isMultiRpcOnboarding: false, @@ -646,16 +644,6 @@ export default function reduceApp( ...appState, metaMetricsDataDeletionMarked: false, }; - case actionConstants.METAMETRICS_DATA_RECORDING: - return { - ...appState, - hasRecordedMetricsSinceDeletion: true, - }; - case actionConstants.METAMETRICS_DATA_NOT_RECORDING: - return { - ...appState, - hasRecordedMetricsSinceDeletion: false, - }; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) case actionConstants.SHOW_KEYRING_SNAP_REMOVAL_RESULT: return { @@ -801,15 +789,3 @@ export function unMarkingMetaMetricsDataDeletion(): Action { type: actionConstants.METAMETRICS_DATA_DELETION_UNMARKED, }; } - -export function continueRecordingMetaMetricsData(): Action { - return { - type: actionConstants.METAMETRICS_DATA_RECORDING, - }; -} - -export function stopRecordingMetaMetricsData(): Action { - return { - type: actionConstants.METAMETRICS_DATA_NOT_RECORDING, - }; -} diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx index 22c4db820d60..6aa3dd76e7ad 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx @@ -11,6 +11,7 @@ import { useI18nContext } from '../../../../hooks/useI18nContext'; import { getMetaMetricsDataDeletionDate, getMetaMetricsDataDeletionStatus, + getMetaMetricsId, getShowDataDeletionErrorModal, getShowDeleteMetaMetricsDataModal, hasRecordedMetricsSinceDeletion, @@ -19,12 +20,14 @@ import { import { DeleteRegulationStatus } from '../../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; import { openDeleteMetaMetricsDataModal } from '../../../../ducks/app/app'; import DataDeletionErrorModal from '../../../../components/app/data-deletion-error-modal'; +import { formatDate } from '../../../../helpers/utils/util'; const DeleteMetaMetricsDataToggle = () => { const t = useI18nContext(); const dispatch = useDispatch(); - const hasMetricsDataRecordedAfterLastDeletion = useSelector( + const metaMetricsId = useSelector(getMetaMetricsId); + const hasMetricsRecordedAfterDeletion = useSelector( hasRecordedMetricsSinceDeletion, ); const metaMetricsDataDeletionStatus = useSelector( @@ -33,6 +36,8 @@ const DeleteMetaMetricsDataToggle = () => { const metaMetricsDataDeletionDate = useSelector( getMetaMetricsDataDeletionDate, ); + const formatedDate = formatDate(metaMetricsDataDeletionDate, 'd/MM/y'); + const metaMetricsDataDeletionMarked = useSelector( isMetaMetricsDataDeletionMarked, ); @@ -40,18 +45,17 @@ const DeleteMetaMetricsDataToggle = () => { getShowDeleteMetaMetricsDataModal, ); const showDataDeletionErrorModal = useSelector(getShowDataDeletionErrorModal); - console.log(showDataDeletionErrorModal); - let dataDeletionButtonDisabled = false; - if (metaMetricsDataDeletionStatus) { + let dataDeletionButtonDisabled = + metaMetricsDataDeletionMarked || Boolean(!metaMetricsId) || !hasMetricsRecordedAfterDeletion; + if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { dataDeletionButtonDisabled = - metaMetricsDataDeletionMarked || - ([ + [ DeleteRegulationStatus.INITIALIZED, DeleteRegulationStatus.RUNNING, DeleteRegulationStatus.FINISHED, ].includes(metaMetricsDataDeletionStatus) && - !hasMetricsDataRecordedAfterLastDeletion); + !hasMetricsRecordedAfterDeletion; } const privacyPolicyLink = ( @@ -78,7 +82,7 @@ const DeleteMetaMetricsDataToggle = () => {
{dataDeletionButtonDisabled ? t('deleteMetaMetricsDataRequestedDescription', [ - metaMetricsDataDeletionDate, + formatedDate, privacyPolicyLink, ]) : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])} @@ -88,7 +92,6 @@ const DeleteMetaMetricsDataToggle = () => { { - // event.preventDefault(); dispatch(openDeleteMetaMetricsDataModal()); }} disabled={dataDeletionButtonDisabled} diff --git a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx index e08101a61d21..1182c7af8924 100644 --- a/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx +++ b/ui/pages/settings/security-tab/metametrics-toggle/metametrics-toggle.tsx @@ -21,7 +21,7 @@ import { TextColor, TextVariant, } from '../../../../helpers/constants/design-system'; -import { continueRecordingMetaMetricsData } from '../../../../ducks/app/app'; +import { setHasMetaMetricsDataRecorded } from '../../../../store/actions'; const MetametricsToggle = ({ dataCollectionForMarketing, @@ -74,7 +74,7 @@ const MetametricsToggle = ({ participateInMetaMetrics, }, }); - dispatch(continueRecordingMetaMetricsData()); + dispatch(setHasMetaMetricsDataRecorded(true)); } if (dataCollectionForMarketing) { diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index 5b9100df2787..c37a7bc9a971 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -103,8 +103,6 @@ export default class SecurityTab extends PureComponent { securityAlertsEnabled: PropTypes.bool, useExternalServices: PropTypes.bool, toggleExternalServices: PropTypes.func.isRequired, - participateInMetaMetrics: PropTypes.bool.isRequired, - continueRecordingMetaMetricsData: PropTypes.func.isRequired, unMarkingMetaMetricsDataDeletion: PropTypes.func.isRequired, setSecurityAlertsEnabled: PropTypes.func, }; @@ -147,9 +145,6 @@ export default class SecurityTab extends PureComponent { const { t } = this.context; handleSettingsRefs(t, t('securityAndPrivacy'), this.settingsRefs); await updateDataDeletionTaskStatus(); - if (this.props.participateInMetaMetrics) { - this.props.continueRecordingMetaMetricsData(); - } } componentWillUnmount() { diff --git a/ui/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js index 78987cd1852e..683d80e2ea33 100644 --- a/ui/pages/settings/security-tab/security-tab.container.js +++ b/ui/pages/settings/security-tab/security-tab.container.js @@ -28,7 +28,6 @@ import { getPetnamesEnabled, } from '../../../selectors'; import { - continueRecordingMetaMetricsData, openBasicFunctionalityModal, unMarkingMetaMetricsDataDeletion, } from '../../../ducks/app/app'; @@ -127,9 +126,6 @@ const mapDispatchToProps = (dispatch) => { unMarkingMetaMetricsDataDeletion: () => { return dispatch(unMarkingMetaMetricsDataDeletion()); }, - continueRecordingMetaMetricsData: () => { - return dispatch(continueRecordingMetaMetricsData()); - }, setSecurityAlertsEnabled: (value) => setSecurityAlertsEnabled(value), }; }; diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js index 81c9a0c051a2..43003bd50777 100644 --- a/ui/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -2590,7 +2590,7 @@ export function isMetaMetricsDataDeletionMarked(state) { } export function hasRecordedMetricsSinceDeletion(state) { - return state.appState.hasRecordedMetricsSinceDeletion; + return state.metamask.hasMetaMetricsDataRecorded; } /** diff --git a/ui/store/actionConstants.ts b/ui/store/actionConstants.ts index 7078f5963aa6..5f5cb5e807c9 100644 --- a/ui/store/actionConstants.ts +++ b/ui/store/actionConstants.ts @@ -111,8 +111,6 @@ export const METAMETRICS_DATA_DELETION_MARKED = 'METAMETRICS_DATA_DELETION_MARKED'; export const METAMETRICS_DATA_DELETION_UNMARKED = 'METAMETRICS_DATA_DELETION_UNMARKED'; -export const METAMETRICS_DATA_RECORDING = 'METAMETRICS_DATA_RECORDING'; -export const METAMETRICS_DATA_NOT_RECORDING = 'METAMETRICS_DATA_NOT_RECORDING'; // locale export const SET_CURRENT_LOCALE = 'SET_CURRENT_LOCALE'; From d015c9379882c071045aed9d06cb695561a0bbc1 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Fri, 7 Jun 2024 15:26:40 -0400 Subject: [PATCH 07/40] adding unit tests --- .../clear-metametrics-data.test.tsx | 19 ++ ...icsData.tsx => clear-metametrics-data.tsx} | 0 .../app/clear-metametrics-data/index.ts | 2 +- .../data-deletion-error-modal.test.tsx | 21 ++ ...odal.tsx => data-deletion-error-modal.tsx} | 0 .../app/data-deletion-error-modal/index.ts | 2 +- .../__snapshots__/security-tab.test.js.snap | 85 ++++--- .../delete-metametrics-data-toggle.test.tsx | 214 ++++++++++++++++++ .../delete-metametrics-data-toggle.tsx | 6 +- .../security-tab/security-tab.test.js | 29 +++ 10 files changed, 342 insertions(+), 36 deletions(-) create mode 100644 ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx rename ui/components/app/clear-metametrics-data/{ClearMetaMetricsData.tsx => clear-metametrics-data.tsx} (100%) create mode 100644 ui/components/app/data-deletion-error-modal/data-deletion-error-modal.test.tsx rename ui/components/app/data-deletion-error-modal/{DataDeletionErrorModal.tsx => data-deletion-error-modal.tsx} (100%) create mode 100644 ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx diff --git a/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx b/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx new file mode 100644 index 000000000000..970e094ff035 --- /dev/null +++ b/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx @@ -0,0 +1,19 @@ +import * as React from 'react'; +import configureStore from '../../../store/store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; + +import ClearMetaMetricsData from './clear-metametrics-data'; + +describe('ClearMetaMetricsData', () => { + it('should render the data deletion error modal', async () => { + const store = configureStore({}); + const { getByText } = renderWithProvider(, store); + + expect(getByText('Delete MetaMetrics data?')).toBeInTheDocument(); + expect( + getByText( + 'We are about to remove all your MetaMetrics data. Are you sure?', + ), + ).toBeInTheDocument(); + }); +}); diff --git a/ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx b/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx similarity index 100% rename from ui/components/app/clear-metametrics-data/ClearMetaMetricsData.tsx rename to ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx diff --git a/ui/components/app/clear-metametrics-data/index.ts b/ui/components/app/clear-metametrics-data/index.ts index 1f7146583f5b..b29aee18d564 100644 --- a/ui/components/app/clear-metametrics-data/index.ts +++ b/ui/components/app/clear-metametrics-data/index.ts @@ -1 +1 @@ -export { default } from './ClearMetaMetricsData'; +export { default } from './clear-metametrics-data'; diff --git a/ui/components/app/data-deletion-error-modal/data-deletion-error-modal.test.tsx b/ui/components/app/data-deletion-error-modal/data-deletion-error-modal.test.tsx new file mode 100644 index 000000000000..6605e687d4f8 --- /dev/null +++ b/ui/components/app/data-deletion-error-modal/data-deletion-error-modal.test.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import configureStore from '../../../store/store'; +import { renderWithProvider } from '../../../../test/lib/render-helpers'; + +import DataDeletionErrorModal from './data-deletion-error-modal'; + +describe('DataDeletionErrorModal', () => { + it('should render data deletion error modal', async () => { + const store = configureStore({}); + const { getByText } = renderWithProvider(, store); + + expect( + getByText('We are unable to delete this data right now'), + ).toBeInTheDocument(); + expect( + getByText( + "This request can't be completed right now due to an analytics system server issue, please try again later", + ), + ).toBeInTheDocument(); + }); +}); diff --git a/ui/components/app/data-deletion-error-modal/DataDeletionErrorModal.tsx b/ui/components/app/data-deletion-error-modal/data-deletion-error-modal.tsx similarity index 100% rename from ui/components/app/data-deletion-error-modal/DataDeletionErrorModal.tsx rename to ui/components/app/data-deletion-error-modal/data-deletion-error-modal.tsx diff --git a/ui/components/app/data-deletion-error-modal/index.ts b/ui/components/app/data-deletion-error-modal/index.ts index f8f03f6c09bf..383efd7029b5 100644 --- a/ui/components/app/data-deletion-error-modal/index.ts +++ b/ui/components/app/data-deletion-error-modal/index.ts @@ -1 +1 @@ -export { default } from './DataDeletionErrorModal'; +export { default } from './data-deletion-error-modal'; diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index d18da9cc2eca..2a06990b3d8f 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -19,8 +19,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - MetaMask offers basic features like token details and gas settings through internet services. When you use internet services, your IP address is shared, in this case with MetaMask. This is just like when you visit any website. MetaMask uses this data temporarily and never sells your data. You can use a VPN or turn off these services, but it may affect your MetaMask experience. To learn more read our + + MetaMask offers basic features like token details and gas settings through internet services. When you use internet services, your IP address is shared, in this case with MetaMask. This is just like when you visit any website. MetaMask uses this data temporarily and never sells your data. You can use a VPN or turn off these services, but it may affect your MetaMask experience. To learn more read our . - +
@@ -130,8 +130,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - This feature alerts you to malicious activity by actively reviewing transaction and signature requests. + + This feature alerts you to malicious activity by actively reviewing transaction and signature requests. Learn more - - + + @@ -223,8 +223,8 @@ exports[`Security Tab should match snapshot 1`] = ` data-testid="profileSyncDescription" > - - Creates a profile that MetaMask uses to sync some settings among your devices. This is required to get notifications. + + Creates a profile that MetaMask uses to sync some settings among your devices. This is required to get notifications. . - + @@ -466,8 +466,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - We use + + We use CoinGecko - and + and CryptoCompare - APIs to display your balance and token price. + APIs to display your balance and token price. Privacy policy - - + + @@ -744,8 +744,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - Turn this on to estimate balance changes of transactions before you confirm them. This doesn't guarantee the final outcome of your transactions. + + Turn this on to estimate balance changes of transactions before you confirm them. This doesn't guarantee the final outcome of your transactions. Learn more - - + + @@ -832,8 +832,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - We use Infura as our remote procedure call (RPC) provider to offer the most reliable and private access to Ethereum data we can. You can choose your own RPC, but remember that any RPC will receive your IP address and Ethereum wallet to make transactions. Read our + + We use Infura as our remote procedure call (RPC) provider to offer the most reliable and private access to Ethereum data we can. You can choose your own RPC, but remember that any RPC will receive your IP address and Ethereum wallet to make transactions. Read our to learn more about how Infura handles data. - + @@ -875,13 +875,13 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - MetaMask uses a third-party service called + + MetaMask uses a third-party service called chainid.network to show accurate and standardized network details. This reduces your chances of connecting to malicious or incorrect network. When using this feature, your IP address is exposed to chainid.network. - + @@ -1030,7 +1030,7 @@ exports[`Security Tab should match snapshot 1`] = ` value="dweb.link" /> - + @@ -1146,8 +1146,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want the app to automatically pull data from those services. + + We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want the app to automatically pull data from those services. Learn More - - + + @@ -1495,18 +1495,34 @@ exports[`Security Tab should match snapshot 1`] = `
Data collection for marketing + Delete MetaMetrics data
We'll use MetaMetrics to learn how you interact with our marketing communications. We may share relevant news (like product features and other materials). + + You initiated this action on + + . This process can take up to 30 days. View the + + Privacy policy + + +
@@ -1559,6 +1575,13 @@ exports[`Security Tab should match snapshot 1`] = `
+ > + diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx new file mode 100644 index 000000000000..b87f6d785006 --- /dev/null +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx @@ -0,0 +1,214 @@ +import * as React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { fireEvent } from '@testing-library/react'; +import configureStore from '../../../../store/store'; +// import mockState from '../../../../../test/data/mock-state.json'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; + +import { + getMetaMetricsDataDeletionDate, + getMetaMetricsDataDeletionStatus, + getMetaMetricsId, + hasRecordedMetricsSinceDeletion, + isMetaMetricsDataDeletionMarked, +} from '../../../../selectors'; +import { openDeleteMetaMetricsDataModal } from '../../../../ducks/app/app'; +import DeleteMetaMetricsDataToggle from './delete-metametrics-data-toggle'; + +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useSelector: jest.fn(), + useDispatch: jest.fn(), +})); + +describe('DeleteMetaMetricsDataToggle', () => { + const useSelectorMock = useSelector as jest.Mock; + const useDispatchMock = useDispatch as jest.Mock; + const mockDispatch = jest.fn(); + + beforeEach(() => { + useDispatchMock.mockReturnValue(mockDispatch); + useSelectorMock.mockImplementation((selector) => { + if (selector === isMetaMetricsDataDeletionMarked) { + return false; + } + if (selector === getMetaMetricsId) { + return 'fake-metrics-id'; + } + if (selector === hasRecordedMetricsSinceDeletion) { + return undefined; + } + if (selector === getMetaMetricsDataDeletionStatus) { + return undefined; + } + if (selector === getMetaMetricsDataDeletionDate) { + return ''; + } + + return undefined; + }); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('renders correctly', () => { + const store = configureStore({}); + const { getByText, getByTestId, getAllByText } = renderWithProvider( + , + store, + ); + expect(getByTestId('delete-metametrics-data-toggle')).toBeInTheDocument(); + expect(getAllByText('Delete MetaMetrics data')).toHaveLength(2); + expect( + getByText( + /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, + ), + ).toBeInTheDocument(); + }); + + it('should enable the data deletion button when metrics is opted in and metametrics id is available ', async () => { + const store = configureStore({}); + const { getByRole, getByText } = renderWithProvider( + , + store, + ); + expect( + getByRole('button', { name: 'Delete MetaMetrics data' }), + ).toBeEnabled(); + expect( + getByText( + /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, + ), + ).toBeInTheDocument(); + }); + it('should enable the data deletion button when page mounts after a deletion task is performed and more data is recoded after the deletion', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === hasRecordedMetricsSinceDeletion) { + return true; + } + if (selector === getMetaMetricsDataDeletionStatus) { + return 'INITIALIZED'; + } + if (selector === getMetaMetricsId) { + return 'fake-metrics-id'; + } + return undefined; + }); + const store = configureStore({}); + const { getByRole, getByText } = renderWithProvider( + , + store, + ); + expect( + getByRole('button', { name: 'Delete MetaMetrics data' }), + ).toBeEnabled(); + expect( + getByText( + /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, + ), + ).toBeInTheDocument(); + }); + + // if user does not opt in to participate in metrics or for profile sync, metametricsId will not be created. + it('should disable the data deletion button when there is metametrics id not available', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === getMetaMetricsId) { + return null; + } + return undefined; + }); + const store = configureStore({}); + const { getByRole } = renderWithProvider( + , + store, + ); + expect( + getByRole('button', { name: 'Delete MetaMetrics data' }), + ).toBeDisabled(); + }); + + // metaMetricsDataDeletionMarked is set to true right after the deletion is performed, it will rest to false when the page unmounts. + it('should disable the data deletion button when metaMetricsDataDeletionMarked is true', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === isMetaMetricsDataDeletionMarked) { + return true; + } + if (selector === getMetaMetricsId) { + return 'fake-metrics-id'; + } + if (selector === hasRecordedMetricsSinceDeletion) { + return true; + } + if (selector === getMetaMetricsDataDeletionStatus) { + return 'INITIALIZED'; + } + if (selector === getMetaMetricsDataDeletionDate) { + return 1717779342113; + } + return undefined; + }); + const store = configureStore({}); + const { getByRole, getByText } = renderWithProvider( + , + store, + ); + expect( + getByRole('button', { name: 'Delete MetaMetrics data' }), + ).toBeDisabled(); + expect( + getByText( + /You initiated this action on 7\/06\/2024. This process can take up to 30 days. View the/u, + ), + ).toBeInTheDocument(); + }); + + // particilapteInMetrics will be false before the deletion is performed, this way no further data will be recorded after deletion. + it('should disable the data deletion button after a deletion task is performed and no data is recoded after the deletion', async () => { + useSelectorMock.mockImplementation((selector) => { + if (selector === hasRecordedMetricsSinceDeletion) { + return false; + } + if (selector === getMetaMetricsId) { + return 'fake-metrics-id'; + } + if (selector === hasRecordedMetricsSinceDeletion) { + return true; + } + if (selector === getMetaMetricsDataDeletionStatus) { + return 'INITIALIZED'; + } + if (selector === getMetaMetricsDataDeletionDate) { + return 1717779342113; + } + return undefined; + }); + const store = configureStore({}); + const { getByRole, getByText } = renderWithProvider( + , + store, + ); + expect( + getByRole('button', { name: 'Delete MetaMetrics data' }), + ).toBeDisabled(); + expect( + getByText( + /You initiated this action on 7\/06\/2024. This process can take up to 30 days. View the/u, + ), + ).toBeInTheDocument(); + }); + + it('should open the modal on the button click', () => { + const store = configureStore({}); + const { getByRole } = renderWithProvider( + , + store, + ); + const deleteButton = getByRole('button', { + name: 'Delete MetaMetrics data', + }); + fireEvent.click(deleteButton); + expect(mockDispatch).toHaveBeenCalledWith(openDeleteMetaMetricsDataModal()); + }); +}); diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx index 6aa3dd76e7ad..dcfe32a766a1 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx @@ -17,10 +17,10 @@ import { hasRecordedMetricsSinceDeletion, isMetaMetricsDataDeletionMarked, } from '../../../../selectors'; -import { DeleteRegulationStatus } from '../../../../../app/scripts/controllers/metametrics-data-deletion/metametrics-data-deletion'; import { openDeleteMetaMetricsDataModal } from '../../../../ducks/app/app'; import DataDeletionErrorModal from '../../../../components/app/data-deletion-error-modal'; import { formatDate } from '../../../../helpers/utils/util'; +import { DeleteRegulationStatus } from '../../../../../shared/constants/metametrics'; const DeleteMetaMetricsDataToggle = () => { const t = useI18nContext(); @@ -47,7 +47,7 @@ const DeleteMetaMetricsDataToggle = () => { const showDataDeletionErrorModal = useSelector(getShowDataDeletionErrorModal); let dataDeletionButtonDisabled = - metaMetricsDataDeletionMarked || Boolean(!metaMetricsId) || !hasMetricsRecordedAfterDeletion; + metaMetricsDataDeletionMarked || Boolean(!metaMetricsId); if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { dataDeletionButtonDisabled = [ @@ -72,7 +72,7 @@ const DeleteMetaMetricsDataToggle = () => { <> () => undefined); @@ -36,6 +38,17 @@ jest.mock('../../../store/actions', () => ({ setSecurityAlertsEnabled: (val) => mockSetSecurityAlertsEnabled(val), })); +jest.mock('../../../ducks/app/app.ts', () => { + return { + openDeleteMetaMetricsDataModal: () => { + return mockOpenDeleteMetaMetricsDataModal; + }, + unMarkingMetaMetricsDataDeletion: () => { + return jest.fn(); + }, + }; +}); + describe('Security Tab', () => { mockState.appState.warning = 'warning'; // This tests an otherwise untested render branch @@ -214,7 +227,23 @@ describe('Security Tab', () => { await user.click(screen.getByText(tEn('addCustomNetwork'))); expect(global.platform.openExtensionInBrowser).toHaveBeenCalled(); }); + it('clicks "Delete MetaMetrics Data"', async () => { + mockState.metamask.participateInMetaMetrics = true; + mockState.metamask.metaMetricsId = 'fake-metametrics-id'; + const localMockStore = configureMockStore([thunk])(mockState); + renderWithProvider(, localMockStore); + + expect( + screen.queryByTestId(`delete-metametrics-data-toggle`), + ).toBeInTheDocument(); + + fireEvent.click( + screen.getByRole('button', { name: 'Delete MetaMetrics data' }), + ); + + expect(mockOpenDeleteMetaMetricsDataModal).toHaveBeenCalled(); + }); describe('Blockaid', () => { afterEach(() => { jest.clearAllMocks(); From 21aca780fb623eb7f09d5ebe4fe8038cd428b1cb Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:07:33 -0400 Subject: [PATCH 08/40] updating the design change for when metametrics id is not available --- app/_locales/en/messages.json | 3 +++ .../delete-metametrics-data-toggle.test.tsx | 12 ++++++++- .../delete-metametrics-data-toggle.tsx | 27 ++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 5e88610c8e44..2174a9054eda 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -2896,6 +2896,9 @@ "metaMaskConnectStatusParagraphTwo": { "message": "The connection status button shows if the website you’re visiting is connected to your currently selected account." }, + "metaMetricsIdNotAvailableError": { + "message": "Since you've never opted into MetaMetrics, there's no data to delete here." + }, "metadataModalSourceTooltip": { "message": "$1 is hosted on npm and $2 is this Snap’s unique identifier.", "description": "$1 is the snap name and $2 is the snap NPM id." diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx index b87f6d785006..9d36f3df4f82 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.test.tsx @@ -120,13 +120,23 @@ describe('DeleteMetaMetricsDataToggle', () => { return undefined; }); const store = configureStore({}); - const { getByRole } = renderWithProvider( + const { getByRole, getByText } = renderWithProvider( , store, ); expect( getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeDisabled(); + expect( + getByText( + /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, + ), + ).toBeInTheDocument(); + expect( + getByText( + /Since you've never opted into MetaMetrics, there's no data to delete here./u, + ), + ).toBeInTheDocument(); }); // metaMetricsDataDeletionMarked is set to true right after the deletion is performed, it will rest to false when the page unmounts. diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx index dcfe32a766a1..253bfa686a5b 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-toggle/delete-metametrics-data-toggle.tsx @@ -2,10 +2,18 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { CONSENSYS_PRIVACY_LINK } from '../../../../../shared/lib/ui-utils'; import ClearMetametricsData from '../../../../components/app/clear-metametrics-data'; -import { Box, ButtonPrimary } from '../../../../components/component-library'; +import { + Box, + ButtonPrimary, + Icon, + IconName, + IconSize, + Text, +} from '../../../../components/component-library'; import { Display, FlexDirection, + TextVariant, } from '../../../../helpers/constants/design-system'; import { useI18nContext } from '../../../../hooks/useI18nContext'; import { @@ -46,7 +54,7 @@ const DeleteMetaMetricsDataToggle = () => { ); const showDataDeletionErrorModal = useSelector(getShowDataDeletionErrorModal); - let dataDeletionButtonDisabled = + let dataDeletionButtonDisabled: boolean = metaMetricsDataDeletionMarked || Boolean(!metaMetricsId); if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { dataDeletionButtonDisabled = @@ -57,7 +65,6 @@ const DeleteMetaMetricsDataToggle = () => { ].includes(metaMetricsDataDeletionStatus) && !hasMetricsRecordedAfterDeletion; } - const privacyPolicyLink = ( {
{t('deleteMetaMetricsData')}
- {dataDeletionButtonDisabled + {dataDeletionButtonDisabled && Boolean(metaMetricsId) ? t('deleteMetaMetricsDataRequestedDescription', [ formatedDate, privacyPolicyLink, @@ -89,6 +96,18 @@ const DeleteMetaMetricsDataToggle = () => {
+ {Boolean(!metaMetricsId) && ( + + + + {t('metaMetricsIdNotAvailableError')} + + + )} { From d724452636f6fa73a43764e13e2b79336c4ac17c Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:34:15 -0400 Subject: [PATCH 09/40] fixing rebase issues --- .../__snapshots__/security-tab.test.js.snap | 354 ++++++++++++++++-- ui/selectors/selectors.js | 4 - 2 files changed, 320 insertions(+), 38 deletions(-) diff --git a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap index 2a06990b3d8f..86dcaa0b1429 100644 --- a/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap +++ b/ui/pages/settings/security-tab/__snapshots__/security-tab.test.js.snap @@ -44,7 +44,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" >
+
+
+
+ Linea Mainnet logo +
+
+

+ Linea Mainnet +

+

+ + Lineascan.build + +

+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ + Off + + + On + +
+ +
+
+
+
+
+
+
+
+ +
+
+ + Off + + + On + +
+ +
+
+
+
+
+ S +
+
+

+ Sepolia +

+

+ + Etherscan.io + +

+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ + Off + + + On + +
+ +
+
+
+ +
+
+
Data collection for marketing - Delete MetaMetrics data
We'll use MetaMetrics to learn how you interact with our marketing communications. We may share relevant news (like product features and other materials). - - You initiated this action on - - . This process can take up to 30 days. View the - - Privacy policy - - -
@@ -1538,7 +1779,7 @@ exports[`Security Tab should match snapshot 1`] = ` style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;" >
+
+
+
+
+ + Delete MetaMetrics data + +
+ + + This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our + + Privacy policy + + . + + +
+
+
+
+ +

+ Since you've never opted into MetaMetrics, there's no data to delete here. +

+
); From 8e3172df87c935cdfa173320daa839eed463e3c8 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Fri, 13 Sep 2024 10:08:16 -0400 Subject: [PATCH 31/40] updaing the DeleteRegulationStatus enum --- .../delete-metametrics-data-button.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx index 68285775ebff..5b02a3362b3d 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx @@ -60,9 +60,9 @@ const DeleteMetaMetricsDataButton = ({ if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { dataDeletionButtonDisabled = [ - DeleteRegulationStatus.initialized, - DeleteRegulationStatus.running, - DeleteRegulationStatus.finished, + DeleteRegulationStatus.Initialized, + DeleteRegulationStatus.Running, + DeleteRegulationStatus.Finished, ].includes(metaMetricsDataDeletionStatus) && metaMetricsDataDeletionTimestamp > latestMetricsEventTimestamp; } From 3b50e53d7636834df502cdc14e32b5344b8e5a2a Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:13:42 -0400 Subject: [PATCH 32/40] addressing review comments - updating unit tests --- .../metrics/delete-metametrics-data.spec.ts | 22 +++++----- test/e2e/webdriver/types.ts | 5 +++ .../clear-metametrics-data.test.tsx | 42 ++++++++++++++++++- .../clear-metametrics-data.tsx | 1 + .../data-deletion-error-modal.test.tsx | 30 +++++++++++++ .../delete-metametrics-data-button.tsx | 3 +- 6 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 test/e2e/webdriver/types.ts diff --git a/test/e2e/tests/metrics/delete-metametrics-data.spec.ts b/test/e2e/tests/metrics/delete-metametrics-data.spec.ts index b2ae5b331cb3..76e08798c6ea 100644 --- a/test/e2e/tests/metrics/delete-metametrics-data.spec.ts +++ b/test/e2e/tests/metrics/delete-metametrics-data.spec.ts @@ -10,6 +10,7 @@ import { import FixtureBuilder from '../../fixture-builder'; import { Driver } from '../../webdriver/driver'; import { TestSuiteArguments } from '../confirmations/transactions/shared'; +import { WebElementWithWaitForElementState } from '../../webdriver/types'; const selectors = { accountOptionsMenuButton: '[data-testid="account-options-menu-button"]', @@ -121,10 +122,9 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { const deleteMetaMetricsDataButton = await driver.findElement( selectors.deleteMetaMetricsDataButton, ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await (deleteMetaMetricsDataButton as any).waitForElementState( - 'disabled', - ); + await ( + deleteMetaMetricsDataButton as WebElementWithWaitForElementState + ).waitForElementState('disabled'); assert.equal( await deleteMetaMetricsDataButton.isEnabled(), false, @@ -195,10 +195,9 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { const deleteMetaMetricsDataButton = await driver.findElement( selectors.deleteMetaMetricsDataButton, ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await (deleteMetaMetricsDataButton as any).waitForElementState( - 'disabled', - ); + await ( + deleteMetaMetricsDataButton as WebElementWithWaitForElementState + ).waitForElementState('disabled'); assert.equal( await deleteMetaMetricsDataButton.isEnabled(), false, @@ -221,10 +220,9 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { const deleteMetaMetricsDataButtonRefreshed = await driver.findElement( selectors.deleteMetaMetricsDataButton, ); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await (deleteMetaMetricsDataButtonRefreshed as any).waitForElementState( - 'disabled', - ); + await ( + deleteMetaMetricsDataButtonRefreshed as WebElementWithWaitForElementState + ).waitForElementState('disabled'); assert.equal( await deleteMetaMetricsDataButtonRefreshed.isEnabled(), false, diff --git a/test/e2e/webdriver/types.ts b/test/e2e/webdriver/types.ts new file mode 100644 index 000000000000..68cfa15dd600 --- /dev/null +++ b/test/e2e/webdriver/types.ts @@ -0,0 +1,5 @@ +import { WebElement, WebElementPromise } from 'selenium-webdriver'; + +export type WebElementWithWaitForElementState = WebElement & { + waitForElementState: (state: unknown, timeout?: unknown) => WebElementPromise; +}; diff --git a/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx b/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx index 970e094ff035..5ce4ac7573dc 100644 --- a/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx +++ b/ui/components/app/clear-metametrics-data/clear-metametrics-data.test.tsx @@ -1,10 +1,34 @@ import * as React from 'react'; +import { fireEvent } from '@testing-library/react'; import configureStore from '../../../store/store'; import { renderWithProvider } from '../../../../test/lib/render-helpers'; - +import * as Actions from '../../../store/actions'; +import { DELETE_METAMETRICS_DATA_MODAL_CLOSE } from '../../../store/actionConstants'; import ClearMetaMetricsData from './clear-metametrics-data'; +const mockCloseDeleteMetaMetricsDataModal = jest.fn().mockImplementation(() => { + return { + type: DELETE_METAMETRICS_DATA_MODAL_CLOSE, + }; +}); + +jest.mock('../../../store/actions', () => ({ + createMetaMetricsDataDeletionTask: jest.fn(), +})); + +jest.mock('../../../ducks/app/app.ts', () => { + return { + hideDeleteMetaMetricsDataModal: () => { + return mockCloseDeleteMetaMetricsDataModal(); + }, + }; +}); + describe('ClearMetaMetricsData', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + it('should render the data deletion error modal', async () => { const store = configureStore({}); const { getByText } = renderWithProvider(, store); @@ -16,4 +40,20 @@ describe('ClearMetaMetricsData', () => { ), ).toBeInTheDocument(); }); + + it('should call createMetaMetricsDataDeletionTask when Clear button is clicked', () => { + const store = configureStore({}); + const { getByText } = renderWithProvider(, store); + expect(getByText('Clear')).toBeEnabled(); + fireEvent.click(getByText('Clear')); + expect(Actions.createMetaMetricsDataDeletionTask).toHaveBeenCalledTimes(1); + }); + + it('should call hideDeleteMetaMetricsDataModal when Cancel button is clicked', () => { + const store = configureStore({}); + const { getByText } = renderWithProvider(, store); + expect(getByText('Cancel')).toBeEnabled(); + fireEvent.click(getByText('Cancel')); + expect(mockCloseDeleteMetaMetricsDataModal).toHaveBeenCalledTimes(1); + }); }); diff --git a/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx b/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx index 222497facf30..216dacc0fff3 100644 --- a/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx +++ b/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx @@ -104,6 +104,7 @@ export default function ClearMetaMetricsData() { {t('cancel')}
@@ -130,8 +130,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - This feature alerts you to malicious activity by actively reviewing transaction and signature requests. + + This feature alerts you to malicious activity by actively reviewing transaction and signature requests. Learn more - - + +
@@ -223,8 +223,8 @@ exports[`Security Tab should match snapshot 1`] = ` data-testid="profileSyncDescription" > - - Creates a profile that MetaMask uses to sync some settings among your devices. This is required to get notifications. + + Creates a profile that MetaMask uses to sync some settings among your devices. This is required to get notifications. . - +
@@ -466,8 +466,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - We use + + We use CoinGecko - and + and CryptoCompare - APIs to display your balance and token price. + APIs to display your balance and token price. Privacy policy - - + +
@@ -647,93 +647,6 @@ exports[`Security Tab should match snapshot 1`] = `
-
-
-
- Linea Mainnet logo -
-
-

- Linea Mainnet -

-

- - Lineascan.build - -

-
-
-
-
- +
@@ -1403,8 +1146,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want the app to automatically pull data from those services. + + We use third-party APIs to detect and display new tokens sent to your wallet. Turn off if you don’t want the app to automatically pull data from those services. Learn More - - + +
@@ -1832,8 +1575,8 @@ exports[`Security Tab should match snapshot 1`] = ` class="settings-page__content-description" > - - This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our + + This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our . - +
From f87ab44a7cca40baa25ef0372971ce5c74fe63c4 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:20:46 -0400 Subject: [PATCH 34/40] adding error occured event --- shared/constants/metametrics.ts | 1 + .../clear-metametrics-data/clear-metametrics-data.tsx | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index c1b464039eac..d0f1cfb87cbe 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -536,6 +536,7 @@ export enum MetaMetricsEventName { EncryptionPublicKeyApproved = 'Encryption Approved', EncryptionPublicKeyRejected = 'Encryption Rejected', EncryptionPublicKeyRequested = 'Encryption Requested', + ErrorOccured = 'Error occured', ExternalLinkClicked = 'External Link Clicked', KeyExportSelected = 'Key Export Selected', KeyExportRequested = 'Key Export Requested', diff --git a/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx b/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx index 216dacc0fff3..019c115eceac 100644 --- a/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx +++ b/ui/components/app/clear-metametrics-data/clear-metametrics-data.tsx @@ -55,6 +55,15 @@ export default function ClearMetaMetricsData() { ); } catch (error: unknown) { dispatch(openDataDeletionErrorModal()); + trackEvent( + { + category: MetaMetricsEventCategory.Settings, + event: MetaMetricsEventName.ErrorOccured, + }, + { + excludeMetaMetricsId: true, + }, + ); } finally { dispatch(hideDeleteMetaMetricsDataModal()); } From 26d520c9c1c69f9ba34453afd14b5f4596d12456 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:33:51 -0400 Subject: [PATCH 35/40] resolving conflict --- privacy-snapshot.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/privacy-snapshot.json b/privacy-snapshot.json index 2516654f1803..3d93f5dd9df3 100644 --- a/privacy-snapshot.json +++ b/privacy-snapshot.json @@ -7,7 +7,6 @@ "api.web3modal.com", "app.ens.domains", "arbitrum-mainnet.infura.io", - "authentication.api.cx.metamask.io", "bafkreifvhjdf6ve4jfv6qytqtux5nd4nwnelioeiqx5x2ez5yrgrzk7ypi.ipfs.dweb.link", "bafybeidxfmwycgzcp4v2togflpqh2gnibuexjy4m4qqwxp7nh3jx5zlh4y.ipfs.dweb.link", "bridge.api.cx.metamask.io", @@ -15,7 +14,6 @@ "cdn.segment.io", "cdnjs.cloudflare.com", "chainid.network", - "client-side-detection.api.cx.metamask.io", "configuration.dev.metamask-institutional.io", "configuration.metamask-institutional.io", "connect.trezor.io", @@ -27,7 +25,6 @@ "gas.api.cx.metamask.io", "github.com", "goerli.infura.io", - "lattice.gridplus.io", "localhost:8000", "localhost:8545", "mainnet.infura.io", @@ -36,14 +33,13 @@ "metametrics.metamask.test", "min-api.cryptocompare.com", "nft.api.cx.metamask.io", - "oidc.api.cx.metamask.io", - "on-ramp-content.api.cx.metamask.io", - "on-ramp-content.uat-api.cx.metamask.io", "phishing-detection.api.cx.metamask.io", "portfolio.metamask.io", "price.api.cx.metamask.io", "proxy.api.cx.metamask.io", "proxy.dev-api.cx.metamask.io", + "on-ramp-content.api.cx.metamask.io", + "on-ramp-content.uat-api.cx.metamask.io", "raw.githubusercontent.com", "registry.npmjs.org", "responsive-rpc.test", @@ -57,6 +53,9 @@ "token.api.cx.metamask.io", "tokens.api.cx.metamask.io", "tx-sentinel-ethereum-mainnet.api.cx.metamask.io", + "unresponsive-rpc.url", + "www.4byte.directory", + "lattice.gridplus.io", "unresponsive-rpc.test", "unresponsive-rpc.url", "user-storage.api.cx.metamask.io", From 472709cab78d2d2040823a7769916fa8ca590fae Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Tue, 1 Oct 2024 15:03:52 -0400 Subject: [PATCH 36/40] adding forwardRef for settings search --- .../delete-metametrics-data-button.tsx | 198 ++++++++++-------- .../security-tab/security-tab.component.js | 2 +- 2 files changed, 109 insertions(+), 91 deletions(-) diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx index 969594cc323e..727d05baf70e 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx @@ -8,6 +8,7 @@ import { Icon, IconName, IconSize, + PolymorphicComponentPropWithRef, PolymorphicRef, Text, } from '../../../../components/component-library'; @@ -30,100 +31,117 @@ import DataDeletionErrorModal from '../../../../components/app/data-deletion-err import { formatDate } from '../../../../helpers/utils/util'; import { DeleteRegulationStatus } from '../../../../../shared/constants/metametrics'; -const DeleteMetaMetricsDataButton = ({ - wrapperRef, -}: { - wrapperRef?: PolymorphicRef; -}) => { - const t = useI18nContext(); - const dispatch = useDispatch(); +type DeleteMetaMetricsDataButtonProps = + PolymorphicComponentPropWithRef; - const metaMetricsId = useSelector(getMetaMetricsId); - const metaMetricsDataDeletionStatus: DeleteRegulationStatus = useSelector( - getMetaMetricsDataDeletionStatus, - ); - const metaMetricsDataDeletionTimestamp = useSelector( - getMetaMetricsDataDeletionTimestamp, - ); - const formatedDate = formatDate(metaMetricsDataDeletionTimestamp, 'd/MM/y'); +type DeleteMetaMetricsDataButtonComponent = < + C extends React.ElementType = 'div', +>( + props: DeleteMetaMetricsDataButtonProps, +) => React.ReactElement | null; - const showDeleteMetaMetricsDataModal = useSelector( - getShowDeleteMetaMetricsDataModal, - ); - const showDataDeletionErrorModal = useSelector(getShowDataDeletionErrorModal); - const latestMetricsEventTimestamp = useSelector( - getLatestMetricsEventTimestamp, - ); +const DeleteMetaMetricsDataButton: DeleteMetaMetricsDataButtonComponent = + React.forwardRef( + ( + // eslint-disable-next-line no-empty-pattern + {}: DeleteMetaMetricsDataButtonProps, + ref: PolymorphicRef, + ) => { + const t = useI18nContext(); + const dispatch = useDispatch(); - let dataDeletionButtonDisabled = Boolean(!metaMetricsId); - if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { - dataDeletionButtonDisabled = - [ - DeleteRegulationStatus.Initialized, - DeleteRegulationStatus.Running, - DeleteRegulationStatus.Finished, - ].includes(metaMetricsDataDeletionStatus) && - metaMetricsDataDeletionTimestamp > latestMetricsEventTimestamp; - } - const privacyPolicyLink = ( - - {t('privacyMsg')} - - ); - return ( - <> - -
- {t('deleteMetaMetricsData')} -
- {dataDeletionButtonDisabled && Boolean(metaMetricsId) - ? t('deleteMetaMetricsDataRequestedDescription', [ - formatedDate, - privacyPolicyLink, - ]) - : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])} -
-
-
- {Boolean(!metaMetricsId) && ( - - - - {t('metaMetricsIdNotAvailableError')} - - - )} - { - dispatch(openDeleteMetaMetricsDataModal()); - }} - disabled={dataDeletionButtonDisabled} + const metaMetricsId = useSelector(getMetaMetricsId); + const metaMetricsDataDeletionStatus: DeleteRegulationStatus = useSelector( + getMetaMetricsDataDeletionStatus, + ); + const metaMetricsDataDeletionTimestamp = useSelector( + getMetaMetricsDataDeletionTimestamp, + ); + const formatedDate = formatDate( + metaMetricsDataDeletionTimestamp, + 'd/MM/y', + ); + + const showDeleteMetaMetricsDataModal = useSelector( + getShowDeleteMetaMetricsDataModal, + ); + const showDataDeletionErrorModal = useSelector( + getShowDataDeletionErrorModal, + ); + const latestMetricsEventTimestamp = useSelector( + getLatestMetricsEventTimestamp, + ); + + let dataDeletionButtonDisabled = Boolean(!metaMetricsId); + if (!dataDeletionButtonDisabled && metaMetricsDataDeletionStatus) { + dataDeletionButtonDisabled = + [ + DeleteRegulationStatus.Initialized, + DeleteRegulationStatus.Running, + DeleteRegulationStatus.Finished, + ].includes(metaMetricsDataDeletionStatus) && + metaMetricsDataDeletionTimestamp > latestMetricsEventTimestamp; + } + const privacyPolicyLink = ( + + {t('privacyMsg')} + + ); + return ( + <> + - {t('deleteMetaMetricsData')} - -
-
- {showDeleteMetaMetricsDataModal && } - {showDataDeletionErrorModal && } - +
+ {t('deleteMetaMetricsData')} +
+ {dataDeletionButtonDisabled && Boolean(metaMetricsId) + ? t('deleteMetaMetricsDataRequestedDescription', [ + formatedDate, + privacyPolicyLink, + ]) + : t('deleteMetaMetricsDataDescription', [privacyPolicyLink])} +
+
+
+ {Boolean(!metaMetricsId) && ( + + + + {t('metaMetricsIdNotAvailableError')} + + + )} + { + dispatch(openDeleteMetaMetricsDataModal()); + }} + disabled={dataDeletionButtonDisabled} + > + {t('deleteMetaMetricsData')} + +
+ + {showDeleteMetaMetricsDataModal && } + {showDataDeletionErrorModal && } + + ); + }, ); -}; export default DeleteMetaMetricsDataButton; diff --git a/ui/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js index b4cc7755ce4a..1fae729d3f31 100644 --- a/ui/pages/settings/security-tab/security-tab.component.js +++ b/ui/pages/settings/security-tab/security-tab.component.js @@ -1228,7 +1228,7 @@ export default class SecurityTab extends PureComponent { setDataCollectionForMarketing={setDataCollectionForMarketing} /> {this.renderDataCollectionForMarketing()} - +
); From 9913bcefaf086192d79497fefa44b44975e579d0 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:10:10 -0400 Subject: [PATCH 37/40] adding unit tests to satisfy sonar cloud --- ui/ducks/app/app.test.js | 38 ++++++++++++++++++++ ui/selectors/metametrics.test.js | 12 +++++++ ui/selectors/selectors.test.js | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/ui/ducks/app/app.test.js b/ui/ducks/app/app.test.js index 0d6441454f90..9a7a93ea958b 100644 --- a/ui/ducks/app/app.test.js +++ b/ui/ducks/app/app.test.js @@ -301,4 +301,42 @@ describe('App State', () => { }); expect(state.smartTransactionsError).toStrictEqual('Server Side Error'); }); + it('shows delete metametrics modal', () => { + const state = reduceApp(metamaskState, { + type: actions.DELETE_METAMETRICS_DATA_MODAL_OPEN, + }); + + expect(state.showDeleteMetaMetricsDataModal).toStrictEqual(true); + }); + it('hides delete metametrics modal', () => { + const deleteMetaMetricsDataModalState = { + showDeleteMetaMetricsDataModal: true, + }; + const oldState = { ...metamaskState, ...deleteMetaMetricsDataModalState }; + + const state = reduceApp(oldState, { + type: actions.DELETE_METAMETRICS_DATA_MODAL_CLOSE, + }); + + expect(state.showDeleteMetaMetricsDataModal).toStrictEqual(false); + }); + it('shows delete metametrics error modal', () => { + const state = reduceApp(metamaskState, { + type: actions.DATA_DELETION_ERROR_MODAL_OPEN, + }); + + expect(state.showDataDeletionErrorModal).toStrictEqual(true); + }); + it('hides delete metametrics error modal', () => { + const deleteMetaMetricsErrorModalState = { + showDataDeletionErrorModal: true, + }; + const oldState = { ...metamaskState, ...deleteMetaMetricsErrorModalState }; + + const state = reduceApp(oldState, { + type: actions.DATA_DELETION_ERROR_MODAL_CLOSE, + }); + + expect(state.showDataDeletionErrorModal).toStrictEqual(false); + }); }); diff --git a/ui/selectors/metametrics.test.js b/ui/selectors/metametrics.test.js index 13185a47700b..454def7d92a4 100644 --- a/ui/selectors/metametrics.test.js +++ b/ui/selectors/metametrics.test.js @@ -2,6 +2,7 @@ const { selectFragmentBySuccessEvent, selectFragmentById, selectMatchingFragment, + getLatestMetricsEventTimestamp, } = require('.'); describe('selectFragmentBySuccessEvent', () => { @@ -68,4 +69,15 @@ describe('selectMatchingFragment', () => { }); expect(selected).toHaveProperty('id', 'randomid'); }); + describe('getLatestMetricsEventTimestamp', () => { + it('should find matching fragment in state by id', () => { + const state = { + metamask: { + latestNonAnonymousEventTimestamp: 12345, + }, + }; + const timestamp = getLatestMetricsEventTimestamp(state); + expect(timestamp).toBe(12345); + }); + }); }); diff --git a/ui/selectors/selectors.test.js b/ui/selectors/selectors.test.js index 342e7d7187c8..24b2a2afe125 100644 --- a/ui/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -11,6 +11,7 @@ import { createMockInternalAccount } from '../../test/jest/mocks'; import { ETH_EOA_METHODS } from '../../shared/constants/eth-methods'; import { getProviderConfig } from '../ducks/metamask/metamask'; import { mockNetworkState } from '../../test/stub/networks'; +import { DeleteRegulationStatus } from '../../shared/constants/metametrics'; import * as selectors from './selectors'; jest.mock('../../app/scripts/lib/util', () => ({ @@ -2018,4 +2019,65 @@ describe('#getConnectedSitesList', () => { }, }); }); + describe('#getShowDeleteMetaMetricsDataModal', () => { + it('returns state of showDeleteMetaMetricsDataModal', () => { + expect( + selectors.getShowDeleteMetaMetricsDataModal({ + appState: { + showDeleteMetaMetricsDataModal: true, + }, + }), + ).toStrictEqual(true); + }); + }); + describe('#getShowDataDeletionErrorModal', () => { + it('returns state of showDataDeletionErrorModal', () => { + expect( + selectors.getShowDataDeletionErrorModal({ + appState: { + showDataDeletionErrorModal: true, + }, + }), + ).toStrictEqual(true); + }); + }); + describe('#getMetaMetricsDataDeletionId', () => { + it('returns metaMetricsDataDeletionId', () => { + expect( + selectors.getMetaMetricsDataDeletionId({ + metamask: { + metaMetricsDataDeletionId: '123', + metaMetricsDataDeletionTimestamp: '123345', + metaMetricsDataDeletionStatus: DeleteRegulationStatus.Initialized, + }, + }), + ).toStrictEqual('123'); + }); + }); + describe('#getMetaMetricsDataDeletionTimestamp', () => { + it('returns metaMetricsDataDeletionTimestamp', () => { + expect( + selectors.getMetaMetricsDataDeletionTimestamp({ + metamask: { + metaMetricsDataDeletionId: '123', + metaMetricsDataDeletionTimestamp: '123345', + metaMetricsDataDeletionStatus: DeleteRegulationStatus.Initialized, + }, + }), + ).toStrictEqual('123345'); + }); + }); + describe('#getMetaMetricsDataDeletionStatus', () => { + it('returns metaMetricsDataDeletionStatus', () => { + expect( + selectors.getMetaMetricsDataDeletionStatus({ + metamask: { + metaMetricsDataDeletionId: '123', + metaMetricsDataDeletionTimestamp: '123345', + metaMetricsDataDeletionStatus: DeleteRegulationStatus.Initialized, + }, + }), + ).toStrictEqual('INITIALIZED'); + }); + }); }); From 57d85446afc653980921878b25e3bf79f18a02b4 Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:16:27 -0400 Subject: [PATCH 38/40] fixing sonar cloud failure --- .../delete-metametrics-data-button.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx index 727d05baf70e..34b61697ed95 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.tsx @@ -43,8 +43,8 @@ type DeleteMetaMetricsDataButtonComponent = < const DeleteMetaMetricsDataButton: DeleteMetaMetricsDataButtonComponent = React.forwardRef( ( - // eslint-disable-next-line no-empty-pattern - {}: DeleteMetaMetricsDataButtonProps, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + { ...props }: DeleteMetaMetricsDataButtonProps, ref: PolymorphicRef, ) => { const t = useI18nContext(); From 2e15e0ed910faa1130c19856bff4396ca0cfe57a Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:16:18 -0400 Subject: [PATCH 39/40] addressing comments --- privacy-snapshot.json | 11 ++++++----- .../tests/metrics/delete-metametrics-data.spec.ts | 15 --------------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/privacy-snapshot.json b/privacy-snapshot.json index 3d93f5dd9df3..2516654f1803 100644 --- a/privacy-snapshot.json +++ b/privacy-snapshot.json @@ -7,6 +7,7 @@ "api.web3modal.com", "app.ens.domains", "arbitrum-mainnet.infura.io", + "authentication.api.cx.metamask.io", "bafkreifvhjdf6ve4jfv6qytqtux5nd4nwnelioeiqx5x2ez5yrgrzk7ypi.ipfs.dweb.link", "bafybeidxfmwycgzcp4v2togflpqh2gnibuexjy4m4qqwxp7nh3jx5zlh4y.ipfs.dweb.link", "bridge.api.cx.metamask.io", @@ -14,6 +15,7 @@ "cdn.segment.io", "cdnjs.cloudflare.com", "chainid.network", + "client-side-detection.api.cx.metamask.io", "configuration.dev.metamask-institutional.io", "configuration.metamask-institutional.io", "connect.trezor.io", @@ -25,6 +27,7 @@ "gas.api.cx.metamask.io", "github.com", "goerli.infura.io", + "lattice.gridplus.io", "localhost:8000", "localhost:8545", "mainnet.infura.io", @@ -33,13 +36,14 @@ "metametrics.metamask.test", "min-api.cryptocompare.com", "nft.api.cx.metamask.io", + "oidc.api.cx.metamask.io", + "on-ramp-content.api.cx.metamask.io", + "on-ramp-content.uat-api.cx.metamask.io", "phishing-detection.api.cx.metamask.io", "portfolio.metamask.io", "price.api.cx.metamask.io", "proxy.api.cx.metamask.io", "proxy.dev-api.cx.metamask.io", - "on-ramp-content.api.cx.metamask.io", - "on-ramp-content.uat-api.cx.metamask.io", "raw.githubusercontent.com", "registry.npmjs.org", "responsive-rpc.test", @@ -53,9 +57,6 @@ "token.api.cx.metamask.io", "tokens.api.cx.metamask.io", "tx-sentinel-ethereum-mainnet.api.cx.metamask.io", - "unresponsive-rpc.url", - "www.4byte.directory", - "lattice.gridplus.io", "unresponsive-rpc.test", "unresponsive-rpc.url", "user-storage.api.cx.metamask.io", diff --git a/test/e2e/tests/metrics/delete-metametrics-data.spec.ts b/test/e2e/tests/metrics/delete-metametrics-data.spec.ts index 76e08798c6ea..308ff8508d0a 100644 --- a/test/e2e/tests/metrics/delete-metametrics-data.spec.ts +++ b/test/e2e/tests/metrics/delete-metametrics-data.spec.ts @@ -125,11 +125,6 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { await ( deleteMetaMetricsDataButton as WebElementWithWaitForElementState ).waitForElementState('disabled'); - assert.equal( - await deleteMetaMetricsDataButton.isEnabled(), - false, - 'Delete MetaMetrics data button is disabled', - ); const events = await getEventPayloads( driver, @@ -198,11 +193,6 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { await ( deleteMetaMetricsDataButton as WebElementWithWaitForElementState ).waitForElementState('disabled'); - assert.equal( - await deleteMetaMetricsDataButton.isEnabled(), - false, - 'Delete MetaMetrics data button is disabled', - ); const events = await getEventPayloads( driver, @@ -223,11 +213,6 @@ describe('Delete MetaMetrics Data @no-mmi', function (this: Suite) { await ( deleteMetaMetricsDataButtonRefreshed as WebElementWithWaitForElementState ).waitForElementState('disabled'); - assert.equal( - await deleteMetaMetricsDataButtonRefreshed.isEnabled(), - false, - 'Delete MetaMetrics data button is disabled', - ); }, ); }); From 8013ee7dae19299398453d9f0c668be8d37522ae Mon Sep 17 00:00:00 2001 From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:39:29 -0400 Subject: [PATCH 40/40] updating unit test --- .../delete-metametrics-data-button.test.tsx | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.test.tsx b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.test.tsx index d9eeb6cbf5cd..27132fb82f5c 100644 --- a/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.test.tsx +++ b/ui/pages/settings/security-tab/delete-metametrics-data-button/delete-metametrics-data-button.test.tsx @@ -47,22 +47,22 @@ describe('DeleteMetaMetricsDataButton', () => { it('renders correctly', () => { const store = configureStore({}); - const { getByText, getByTestId, getAllByText } = renderWithProvider( + const { getByTestId, getAllByText, container } = renderWithProvider( , store, ); expect(getByTestId('delete-metametrics-data-button')).toBeInTheDocument(); expect(getAllByText('Delete MetaMetrics data')).toHaveLength(2); expect( - getByText( - /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our Privacy policy. "`, + ); }); - it('should enable the data deletion button when metrics is opted in and metametrics id is available ', async () => { const store = configureStore({}); - const { getByRole, getByText } = renderWithProvider( + const { getByRole, container } = renderWithProvider( , store, ); @@ -70,10 +70,11 @@ describe('DeleteMetaMetricsDataButton', () => { getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeEnabled(); expect( - getByText( - /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our Privacy policy. "`, + ); }); it('should enable the data deletion button when page mounts after a deletion task is performed and more data is recoded after the deletion', async () => { useSelectorMock.mockImplementation((selector) => { @@ -86,7 +87,7 @@ describe('DeleteMetaMetricsDataButton', () => { return undefined; }); const store = configureStore({}); - const { getByRole, getByText } = renderWithProvider( + const { getByRole, container } = renderWithProvider( , store, ); @@ -94,10 +95,11 @@ describe('DeleteMetaMetricsDataButton', () => { getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeEnabled(); expect( - getByText( - /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our Privacy policy. "`, + ); }); // if user does not opt in to participate in metrics or for profile sync, metametricsId will not be created. @@ -109,7 +111,7 @@ describe('DeleteMetaMetricsDataButton', () => { return undefined; }); const store = configureStore({}); - const { getByRole, getByText } = renderWithProvider( + const { getByRole, container } = renderWithProvider( , store, ); @@ -117,15 +119,16 @@ describe('DeleteMetaMetricsDataButton', () => { getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeDisabled(); expect( - getByText( - /This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" This will delete historical MetaMetrics data associated with your use on this device. Your wallet and accounts will remain exactly as they are now after this data has been deleted. This process may take up to 30 days. View our Privacy policy. "`, + ); expect( - getByText( - /Since you've never opted into MetaMetrics, there's no data to delete here./u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-item-col')?.textContent, + ).toMatchInlineSnapshot( + `"Since you've never opted into MetaMetrics, there's no data to delete here.Delete MetaMetrics data"`, + ); }); // particilapteInMetrics will be false before the deletion is performed, this way no further data will be recorded after deletion. @@ -146,7 +149,7 @@ describe('DeleteMetaMetricsDataButton', () => { return undefined; }); const store = configureStore({}); - const { getByRole, getByText } = renderWithProvider( + const { getByRole, container } = renderWithProvider( , store, ); @@ -154,10 +157,11 @@ describe('DeleteMetaMetricsDataButton', () => { getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeDisabled(); expect( - getByText( - /You initiated this action on 7\/06\/2024. This process can take up to 30 days. View the/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" You initiated this action on 7/06/2024. This process can take up to 30 days. View the Privacy policy "`, + ); }); // particilapteInMetrics will be false before the deletion is performed, this way no further data will be recorded after deletion. @@ -178,7 +182,7 @@ describe('DeleteMetaMetricsDataButton', () => { return undefined; }); const store = configureStore({}); - const { getByRole, getByText } = renderWithProvider( + const { getByRole, container } = renderWithProvider( , store, ); @@ -186,10 +190,11 @@ describe('DeleteMetaMetricsDataButton', () => { getByRole('button', { name: 'Delete MetaMetrics data' }), ).toBeDisabled(); expect( - getByText( - /You initiated this action on 7\/06\/2024. This process can take up to 30 days. View the/u, - ), - ).toBeInTheDocument(); + container.querySelector('.settings-page__content-description') + ?.textContent, + ).toMatchInlineSnapshot( + `" You initiated this action on 7/06/2024. This process can take up to 30 days. View the Privacy policy "`, + ); }); it('should open the modal on the button click', () => {