Skip to content

Commit

Permalink
Add localization verification on mission schedule
Browse files Browse the repository at this point in the history
For missions scheduled through inspection plan
  • Loading branch information
Eddasol authored and aeshub committed Jan 8, 2024
1 parent 2208444 commit bc4b8d8
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Button, Checkbox, Dialog, Typography } from '@equinor/eds-core-react'
import { DeckMapView } from 'utils/DeckMapView'
import { HorizontalContent, StyledDialog, VerticalContent } from './ScheduleMissionStyles'
import { useLanguageContext } from 'components/Contexts/LanguageContext'
import { Robot } from 'models/Robot'
import { ChangeEvent, useEffect, useState } from 'react'
import { Deck } from 'models/Deck'
import { BackendAPICaller } from 'api/ApiCaller'

interface ConfirmLocalizationDialogProps {
closeDialog: () => void
scheduleMissions: () => void
robot: Robot
newDeckName: string
}

export const ConfirmLocalizationDialog = ({
closeDialog,
scheduleMissions,
robot,
newDeckName,
}: ConfirmLocalizationDialogProps) => {
const { TranslateText } = useLanguageContext()
const [isCheckboxClicked, setIsCheckboxClicked] = useState<boolean>(false)
const [newDeck, setNewDeck] = useState<Deck>()

useEffect(() => {
BackendAPICaller.getDecks().then(async (decks: Deck[]) => {
setNewDeck(decks.find((deck) => deck.deckName === newDeckName))
})
}, [newDeckName])

return (
<StyledDialog open={true} onClose={closeDialog}>
<Dialog.Header>
<Typography variant="h5">{TranslateText('Confirm placement of robot')}</Typography>
</Dialog.Header>
<Dialog.Content>
<VerticalContent>
<Typography>
{`${robot.name} (${robot.model.type}) ${TranslateText(
'needs to be placed on marked position on'
)} ${newDeckName} `}
<b>{TranslateText('before')}</b>
{` ${TranslateText('clicking confirm')}.`}
</Typography>
{newDeck && newDeck.defaultLocalizationPose && (
<DeckMapView deck={newDeck} markedRobotPosition={newDeck.defaultLocalizationPose}></DeckMapView>
)}
<HorizontalContent>
<Checkbox
crossOrigin={undefined}
onChange={(e: ChangeEvent<HTMLInputElement>) => setIsCheckboxClicked(e.target.checked)}
/>
<Typography>
{`${TranslateText('I confirm that')} ${robot.name} (${robot.model.type}) ${TranslateText(
'has been placed on marked position on'
)} `}
<b>{newDeckName}</b>
</Typography>
</HorizontalContent>
</VerticalContent>
</Dialog.Content>
<Dialog.Actions>
<HorizontalContent>
<Button variant="outlined" onClick={closeDialog}>
{TranslateText('Cancel')}
</Button>
<Button onClick={scheduleMissions} disabled={!isCheckboxClicked}>
{TranslateText('Confirm')}
</Button>
</HorizontalContent>
</Dialog.Actions>
</StyledDialog>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Button, Dialog, List, Typography } from '@equinor/eds-core-react'
import { StyledDialog, VerticalContent } from './ScheduleMissionStyles'
import { useLanguageContext } from 'components/Contexts/LanguageContext'

interface ConflictingRobotDeckDialogProps {
closeDialog: () => void
robotDeckName: string
desiredDeckName: string
}

interface ConflictingMissionDecksDialogProps {
closeDialog: () => void
missionDeckNames: string[]
}

export const ConflictingRobotDeckDialog = ({
closeDialog,
robotDeckName,
desiredDeckName,
}: ConflictingRobotDeckDialogProps) => {
const { TranslateText } = useLanguageContext()

return (
<StyledDialog open={true} onClose={closeDialog}>
<Dialog.Header>
<Typography variant="h5">{TranslateText('Conflicting decks')}</Typography>
</Dialog.Header>
<Dialog.Content>
<VerticalContent>
<Typography>
{TranslateText('The missions you are trying to add are on')} <b>{desiredDeckName}</b>{' '}
{TranslateText('but the robot is currently running missions on')} {<b>{robotDeckName}</b>}.
</Typography>
<Typography>{TranslateText('Will not be added dialog text')}</Typography>
</VerticalContent>
</Dialog.Content>
<Dialog.Actions>
<Button variant="outlined" color="danger" onClick={closeDialog}>
{TranslateText('Close')}
</Button>
</Dialog.Actions>
</StyledDialog>
)
}

export const ConflictingMissionDecksDialog = ({
closeDialog,
missionDeckNames,
}: ConflictingMissionDecksDialogProps) => {
const { TranslateText } = useLanguageContext()

const MissionDeckNamesList = (
<List>
{missionDeckNames.map((deckName) => (
<List.Item>
<b>{deckName}</b>
</List.Item>
))}
</List>
)

return (
<StyledDialog open={true} onClose={closeDialog}>
<Dialog.Header>
<Typography variant="h5">{TranslateText('Conflicting decks')}</Typography>
</Dialog.Header>
<Dialog.Content>
<VerticalContent>
<Typography>
{TranslateText('The missions you are trying to add are on these decks:')}
{MissionDeckNamesList}
</Typography>
<Typography>{TranslateText('You can only add missions from one deck.')}</Typography>
</VerticalContent>
</Dialog.Content>
<Dialog.Actions>
<Button variant="outlined" color="danger" onClick={closeDialog}>
{TranslateText('Close')}
</Button>
</Dialog.Actions>
</StyledDialog>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Dialog } from '@equinor/eds-core-react'
import styled from 'styled-components'

export const StyledDialog = styled(Dialog)`
display: flex;
flex-direction: column;
padding: 1rem;
width: 480px;
`

export const HorizontalContent = styled.div`
display: flex;
gap: 1rem;
`

export const VerticalContent = styled.div`
display: flex;
flex-direction: column;
gap: 1rem;
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Robot } from 'models/Robot'
import { useEffect, useState } from 'react'
import { ConfirmLocalizationDialog } from './ConfirmLocalizationDialog'
import { ConflictingMissionDecksDialog, ConflictingRobotDeckDialog } from './ConflictingLocalizationDialog'
import { UnknownDeckDialog } from './UnknownDeckDialog'
import { useRobotContext } from 'components/Contexts/RobotContext'

interface IProps {
scheduleMissions: () => void
closeDialog: () => void
robotId: string
missionDeckNames: string[]
}

enum DialogTypes {
verifyDeck,
unknownNewDeck,
conflictingMissionDecks,
conflictingRobotDeck,
unknown,
}

export const ScheduleMissionWithLocalizationVerificationDialog = ({
robotId,
missionDeckNames,
scheduleMissions,
closeDialog,
}: IProps): JSX.Element => {
const { enabledRobots } = useRobotContext()
const [dialogToOpen, setDialogToOpen] = useState<DialogTypes>(DialogTypes.unknown)
const [selectedRobot, setSelectedRobot] = useState<Robot>()

const unikMissionDeckNames = missionDeckNames.filter(
(deckName, index) => deckName !== '' && missionDeckNames.indexOf(deckName) === index
)

useEffect(() => {
setSelectedRobot(enabledRobots.find((robot) => robot.id === robotId))
}, [robotId, enabledRobots])

useEffect(() => {
if (!selectedRobot) return

if (
unikMissionDeckNames.length === 1 &&
selectedRobot.currentArea?.deckName &&
unikMissionDeckNames[0] === selectedRobot?.currentArea?.deckName
) {
scheduleMissions()
return
}

if (unikMissionDeckNames.length > 1) {
setDialogToOpen(DialogTypes.conflictingMissionDecks)
return
}

if (unikMissionDeckNames.length === 0) {
setDialogToOpen(DialogTypes.unknownNewDeck)
return
}

if (!selectedRobot.currentArea?.deckName) {
setDialogToOpen(DialogTypes.verifyDeck)
return
}

if (unikMissionDeckNames[0] !== selectedRobot.currentArea?.deckName) {
setDialogToOpen(DialogTypes.conflictingRobotDeck)
return
}
// To ignore scheduleMissions dependency
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [unikMissionDeckNames, selectedRobot?.currentArea?.deckName])

return (
<>
{dialogToOpen === DialogTypes.verifyDeck && (
<ConfirmLocalizationDialog
closeDialog={closeDialog}
scheduleMissions={scheduleMissions}
robot={selectedRobot!}
newDeckName={unikMissionDeckNames![0]}
/>
)}
{dialogToOpen === DialogTypes.conflictingMissionDecks && (
<ConflictingMissionDecksDialog closeDialog={closeDialog} missionDeckNames={unikMissionDeckNames!} />
)}
{dialogToOpen === DialogTypes.conflictingRobotDeck && (
<ConflictingRobotDeckDialog
closeDialog={closeDialog}
robotDeckName={selectedRobot?.currentArea?.deckName!}
desiredDeckName={unikMissionDeckNames![0]}
/>
)}
{dialogToOpen === DialogTypes.unknownNewDeck && <UnknownDeckDialog closeDialog={closeDialog} />}
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Button, Dialog, Typography } from '@equinor/eds-core-react'
import { StyledDialog, VerticalContent } from './ScheduleMissionStyles'
import { useLanguageContext } from 'components/Contexts/LanguageContext'

interface UnknownDeckDialogProps {
closeDialog: () => void
}

export const UnknownDeckDialog = ({ closeDialog }: UnknownDeckDialogProps) => {
const { TranslateText } = useLanguageContext()

return (
<StyledDialog open={true} onClose={closeDialog}>
<Dialog.Header>
<Typography variant="h5">{TranslateText('Unknown deck')}</Typography>
</Dialog.Header>
<Dialog.Content>
<VerticalContent>
<Typography>{TranslateText('Cannot start selected mission as it has unknown deck.')}</Typography>
</VerticalContent>
</Dialog.Content>
<Dialog.Actions>
<Button variant="outlined" color="danger" onClick={closeDialog}>
{TranslateText('Close')}
</Button>
</Dialog.Actions>
</StyledDialog>
)
}
Loading

0 comments on commit bc4b8d8

Please sign in to comment.