Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(app): add privacy policy acknowledgement screen on ODD #14435

Merged
merged 9 commits into from
Feb 7, 2024
7 changes: 7 additions & 0 deletions app/src/App/OnDeviceDisplayApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ConnectViaWifi } from '../pages/ConnectViaWifi'
import { EmergencyStop } from '../pages/EmergencyStop'
import { NameRobot } from '../pages/NameRobot'
import { NetworkSetupMenu } from '../pages/NetworkSetupMenu'
import { PrivacyPolicy } from '../pages/PrivacyPolicy'
import { ProtocolSetup } from '../pages/ProtocolSetup'
import { RobotDashboard } from '../pages/RobotDashboard'
import { RobotSettingsDashboard } from '../pages/RobotSettingsDashboard'
Expand Down Expand Up @@ -195,6 +196,12 @@ export const onDeviceDisplayRoutes: RouteProps[] = [
name: 'Emergency Stop',
path: '/emergency-stop',
},
{
Component: PrivacyPolicy,
exact: true,
name: 'Privacy Policy',
path: '/privacy-policy',
},
{
Component: DeckConfigurationEditor,
exact: true,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/src/assets/localization/en/device_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"about_calibration_description": "For the robot to move accurately and precisely, you need to calibrate it. Positional calibration happens in three parts: deck calibration, pipette offset calibration and tip length calibration.",
"about_calibration_description_ot3": "<block>For the robot to move accurately and precisely, you need to calibrate it. Pipette and gripper calibration is an automated process that uses a calibration probe or pin.</block><block>After calibration is complete, you can save the calibration data to your computer as a JSON file.</block>",
"about_calibration_title": "About Calibration",
"acknowledge_privacy_policy": "Acknowledge Privacy Policy",
"advanced": "Advanced",
"agree": "I agree",
"alpha_description": "Warning: alpha releases are feature-complete but may contain significant bugs.",
"alternative_security_types": "Alternative security types",
"alternative_security_types_description": "The Opentrons App supports connecting Flex to various enterprise access points. Connect via USB and finish setup in the app.",
Expand Down Expand Up @@ -206,6 +208,7 @@
"pipette_offset_calibration_recommended": "Pipette Offset calibration recommended",
"pipette_offset_calibrations_history": "See all Pipette Offset Calibration history",
"pipette_offset_calibrations_title": "Pipette Offset Calibrations",
"privacy_policy_description": "<block>By proceeding you are agreeing to share robot usage data. Opentrons uses this data to improve our products and services.</block><block>To read more about our data collection policies, visit our Privacy Policy.</block>",
"problem_during_update": "This update is taking longer than usual.",
"proceed_without_updating": "Proceed without update",
"protocol_run_history": "Protocol run History",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function ConfirmRobotName({
}
return (
<>
<StepMeter totalSteps={6} currentStep={6} />
<StepMeter totalSteps={5} currentStep={5} />
<Flex
padding={`${SPACING.spacing32} ${SPACING.spacing40} ${SPACING.spacing40}`}
flexDirection={DIRECTION_COLUMN}
Expand Down
2 changes: 1 addition & 1 deletion app/src/pages/ConnectViaEthernet/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function ConnectViaEthernet(): JSX.Element {

return (
<>
<StepMeter totalSteps={6} currentStep={2} />
<StepMeter totalSteps={5} currentStep={1} />
<Flex
margin={`${SPACING.spacing32} ${SPACING.spacing40} ${SPACING.spacing40}`}
flexDirection={DIRECTION_COLUMN}
Expand Down
2 changes: 1 addition & 1 deletion app/src/pages/ConnectViaUSB/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function ConnectViaUSB(): JSX.Element {

return (
<>
<StepMeter totalSteps={6} currentStep={2} />
<StepMeter totalSteps={5} currentStep={1} />
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing32}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('ConnectViaWifi', () => {
render()
screen.getByTestId('StepMeter_StepMeterContainer')
const bar = screen.getByTestId('StepMeter_StepMeterBar')
expect(bar).toHaveStyle('width: 33.33333333333333%')
expect(bar).toHaveStyle('width: 20%')
})

it('should render Searching for networks', () => {
Expand Down
2 changes: 1 addition & 1 deletion app/src/pages/ConnectViaWifi/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function ConnectViaWifi(): JSX.Element {

return (
<>
<StepMeter totalSteps={6} currentStep={2} />
<StepMeter totalSteps={5} currentStep={1} />
<Flex
flexDirection={DIRECTION_COLUMN}
// subtract height of StepMeter
Expand Down
15 changes: 13 additions & 2 deletions app/src/pages/EmergencyStop/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { useHistory } from 'react-router-dom'
import { useSelector } from 'react-redux'

import {
Icon,
Expand All @@ -14,6 +15,10 @@ import {
TYPOGRAPHY,
} from '@opentrons/components'
import { useEstopQuery } from '@opentrons/react-api-client'
import {
getAnalyticsOptInSeen,
getAnalyticsOptedIn,
} from '../../redux/analytics'

import { StyledText } from '../../atoms/text'
import { MediumButton } from '../../atoms/buttons'
Expand All @@ -26,6 +31,8 @@ const ESTOP_STATUS_REFETCH_INTERVAL_MS = 10000
export function EmergencyStop(): JSX.Element {
const { i18n, t } = useTranslation(['device_settings', 'shared'])
const history = useHistory()
const seenOptIn = useSelector(getAnalyticsOptInSeen)
const optedIn = useSelector(getAnalyticsOptedIn)

// Note here the touchscreen app is using status since status is linked to EstopPhysicalStatuses
// left notPresent + right disengaged => disengaged
Expand All @@ -38,7 +45,7 @@ export function EmergencyStop(): JSX.Element {

return (
<>
<StepMeter totalSteps={6} currentStep={4} />
<StepMeter totalSteps={5} currentStep={2} />
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing32}
Expand Down Expand Up @@ -98,7 +105,11 @@ export function EmergencyStop(): JSX.Element {
flex="1"
buttonText={i18n.format(t('shared:continue'), 'capitalize')}
disabled={!isEstopConnected}
onClick={() => history.push('/robot-settings/rename-robot')}
onClick={() => {
seenOptIn && optedIn
? history.push('/robot-settings/rename-robot')
: history.push('/privacy-policy')
}}
/>
</Flex>
</>
Expand Down
7 changes: 0 additions & 7 deletions app/src/pages/NameRobot/__tests__/NameRobot.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,4 @@ describe('NameRobot', () => {
screen.getByText('Enter up to 17 characters (letters and numbers only)')
screen.getByText('Confirm')
})

it('should call a mock function when tapping back button', () => {
mockuseIsUnboxingFlowOngoing.mockReturnValue(false)
render()
fireEvent.click(screen.getByTestId('name_back_button'))
expect(mockPush).toHaveBeenCalledWith('/robot-settings')
})
})
18 changes: 2 additions & 16 deletions app/src/pages/NameRobot/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
COLORS,
TYPOGRAPHY,
Icon,
Btn,
} from '@opentrons/components'
import { useUpdateRobotNameMutation } from '@opentrons/react-api-client'

Expand Down Expand Up @@ -153,7 +152,7 @@ export function NameRobot(): JSX.Element {
) : (
<>
{isUnboxingFlowOngoing ? (
<StepMeter totalSteps={6} currentStep={5} />
<StepMeter totalSteps={5} currentStep={4} />
) : null}
<Flex
flexDirection={DIRECTION_COLUMN}
Expand All @@ -168,20 +167,7 @@ export function NameRobot(): JSX.Element {
}
position={POSITION_RELATIVE}
>
<Flex position={POSITION_ABSOLUTE} left="0">
<Btn
data-testid="name_back_button"
onClick={() => {
if (isUnboxingFlowOngoing) {
history.push('/emergency-stop')
} else {
history.push('/robot-settings')
}
}}
>
<Icon name="back" size="3rem" color={COLORS.black90} />
</Btn>
</Flex>
<Flex position={POSITION_ABSOLUTE} left="0"></Flex>
<Flex marginLeft={isUnboxingFlowOngoing ? '0' : '4rem'}>
<StyledText as="h2" fontWeight={TYPOGRAPHY.fontWeightBold}>
{isUnboxingFlowOngoing
Expand Down
2 changes: 1 addition & 1 deletion app/src/pages/NetworkSetupMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function NetworkSetupMenu(): JSX.Element {

return (
<>
<StepMeter totalSteps={6} currentStep={1} />
<StepMeter totalSteps={5} currentStep={1} />
<Flex
padding={`${SPACING.spacing32} ${SPACING.spacing60} ${SPACING.spacing60}`}
flexDirection={DIRECTION_COLUMN}
Expand Down
106 changes: 106 additions & 0 deletions app/src/pages/PrivacyPolicy/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { useHistory } from 'react-router-dom'

import {
Flex,
DIRECTION_COLUMN,
SPACING,
JUSTIFY_CENTER,
ALIGN_CENTER,
TYPOGRAPHY,
COLORS,
} from '@opentrons/components'

import {
getAnalyticsOptedIn,
toggleAnalyticsOptedIn,
setAnalyticsOptInSeen,
getAnalyticsOptInSeen,
} from '../../redux/analytics'
import { useIsUnboxingFlowOngoing } from '../../organisms/RobotSettingsDashboard/NetworkSettings/hooks'
import { StyledText } from '../../atoms/text'
import { MediumButton } from '../../atoms/buttons'
import { StepMeter } from '../../atoms/StepMeter'

import type { Dispatch } from '../../redux/types'
import imgSrc from '../../assets/images/on-device-display/privacy_policy_qrcode.png'

const PRIVACY_POLICY_URL = 'opentrons.com/privacy-policy/'
const IMG_ALT = 'QR Code for Opentrons Privacy Policy'

export function PrivacyPolicy(): JSX.Element {
const { t } = useTranslation(['device_settings', 'shared'])
const history = useHistory()
const dispatch = useDispatch<Dispatch>()
const isUnboxingFlowOngoing = useIsUnboxingFlowOngoing()
const seenOptedIn = useSelector(getAnalyticsOptInSeen)
const optedIn = useSelector(getAnalyticsOptedIn)

Check warning on line 39 in app/src/pages/PrivacyPolicy/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/PrivacyPolicy/index.tsx#L34-L39

Added lines #L34 - L39 were not covered by tests

const handleAgree = (): void => {
dispatch(setAnalyticsOptInSeen())
dispatch(toggleAnalyticsOptedIn())

Check warning on line 43 in app/src/pages/PrivacyPolicy/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/PrivacyPolicy/index.tsx#L41-L43

Added lines #L41 - L43 were not covered by tests
}

if (seenOptedIn && optedIn) {
if (isUnboxingFlowOngoing) {
history.push('/robot-settings/rename-robot')

Check warning on line 48 in app/src/pages/PrivacyPolicy/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/PrivacyPolicy/index.tsx#L48

Added line #L48 was not covered by tests
} else {
history.push('/dashboard')

Check warning on line 50 in app/src/pages/PrivacyPolicy/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/PrivacyPolicy/index.tsx#L50

Added line #L50 was not covered by tests
}
}

return (

Check warning on line 54 in app/src/pages/PrivacyPolicy/index.tsx

View check run for this annotation

Codecov / codecov/patch

app/src/pages/PrivacyPolicy/index.tsx#L54

Added line #L54 was not covered by tests
<>
{isUnboxingFlowOngoing ? (
<StepMeter totalSteps={5} currentStep={3} />
) : null}
<Flex flexDirection={DIRECTION_COLUMN}>
<Flex justifyContent={JUSTIFY_CENTER} alignItems={ALIGN_CENTER}>
<StyledText
as="h2"
fontWeight={TYPOGRAPHY.fontWeightBold}
paddingX={SPACING.spacing40}
paddingY={SPACING.spacing32}
>
{t('acknowledge_privacy_policy')}
</StyledText>
</Flex>
<Flex
gridGap={SPACING.spacing40}
paddingX={SPACING.spacing40}
paddingBottom={SPACING.spacing40}
>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing24}>
<Trans
t={t}
i18nKey={'privacy_policy_description'}
components={{ block: <StyledText as="h4" /> }}
/>
<StyledText
as="p"
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
ncdiehl11 marked this conversation as resolved.
Show resolved Hide resolved
paddingX={SPACING.spacing24}
paddingY={SPACING.spacing16}
borderRadius={SPACING.spacing12}
backgroundColor={COLORS.grey35}
>
{PRIVACY_POLICY_URL}
</StyledText>
</Flex>
<Flex>
<img src={imgSrc} alt={IMG_ALT} width="178px" height="178px" />
</Flex>
</Flex>
<Flex padding={SPACING.spacing40} paddingTop={SPACING.spacing48}>
<MediumButton
flex="1"
buttonText={t('agree')}
onClick={handleAgree}
/>
</Flex>
</Flex>
</>
)
}
91 changes: 0 additions & 91 deletions app/src/pages/RobotDashboard/AnalyticsOptInModal.tsx

This file was deleted.

Loading
Loading