diff --git a/frontend/src/components/Alerts/AlertsListItem.tsx b/frontend/src/components/Alerts/AlertsListItem.tsx
index 8b26e520d..90a0264fa 100644
--- a/frontend/src/components/Alerts/AlertsListItem.tsx
+++ b/frontend/src/components/Alerts/AlertsListItem.tsx
@@ -31,7 +31,7 @@ const StyledListItem = styled(outline)`
display: flex;
flex-direction: column;
align-items: left;
- row-gap: 10px
+ row-gap: 10px;
`
const VerticalContent = styled.div`
@@ -55,9 +55,9 @@ const Horizontal = styled.div`
`
const Right = styled.div`
- display: flex;
- align-items: right;
- justify-content: right;
+ display: flex;
+ align-items: right;
+ justify-content: right;
`
export enum AlertCategory {
@@ -82,24 +82,31 @@ interface AlertProps {
export const AlertListContents = ({ icon, iconColor, alertTitle, alertText, mission }: AlertListInfo) => {
let missionHasFailedTasks = false
- if (mission !== undefined) missionHasFailedTasks = mission.tasks.some(
- (t) => t.status !== TaskStatus.PartiallySuccessful && t.status !== TaskStatus.Successful
- )
+ if (mission !== undefined)
+ missionHasFailedTasks = mission.tasks.some(
+ (t) => t.status !== TaskStatus.PartiallySuccessful && t.status !== TaskStatus.Successful
+ )
return (
<>
- {alertTitle}
+ {alertTitle}
- {alertText}
+ {alertText}
- {mission !== undefined && mission.tasks[0]?.type !== TaskType.ReturnHome && mission.tasks[0]?.type !== TaskType.Localization && (
-
- )}
+ {mission !== undefined &&
+ mission.tasks[0]?.type !== TaskType.ReturnHome &&
+ mission.tasks[0]?.type !== TaskType.Localization && (
+
+ )}
@@ -107,9 +114,6 @@ export const AlertListContents = ({ icon, iconColor, alertTitle, alertText, miss
)
}
-
-
-
export const AlertListItem = ({ children, dismissAlert }: AlertProps) => {
return (
<>
diff --git a/frontend/src/components/Alerts/BlockedRobotAlert.tsx b/frontend/src/components/Alerts/BlockedRobotAlert.tsx
index 679ebfc93..bab3647a1 100644
--- a/frontend/src/components/Alerts/BlockedRobotAlert.tsx
+++ b/frontend/src/components/Alerts/BlockedRobotAlert.tsx
@@ -47,12 +47,16 @@ export const BlockedRobotAlertContent = ({ robotNames }: AlertProps) => {
export const BlockedRobotAlertListContent = ({ robotNames }: AlertProps) => {
const { TranslateText } = useLanguageContext()
- let message =
- `${TranslateText('The robot')} ${robotNames[0]} ${TranslateText('is blocked and cannot perform tasks')}.`
+ let message = `${TranslateText('The robot')} ${robotNames[0]} ${TranslateText('is blocked and cannot perform tasks')}.`
if (robotNames.length > 1) message = `${TranslateText('Several robots are blocked and cannot perform tasks')}.`
return (
-
+
)
}
diff --git a/frontend/src/components/Alerts/FailedAlertContent.tsx b/frontend/src/components/Alerts/FailedAlertContent.tsx
index f2c7e343e..03b09ab20 100644
--- a/frontend/src/components/Alerts/FailedAlertContent.tsx
+++ b/frontend/src/components/Alerts/FailedAlertContent.tsx
@@ -20,10 +20,6 @@ const Indent = styled.div`
padding: 0px 9px;
`
-
-
-
-
export const FailedAlertContent = ({ title, message }: { title: string; message: string }) => {
const { TranslateText } = useLanguageContext()
const iconColor = tokens.colors.interactive.danger__resting.rgba
@@ -44,10 +40,14 @@ export const FailedAlertContent = ({ title, message }: { title: string; message:
)
}
-
export const FailedAlertListContent = ({ title, message }: { title: string; message: string }) => {
const { TranslateText } = useLanguageContext()
return (
-
+
)
}
diff --git a/frontend/src/components/Alerts/FailedMissionAlert.tsx b/frontend/src/components/Alerts/FailedMissionAlert.tsx
index f48d492cb..b5868f7dd 100644
--- a/frontend/src/components/Alerts/FailedMissionAlert.tsx
+++ b/frontend/src/components/Alerts/FailedMissionAlert.tsx
@@ -71,9 +71,24 @@ export const FailedMissionAlertListContent = ({ missions }: MissionsProps) => {
const { TranslateText } = useLanguageContext()
const mission = missions[0]
let message = `${mission.name} ${TranslateText('failed on robot')} ${mission.robot.name}: ${mission.statusReason}`
- if (mission.statusReason === null) message = `${mission.name} ${TranslateText('failed on robot')} ${mission.robot.name}`
- if (missions.length > 1) message = `${missions.length.toString()} ${TranslateText("missions failed recently. See 'Mission History' for more information.")}.`
- return (
-
+ if (mission.statusReason === null)
+ message = `${mission.name} ${TranslateText('failed on robot')} ${mission.robot.name}`
+ if (missions.length > 1)
+ message = `${missions.length.toString()} ${TranslateText("missions failed recently. See 'Mission History' for more information.")}.`
+ return missions.length === 1 ? (
+
+ ) : (
+
)
}
diff --git a/frontend/src/components/Alerts/FailedRequestAlert.tsx b/frontend/src/components/Alerts/FailedRequestAlert.tsx
index e6bc10c5d..8d7983719 100644
--- a/frontend/src/components/Alerts/FailedRequestAlert.tsx
+++ b/frontend/src/components/Alerts/FailedRequestAlert.tsx
@@ -38,6 +38,11 @@ export const FailedRequestAlertContent = ({ translatedMessage }: { translatedMes
export const FailedRequestAlertListContent = ({ translatedMessage }: { translatedMessage: string }) => {
const { TranslateText } = useLanguageContext()
return (
-
+
)
}
diff --git a/frontend/src/components/Alerts/SafeZoneAlert.tsx b/frontend/src/components/Alerts/SafeZoneAlert.tsx
index e3f20216a..c01d1dad1 100644
--- a/frontend/src/components/Alerts/SafeZoneAlert.tsx
+++ b/frontend/src/components/Alerts/SafeZoneAlert.tsx
@@ -50,7 +50,6 @@ export const SafeZoneAlertContent = ({ alertType, alertCategory }: SafeZoneBanne
)
}
-
export const SafeZoneAlertListContent = ({ alertType, alertCategory }: SafeZoneBannerProps): JSX.Element => {
const { TranslateText } = useLanguageContext()
let titleMessage = TranslateText('INFO')
@@ -58,10 +57,18 @@ export const SafeZoneAlertListContent = ({ alertType, alertCategory }: SafeZoneB
let icon = Icons.Warning
let iconColor = tokens.colors.interactive.danger__resting.rgba
if (alertCategory === AlertCategory.WARNING) titleMessage = TranslateText('WARNING')
- if (alertCategory === AlertCategory.INFO && alertType === AlertType.SafeZoneSuccess) [message, icon, iconColor] = [TranslateText('Safe Zone successful text'), Icons.Info, tokens.colors.text.static_icons__default.rgba]
- if (alertCategory === AlertCategory.INFO && alertType === AlertType.DismissSafeZone) [message, icon, iconColor] = [TranslateText('Dismiss safe zone banner text'), Icons.Info, tokens.colors.text.static_icons__default.rgba]
+ if (alertCategory === AlertCategory.INFO && alertType === AlertType.SafeZoneSuccess)
+ [message, icon, iconColor] = [
+ TranslateText('Safe Zone successful text'),
+ Icons.Info,
+ tokens.colors.text.static_icons__default.rgba,
+ ]
+ if (alertCategory === AlertCategory.INFO && alertType === AlertType.DismissSafeZone)
+ [message, icon, iconColor] = [
+ TranslateText('Dismiss safe zone banner text'),
+ Icons.Info,
+ tokens.colors.text.static_icons__default.rgba,
+ ]
- return (
-
- )
+ return
}
diff --git a/frontend/src/components/Contexts/AlertContext.tsx b/frontend/src/components/Contexts/AlertContext.tsx
index 34c4648b7..41382ffca 100644
--- a/frontend/src/components/Contexts/AlertContext.tsx
+++ b/frontend/src/components/Contexts/AlertContext.tsx
@@ -1,20 +1,20 @@
import { createContext, FC, ReactNode, useContext, useEffect, useState } from 'react'
import { addMinutes, max } from 'date-fns'
import { Mission, MissionStatus } from 'models/Mission'
-import { FailedMissionAlertListContent } from 'components/Alerts/FailedMissionAlert'
+import { FailedMissionAlertContent, FailedMissionAlertListContent } from 'components/Alerts/FailedMissionAlert'
import { BackendAPICaller } from 'api/ApiCaller'
import { SignalREventLabels, useSignalRContext } from './SignalRContext'
import { useInstallationContext } from './InstallationContext'
import { Alert } from 'models/Alert'
import { useRobotContext } from './RobotContext'
-import { BlockedRobotAlertListContent } from 'components/Alerts/BlockedRobotAlert'
+import { BlockedRobotAlertContent, BlockedRobotAlertListContent } from 'components/Alerts/BlockedRobotAlert'
import { RobotStatus } from 'models/Robot'
-import { FailedAlertListContent } from 'components/Alerts/FailedAlertContent'
+import { FailedAlertContent, FailedAlertListContent } from 'components/Alerts/FailedAlertContent'
import { convertUTCDateToLocalDate } from 'utils/StringFormatting'
import { AlertCategory } from 'components/Alerts/AlertsBanner'
-import { SafeZoneAlertListContent } from 'components/Alerts/SafeZoneAlert'
+import { SafeZoneAlertContent, SafeZoneAlertListContent } from 'components/Alerts/SafeZoneAlert'
import { useLanguageContext } from './LanguageContext'
-import { FailedRequestAlertListContent } from 'components/Alerts/FailedRequestAlert'
+import { FailedRequestAlertContent, FailedRequestAlertListContent } from 'components/Alerts/FailedRequestAlert'
export enum AlertType {
MissionFail,
@@ -41,6 +41,10 @@ interface IAlertContext {
setAlert: (source: AlertType, alert: ReactNode, category: AlertCategory) => void
clearAlerts: () => void
clearAlert: (source: AlertType) => void
+ listAlerts: AlertDictionaryType
+ setListAlert: (source: AlertType, listAlert: ReactNode, category: AlertCategory) => void
+ clearListAlerts: () => void
+ clearListAlert: (source: AlertType) => void
}
interface Props {
@@ -49,15 +53,20 @@ interface Props {
const defaultAlertInterface = {
alerts: {},
- setAlert: (source: AlertType, alert: ReactNode, category: AlertCategory) => { },
- clearAlerts: () => { },
- clearAlert: (source: AlertType) => { },
+ setAlert: (source: AlertType, alert: ReactNode, category: AlertCategory) => {},
+ clearAlerts: () => {},
+ clearAlert: (source: AlertType) => {},
+ listAlerts: {},
+ setListAlert: (source: AlertType, alert: ReactNode, category: AlertCategory) => {},
+ clearListAlerts: () => {},
+ clearListAlert: (source: AlertType) => {},
}
export const AlertContext = createContext(defaultAlertInterface)
export const AlertProvider: FC = ({ children }) => {
const [alerts, setAlerts] = useState(defaultAlertInterface.alerts)
+ const [listAlerts, setListAlerts] = useState(defaultAlertInterface.listAlerts)
const [recentFailedMissions, setRecentFailedMissions] = useState([])
const [blockedRobotNames, setBlockedRobotNames] = useState([])
const { registerEvent, connectionReady } = useSignalRContext()
@@ -94,6 +103,32 @@ export const AlertProvider: FC = ({ children }) => {
})
}
+ const setListAlert = (source: AlertType, listAlert: ReactNode, category: AlertCategory) => {
+ setListAlerts((oldListAlerts) => {
+ return {
+ ...oldListAlerts,
+ [source]: {
+ content: listAlert,
+ dismissFunction: () => clearListAlert(source),
+ alertCategory: category,
+ },
+ }
+ })
+ }
+
+ const clearListAlerts = () => setAlerts({})
+
+ const clearListAlert = (source: AlertType) => {
+ if (source === AlertType.MissionFail)
+ sessionStorage.setItem(dismissMissionFailTimeKey, JSON.stringify(Date.now()))
+
+ setListAlerts((oldListAlerts) => {
+ let newListAlerts = { ...oldListAlerts }
+ delete newListAlerts[source]
+ return newListAlerts
+ })
+ }
+
const getLastDismissalTime = (): Date => {
const sessionValue = sessionStorage.getItem(dismissMissionFailTimeKey)
if (sessionValue === null || sessionValue === '') {
@@ -124,6 +159,13 @@ export const AlertProvider: FC = ({ children }) => {
})
.catch((e) => {
setAlert(
+ AlertType.RequestFail,
+ ,
+ AlertCategory.ERROR
+ )
+ setListAlert(
AlertType.RequestFail,
= ({ children }) => {
installationCode &&
(!newFailedMission.installationCode ||
newFailedMission.installationCode.toLocaleLowerCase() !==
- installationCode.toLocaleLowerCase())
+ installationCode.toLocaleLowerCase())
)
return failedMissions // Ignore missions for other installations
// Ignore missions shortly after the user dismissed the last one
@@ -174,12 +216,23 @@ export const AlertProvider: FC = ({ children }) => {
if (alertType === AlertType.SafeZoneSuccess) {
setAlert(
alertType,
- ,
+ ,
AlertCategory.INFO
)
clearAlert(AlertType.RequestSafeZone)
+ setListAlert(
+ alertType,
+ ,
+ AlertCategory.INFO
+ )
+ clearListAlert(AlertType.RequestSafeZone)
} else {
setAlert(
+ alertType,
+ ,
+ AlertCategory.ERROR
+ )
+ setListAlert(
alertType,
,
AlertCategory.ERROR
@@ -193,6 +246,11 @@ export const AlertProvider: FC = ({ children }) => {
useEffect(() => {
if (newFailedMissions.length > 0) {
setAlert(
+ AlertType.MissionFail,
+ ,
+ AlertCategory.ERROR
+ )
+ setListAlert(
AlertType.MissionFail,
,
AlertCategory.ERROR
@@ -207,7 +265,7 @@ export const AlertProvider: FC = ({ children }) => {
.filter(
(robot) =>
robot.currentInstallation.installationCode.toLocaleLowerCase() ===
- installationCode.toLocaleLowerCase() && robot.status === RobotStatus.Blocked
+ installationCode.toLocaleLowerCase() && robot.status === RobotStatus.Blocked
)
.map((robot) => robot.name!)
@@ -218,12 +276,18 @@ export const AlertProvider: FC = ({ children }) => {
if (isBlockedRobotNamesModifyed) {
if (newBlockedRobotNames.length > 0) {
setAlert(
+ AlertType.BlockedRobot,
+ ,
+ AlertCategory.WARNING
+ )
+ setListAlert(
AlertType.BlockedRobot,
,
AlertCategory.WARNING
)
} else {
clearAlert(AlertType.BlockedRobot)
+ clearListAlert(AlertType.BlockedRobot)
}
}
setBlockedRobotNames(newBlockedRobotNames)
@@ -237,6 +301,10 @@ export const AlertProvider: FC = ({ children }) => {
setAlert,
clearAlerts,
clearAlert,
+ listAlerts,
+ setListAlert,
+ clearListAlerts,
+ clearListAlert,
}}
>
{children}
diff --git a/frontend/src/components/Contexts/InstallationContext.tsx b/frontend/src/components/Contexts/InstallationContext.tsx
index 45ee62cdb..ec95e7c5c 100644
--- a/frontend/src/components/Contexts/InstallationContext.tsx
+++ b/frontend/src/components/Contexts/InstallationContext.tsx
@@ -6,7 +6,7 @@ import { SignalREventLabels, useSignalRContext } from './SignalRContext'
import { Area } from 'models/Area'
import { useLanguageContext } from './LanguageContext'
import { AlertType, useAlertContext } from './AlertContext'
-import { FailedRequestAlertListContent } from 'components/Alerts/FailedRequestAlert'
+import { FailedRequestAlertContent, FailedRequestAlertListContent } from 'components/Alerts/FailedRequestAlert'
import { AlertCategory } from 'components/Alerts/AlertsBanner'
interface IInstallationContext {
@@ -34,7 +34,7 @@ const defaultInstallation = {
installationName: '',
installationDecks: [],
installationAreas: [],
- switchInstallation: (selectedInstallation: string) => { },
+ switchInstallation: (selectedInstallation: string) => {},
}
export const InstallationContext = createContext(defaultInstallation)
@@ -42,7 +42,7 @@ export const InstallationContext = createContext(defaultIn
export const InstallationProvider: FC = ({ children }) => {
const { registerEvent, connectionReady } = useSignalRContext()
const { TranslateText } = useLanguageContext()
- const { setAlert } = useAlertContext()
+ const { setAlert, setListAlert } = useAlertContext()
const [allPlantsMap, setAllPlantsMap] = useState