Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ compose:

broker:
docker compose up broker --build

# run pretties, eslint and check fo unused exports
format-frontend:
npx prettier --write src
npx eslint src
node_modules/.bin/ts-unused-exports tsconfig.json

31 changes: 5 additions & 26 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@ import { ApplicationInsights } from '@microsoft/applicationinsights-web'
import { AuthenticatedTemplate, UnauthenticatedTemplate } from '@azure/msal-react'
import { FlotillaSite } from 'pages/FlotillaSite'
import { LanguageProvider } from 'components/Contexts/LanguageContext'
import { MissionControlProvider } from 'components/Contexts/MissionControlContext'
import { MissionRunsProvider } from 'components/Contexts/MissionRunsContext'
import { AlertProvider } from 'components/Contexts/AlertContext'
import { AuthProvider } from 'components/Contexts/AuthProvider'
import { SignalRProvider } from 'components/Contexts/SignalRContext'
import { AssetProvider } from 'components/Contexts/AssetContext'
import { config } from 'config'
import { MissionDefinitionsProvider } from 'components/Contexts/MissionDefinitionsContext'
import { MediaStreamProvider } from 'components/Contexts/MediaStreamContext'
import { InspectionsProvider } from 'components/Contexts/InspectionsContext'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const appInsights = new ApplicationInsights({
Expand All @@ -32,25 +25,11 @@ const App = () => (
<UnauthenticatedTemplate />
<AuthenticatedTemplate>
<LanguageProvider>
<SignalRProvider>
<QueryClientProvider client={queryClient}>
<AssetProvider>
<InspectionsProvider>
<MissionDefinitionsProvider>
<MissionRunsProvider>
<AlertProvider>
<MissionControlProvider>
<MediaStreamProvider>
<FlotillaSite />
</MediaStreamProvider>
</MissionControlProvider>
</AlertProvider>
</MissionRunsProvider>
</MissionDefinitionsProvider>
</InspectionsProvider>
</AssetProvider>
</QueryClientProvider>
</SignalRProvider>
<QueryClientProvider client={queryClient}>
<MediaStreamProvider>
<FlotillaSite />
</MediaStreamProvider>
</QueryClientProvider>
</LanguageProvider>
</AuthenticatedTemplate>
</AuthProvider>
Expand Down
18 changes: 11 additions & 7 deletions frontend/src/api/BackendApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ import { InspectionArea } from 'models/InspectionArea'
import { MissionDefinitionUpdateForm } from 'models/MissionDefinitionUpdateForm'
import { filterRobots } from 'utils/filtersAndSorts'
import { PointillaMapInfo } from 'models/PointillaMapInfo'
import { Installation } from 'models/Installation'

export class BackendApi {
constructor(
private readonly api: BackendAPICaller,
private readonly installationCode: string | null
) {}
constructor(private readonly api: BackendAPICaller) {}

async postControlMissionRequest(path: string, robotId: string): Promise<void> {
const body = { robotId: robotId }
Expand Down Expand Up @@ -45,7 +43,7 @@ export class BackendApi {
let path: string = 'missions/runs?'

// Always filter by currently selected installation
if (this.installationCode) path = path + 'InstallationCode=' + this.installationCode + '&'
path = path + 'InstallationCode=' + parameters.installationCode + '&'

if (parameters.statuses) {
parameters.statuses.forEach((status) => {
Expand Down Expand Up @@ -82,7 +80,7 @@ export class BackendApi {
return { pagination: pagination, content: result.content }
}

async getAvailableMissions(installationCode: string = ''): Promise<CondensedMissionDefinition[]> {
async getAvailableMissions(installationCode: string): Promise<CondensedMissionDefinition[]> {
const path: string = 'mission-loader/available-missions/' + installationCode
const result = await this.api.GET<MissionDefinition[]>(path).catch(handleError('GET', path))
return result.content
Expand All @@ -94,7 +92,7 @@ export class BackendApi {
let path: string = 'missions/definitions?'

// Always filter by currently selected installation
if (this.installationCode) path = path + 'InstallationCode=' + this.installationCode + '&'
path = path + 'InstallationCode=' + parameters.installationCode + '&'

if (parameters.inspectionArea) path = path + 'InspectionArea=' + parameters.inspectionArea + '&'
if (parameters.sourceId) path = path + 'SourceId=' + parameters.sourceId + '&'
Expand Down Expand Up @@ -216,6 +214,12 @@ export class BackendApi {
return result.content
}

async getInstallations(): Promise<Installation[]> {
const path: string = 'installations'
const result = await this.api.GET<Installation[]>(path).catch(handleError('GET', path))
return result.content
}

async reRunMission(missionId: string, failedTasksOnly: boolean = false): Promise<Mission> {
const mission = await this.getMissionRunById(missionId)

Expand Down
6 changes: 2 additions & 4 deletions frontend/src/api/UseBackendApi.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { useContext, useMemo } from 'react'
import { BackendApi } from './BackendApi'
import { AuthContext } from 'components/Contexts/AuthContext'
import { AssetContext } from 'components/Contexts/AssetContext'
import { BackendAPICaller } from './ApiCaller'

export function useBackendApi() {
const { getAccessToken } = useContext(AuthContext)
const { installationCode } = useContext(AssetContext)

return useMemo(() => {
const api = new BackendAPICaller(getAccessToken)
return new BackendApi(api, installationCode ?? null)
}, [getAccessToken, installationCode])
return new BackendApi(api)
}, [])
}
14 changes: 8 additions & 6 deletions frontend/src/components/Alerts/FailedMissionAlert.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { config } from 'config'
import { Mission, MissionStatus } from 'models/Mission'
import { MissionStatusDisplay } from 'components/Displays/MissionDisplays/MissionStatusDisplay'
import { useNavigate } from 'react-router-dom'
Expand All @@ -7,7 +6,8 @@ import { AlertListContents } from './AlertsListItem'
import { Icons } from 'utils/icons'
import { tokens } from '@equinor/eds-tokens'
import { AlertContainer, AlertButton } from './AlertStyles'
import { useAssetContext } from 'components/Contexts/AssetContext'
import { useContext } from 'react'
import { InstallationContext } from 'components/Contexts/InstallationContext'

interface MissionsProps {
missions: Mission[]
Expand All @@ -16,10 +16,11 @@ interface MissionsProps {
const FailedMission = ({ missions }: MissionsProps) => {
const mission = missions[0]
const { TranslateText } = useLanguageContext()
const { installationCode } = useAssetContext()
const { installation } = useContext(InstallationContext)
const navigate = useNavigate()

const goToMission = () => {
const path = `${config.FRONTEND_BASE_ROUTE}/${installationCode}:mission?id=${mission.id}`
const path = `/${installation.installationCode}/mission/${mission.id}`
navigate(path)
}

Expand All @@ -33,10 +34,11 @@ const FailedMission = ({ missions }: MissionsProps) => {

const SeveralFailedMissions = ({ missions }: MissionsProps) => {
const { TranslateText } = useLanguageContext()
const { installationCode } = useAssetContext()
const { installation } = useContext(InstallationContext)
const navigate = useNavigate()

const goToHistory = () => {
const path = `${config.FRONTEND_BASE_ROUTE}/${installationCode}:history`
const path = `/${installation.installationCode}/history`
navigate(path)
}

Expand Down
30 changes: 21 additions & 9 deletions frontend/src/components/Contexts/AlertContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FailedRequestAlertContent, FailedRequestAlertListContent } from 'compon
import { InfoAlertContent, InfoAlertListContent } from 'components/Alerts/InfoAlertContent'
import { useBackendApi } from 'api/UseBackendApi'
import { AuthContext } from './AuthContext'
import { InstallationContext } from './InstallationContext'

export enum AlertType {
MissionFail,
Expand All @@ -39,7 +40,7 @@ const alertTypeEnumMap: { [key: string]: AlertType } = {
skipAutoMission: AlertType.InfoAlert,
}

type AlertDictionaryType = {
export type AlertDictionaryType = {
[key in AlertType]?: { content: ReactNode | undefined; dismissFunction: () => void; alertCategory: AlertCategory }
}

Expand Down Expand Up @@ -81,7 +82,8 @@ export const AlertProvider: FC<Props> = ({ children }) => {
const [recentFailedMissions, setRecentFailedMissions] = useState<Mission[]>([])
const { registerEvent, connectionReady } = useSignalRContext()
const { TranslateText } = useLanguageContext()
const { enabledRobots, installationCode } = useAssetContext()
const { enabledRobots } = useAssetContext()
const { installation } = useContext(InstallationContext)
const [autoScheduleFailedMissionDict, setAutoScheduleFailedMissionDict] = useState<AutoScheduleFailedMissionDict>(
JSON.parse(window.localStorage.getItem('autoScheduleFailedMissionDict') || '{}')
)
Expand Down Expand Up @@ -171,12 +173,17 @@ export const AlertProvider: FC<Props> = ({ children }) => {
const updateRecentFailedMissions = () => {
const lastDismissTime: Date = getLastDismissalTime()
backendApi
.getMissionRuns({ statuses: [MissionStatus.Failed], pageSize: pageSize })
.getMissionRuns({
installationCode: installation.installationCode,
statuses: [MissionStatus.Failed],
pageSize: pageSize,
})
.then((missions) => {
const newRecentFailedMissions = missions.content.filter(
(m) =>
convertUTCDateToLocalDate(new Date(m.endTime!)) > lastDismissTime &&
m.installationCode!.toLocaleLowerCase() === installationCode.toLocaleLowerCase()
m.installationCode!.toLocaleLowerCase() ===
installation.installationCode.toLocaleLowerCase()
)
setRecentFailedMissions(newRecentFailedMissions)
})
Expand All @@ -198,7 +205,7 @@ export const AlertProvider: FC<Props> = ({ children }) => {
})
}
if (!recentFailedMissions || recentFailedMissions.length === 0) updateRecentFailedMissions()
}, [installationCode])
}, [installation])

// Register a signalR event handler that listens for new failed missions
useEffect(() => {
Expand All @@ -210,7 +217,8 @@ export const AlertProvider: FC<Props> = ({ children }) => {
setRecentFailedMissions((failedMissions) => {
if (
!newFailedMission.installationCode ||
newFailedMission.installationCode.toLocaleLowerCase() !== installationCode.toLocaleLowerCase()
newFailedMission.installationCode.toLocaleLowerCase() !==
installation.installationCode.toLocaleLowerCase()
)
return failedMissions // Ignore missions for other installations
// Ignore missions shortly after the user dismissed the last one
Expand All @@ -222,13 +230,17 @@ export const AlertProvider: FC<Props> = ({ children }) => {
})
})
}
}, [registerEvent, connectionReady, installationCode])
}, [registerEvent, connectionReady, installation])

useEffect(() => {
if (connectionReady) {
registerEvent(SignalREventLabels.alert, (username: string, message: string) => {
const backendAlert: Alert = JSON.parse(message)
if (backendAlert.installationCode.toLocaleLowerCase() !== installationCode.toLocaleLowerCase()) return
if (
backendAlert.installationCode.toLocaleLowerCase() !==
installation.installationCode.toLocaleLowerCase()
)
return

const alertType = alertTypeEnumMap[backendAlert.alertCode]

Expand Down Expand Up @@ -272,7 +284,7 @@ export const AlertProvider: FC<Props> = ({ children }) => {
}
})
}
}, [registerEvent, connectionReady, installationCode, enabledRobots])
}, [registerEvent, connectionReady, installation, enabledRobots])

useEffect(() => {
if (recentFailedMissions.length > 0) {
Expand Down
Loading
Loading