-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add localization verification on mission schedule
For missions scheduled through inspection plan
- Loading branch information
Showing
8 changed files
with
374 additions
and
31 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
frontend/src/components/Displays/LocalizationVerification/ConfirmLocalizationDialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
) | ||
} |
83 changes: 83 additions & 0 deletions
83
frontend/src/components/Displays/LocalizationVerification/ConflictingLocalizationDialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
) | ||
} |
20 changes: 20 additions & 0 deletions
20
frontend/src/components/Displays/LocalizationVerification/ScheduleMissionStyles.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
` |
99 changes: 99 additions & 0 deletions
99
...ponents/Displays/LocalizationVerification/ScheduleMissionWithLocalizationVerification.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} />} | ||
</> | ||
) | ||
} |
29 changes: 29 additions & 0 deletions
29
frontend/src/components/Displays/LocalizationVerification/UnknownDeckDialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
) | ||
} |
Oops, something went wrong.