Skip to content

Commit

Permalink
fix(app): add reinstall support for new robot update flows (#13554)
Browse files Browse the repository at this point in the history
Closes RQA-1587

Also adds support for robot downgrading.
  • Loading branch information
mjhuff authored Sep 14, 2023
1 parent 487de91 commit c8aca82
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 32 deletions.
2 changes: 2 additions & 0 deletions app/src/assets/localization/en/device_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@
"robot_successfully_connected": "Robot successfully connected to {{networkName}}.",
"robot_system_version": "Robot System Version",
"robot_system_version_available": "Robot System Version {{releaseVersion}} available",
"robot_up_to_date": "Robot is up to date",
"robot_up_to_date_description": "It looks like your robot is already up to date, but if you're experiencing issues you can re-apply the latest update.",
"robot_update_available": "Robot Update Available",
"robot_update_success": "Robot software successfully updated",
"search_again": "Search again",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ function RobotUpdateProgressFooter({
}: RobotUpdateProgressFooterProps): JSX.Element {
const { t } = useTranslation('device_settings')
const dispatch = useDispatch<Dispatch>()
// TODO(jh, 08-30-2023: add reinstall logic for zip file installation)
const installUpdate = React.useCallback(() => {
dispatch(clearRobotUpdateSession())
dispatch(startRobotUpdate(robotName))
Expand Down Expand Up @@ -123,7 +122,7 @@ function RobotUpdateProgressFooter({
interface RobotUpdateProgressModalProps {
robotName: string
updateStep: UpdateStep
stepProgress?: number | null
stepProgress: number | null
error?: string | null
closeUpdateBuildroot?: () => void
}
Expand Down Expand Up @@ -162,12 +161,8 @@ export function RobotUpdateProgressModal({
)
}

let modalBodyText = t('downloading_update')
if (updateStep === 'install') {
modalBodyText = t('installing_update')
} else if (updateStep === 'restart') {
modalBodyText = t('restarting_robot')
}
let modalBodyText = t('installing_update')
if (updateStep === 'restart') modalBodyText = t('restarting_robot')

// Make sure to start the animation when this modal first pops up
React.useEffect(startUpdatingAnimation, [])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import {
robotUpdateChangelogSeen,
startRobotUpdate,
OT2_BALENA,
UPGRADE,
REINSTALL,
DOWNGRADE,
} from '../../../../redux/robot-update'
import { ReleaseNotes } from '../../../../molecules/ReleaseNotes'
import { useIsRobotBusy } from '../../hooks'
Expand All @@ -45,18 +48,21 @@ export const FOOTER_BUTTON_STYLE = css`
text-transform: uppercase;
}
`
type UpdateType = typeof UPGRADE | typeof DOWNGRADE | typeof REINSTALL | null

export interface UpdateRobotModalProps {
robotName: string
releaseNotes: string
systemType: RobotSystemType | null
systemType: RobotSystemType
updateType: UpdateType
closeModal: () => void
}

export function UpdateRobotModal({
robotName,
releaseNotes,
systemType,
updateType,
closeModal,
}: UpdateRobotModalProps): JSX.Element {
const dispatch = useDispatch<Dispatch>()
Expand All @@ -78,10 +84,17 @@ export function UpdateRobotModal({
dispatch(robotUpdateChangelogSeen(robotName))
}, [robotName])

const heading =
systemType === OT2_BALENA
? 'Robot Operating System Update'
: `${robotName} ${t('update_available')}`
let heading = ''
if (updateType === UPGRADE || updateType === DOWNGRADE) {
if (systemType === OT2_BALENA) {
heading = t('robot_operating_update_available')
} else {
heading = `${robotName} ${t('update_available')}`
}
} else if (updateType === REINSTALL) {
heading = t('robot_up_to_date')
releaseNotes = t('robot_up_to_date_description')
}

const robotUpdateFooter = (
<Flex alignItems={ALIGN_CENTER} justifyContent={JUSTIFY_FLEX_END}>
Expand All @@ -90,7 +103,7 @@ export function UpdateRobotModal({
marginRight={SPACING.spacing8}
css={FOOTER_BUTTON_STYLE}
>
{t('remind_me_later')}
{updateType === UPGRADE ? t('remind_me_later') : t('not_now')}
</NewSecondaryBtn>
<NewPrimaryBtn
onClick={() => dispatch(startRobotUpdate(robotName))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useSelector } from 'react-redux'

import {
OT2_BALENA,
UPGRADE,
getRobotUpdateInfo,
getRobotUpdateDownloadProgress,
getRobotUpdateDownloadError,
Expand Down Expand Up @@ -54,7 +53,6 @@ export function ViewUpdateModal(
children: downloadError !== null ? 'close' : 'not now',
}

const showReleaseNotes = robotUpdateType === UPGRADE
let releaseNotes = ''
if (updateInfo?.releaseNotes) releaseNotes = updateInfo.releaseNotes

Expand Down Expand Up @@ -85,12 +83,13 @@ export function ViewUpdateModal(
/>
)

if (showReleaseNotes)
if (robotSystemType != null)
return (
<UpdateRobotModal
robotName={robotName}
releaseNotes={releaseNotes}
systemType={robotSystemType}
updateType={robotUpdateType}
closeModal={closeModal}
/>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,6 @@ describe('DownloadUpdateModal', () => {
})
})

it('renders the correct text when downloading the robot update with no close button', () => {
const [{ queryByRole, getByText }] = render(props)

expect(getByText('Downloading update...')).toBeInTheDocument()
expect(
getByText('Do not turn off the robot while updating')
).toBeInTheDocument()
expect(queryByRole('button')).not.toBeInTheDocument()
})

it('renders the correct text when installing the robot update with no close button', () => {
props = {
...props,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('UpdateRobotModal', () => {
releaseNotes: 'test notes',
systemType: 'flex',
closeModal: jest.fn(),
updateType: 'upgrade',
}
when(mockGetRobotUpdateDisplayInfo).mockReturnValue({
autoUpdateAction: 'upgrade',
Expand All @@ -56,7 +57,7 @@ describe('UpdateRobotModal', () => {
jest.resetAllMocks()
})

it('renders an update available header if the type is not Balena', () => {
it('renders an update available header if the type is not Balena when upgrading', () => {
const [{ getByText }] = render(props)
getByText('test robot Update Available')
})
Expand All @@ -67,10 +68,10 @@ describe('UpdateRobotModal', () => {
systemType: 'ot2-balena',
}
const [{ getByText }] = render(props)
getByText('Robot Operating System Update')
getByText('Robot Operating System Update Available')
})

it('renders release notes and a modal header close icon', () => {
it('renders release notes and a modal header close icon when upgrading', () => {
const [{ getByText, getByTestId }] = render(props)
getByText('test notes')

Expand All @@ -81,7 +82,7 @@ describe('UpdateRobotModal', () => {
expect(props.closeModal).toHaveBeenCalled()
})

it('renders remind me later and and disabled update robot now buttons', () => {
it('renders remind me later and and disabled update robot now buttons when upgrading', () => {
const [{ getByText }] = render(props)
getByText('test notes')

Expand All @@ -91,4 +92,29 @@ describe('UpdateRobotModal', () => {
fireEvent.click(remindMeLater)
expect(props.closeModal).toHaveBeenCalled()
})

it('renders proper text when reinstalling', () => {
props = {
...props,
updateType: 'reinstall',
}

const [{ getByText, queryByText }] = render(props)
getByText('Robot is up to date')
queryByText('It looks like your robot is already up to date')
getByText('Not now')
getByText('Update robot now')
})

it('renders proper text when downgrading', () => {
props = {
...props,
updateType: 'downgrade',
}

const [{ getByText }] = render(props)
getByText('test robot Update Available')
getByText('Not now')
getByText('Update robot now')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ export function UpdateBuildroot(props: UpdateBuildrootProps): JSX.Element {

const robotSystemType = getRobotSystemType(robot)

// TODO(jh, 09-14-2023: add download logic to app-shell/redux/progress bar.
let updateStep: UpdateStep
if (step == null) updateStep = 'download'
const DOWNLOAD_STEPS = ['getToken']
if (step == null || DOWNLOAD_STEPS.includes(step)) updateStep = 'download'
else if (step === 'finished') updateStep = 'finished'
else if (step === 'restart' || step === 'restarting') updateStep = 'restart'
else updateStep = 'install'
Expand Down

0 comments on commit c8aca82

Please sign in to comment.