Skip to content

Commit

Permalink
Store plant and installation in frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
andchiind committed Aug 1, 2023
1 parent aa3913b commit 54343fd
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 101 deletions.
4 changes: 2 additions & 2 deletions backend/api/Controllers/EchoController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public EchoController(ILogger<EchoController> logger, IEchoService echoService)
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ProducesResponseType(StatusCodes.Status502BadGateway)]
public async Task<ActionResult<IList<CondensedMissionDefinition>>> GetAvailableEchoMissions(string? plantCode)
public async Task<ActionResult<IList<CondensedMissionDefinition>>> GetAvailableEchoMissions(string? installationCode)
{
try
{
var missions = await _echoService.GetAvailableMissions(plantCode);
var missions = await _echoService.GetAvailableMissions(installationCode);
return Ok(missions);
}
catch (HttpRequestException e)
Expand Down
1 change: 1 addition & 0 deletions backend/api/Controllers/Models/EchoPlantInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ public class EchoPlantInfo
{
public string PlantCode { get; set; }
public string ProjectDescription { get; set; }
public string InstallationCode { get; set; }
}
}
3 changes: 2 additions & 1 deletion backend/api/Services/EchoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ List<EchoPlantInfoResponse> echoPlantInfoResponse
var echoPlantInfo = new EchoPlantInfo()
{
PlantCode = plant.InstallationCode,
ProjectDescription = plant.ProjectDescription
ProjectDescription = plant.ProjectDescription,
InstallationCode = plant.InstallationCode
};

echoPlantInfos.Add(echoPlantInfo);
Expand Down
19 changes: 0 additions & 19 deletions flotilla.code-workspace

This file was deleted.

5 changes: 3 additions & 2 deletions frontend/src/components/Contexts/APIUpdater.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BackendAPICaller } from 'api/ApiCaller'
import { useContext } from 'react'
import { InstallationContext } from './InstallationContext'
import { InstallationContext } from './PlantContext'
import { AuthContext } from './AuthProvider'

type Props = {
Expand All @@ -10,7 +10,8 @@ type Props = {
// Can't use contexts inside the static class so we need a component to update it
export const APIUpdater = (props: Props) => {
const accessToken = useContext(AuthContext)
const installationCode = useContext(InstallationContext).installationCode
const { currentPlant } = useContext(InstallationContext)
const installationCode = currentPlant ? currentPlant.installationCode : ''
BackendAPICaller.accessToken = accessToken
BackendAPICaller.installationCode = installationCode
return <>{props.children}</>
Expand Down
40 changes: 0 additions & 40 deletions frontend/src/components/Contexts/InstallationContext.tsx

This file was deleted.

45 changes: 45 additions & 0 deletions frontend/src/components/Contexts/PlantContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { EchoPlantInfo } from 'models/EchoMission'
import { createContext, FC, useContext, useState } from 'react'

interface IInstallationContext {
currentPlant: EchoPlantInfo | undefined
setPlant: (selectedEchoPlant: EchoPlantInfo | undefined) => void
}

interface Props {
children: React.ReactNode
}

const defaultInstallation = {
currentPlant: undefined,
setPlant: (selectedEchoPlant: EchoPlantInfo | undefined) => {},
}

export const InstallationContext = createContext<IInstallationContext>(defaultInstallation)

export const InstallationProvider: FC<Props> = ({ children }) => {
const localStoragePlant = window.localStorage.getItem('plant')
const previousPlant =
localStoragePlant && localStoragePlant != 'undefined' ? JSON.parse(localStoragePlant) : undefined
const [currentPlant, setCurrentPlant] = useState<EchoPlantInfo | undefined>(
previousPlant || defaultInstallation.currentPlant
)

const setPlant = (selectedEchoPlant: EchoPlantInfo | undefined) => {
setCurrentPlant(selectedEchoPlant)
window.localStorage.setItem('plant', JSON.stringify(selectedEchoPlant))
}

return (
<InstallationContext.Provider
value={{
currentPlant,
setPlant,
}}
>
{children}
</InstallationContext.Provider>
)
}

export const usePlantContext = () => useContext(InstallationContext)
29 changes: 17 additions & 12 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { config } from 'config'
import { Button, Icon, TopBar, Autocomplete, Typography } from '@equinor/eds-core-react'
import { BackendAPICaller } from 'api/ApiCaller'
import { useInstallationContext } from 'components/Contexts/InstallationContext'
import { usePlantContext } from 'components/Contexts/PlantContext'
import { EchoPlantInfo } from 'models/EchoMission'
import { useEffect, useState } from 'react'
import styled from 'styled-components'
Expand Down Expand Up @@ -72,35 +72,40 @@ export function Header({ page }: { page: string }) {

function InstallationPicker(page: string) {
const { TranslateText } = useLanguageContext()
const [allPlantsMap, setAllPlantsMap] = useState<Map<string, string>>()
const { installationCode, switchInstallation } = useInstallationContext()
const [allPlantsMap, setAllPlantsMap] = useState<{ [plantDescription: string]: EchoPlantInfo }>()
const { currentPlant, setPlant } = usePlantContext()
useEffect(() => {
BackendAPICaller.getEchoPlantInfo().then((response: EchoPlantInfo[]) => {
const mapping = mapInstallationCodeToName(response)
setAllPlantsMap(mapping)
})
}, [])
const mappedOptions = allPlantsMap ? allPlantsMap : new Map<string, string>()
const emptyObject: { [plantDescription: string]: EchoPlantInfo } = {}
const mappedOptions = allPlantsMap ? allPlantsMap : emptyObject
return (
<Autocomplete
options={Array.from(mappedOptions.keys()).sort()}
options={Array.from(Object.keys(mappedOptions)).sort()}
label=""
disabled={page === 'mission'}
initialSelectedOptions={[installationCode.toUpperCase()]}
initialSelectedOptions={[currentPlant?.projectDescription.toUpperCase()]}
placeholder={TranslateText('Select installation')}
onOptionsChange={({ selectedItems }) => {
const mapKey = mappedOptions.get(selectedItems[0])
if (mapKey !== undefined) switchInstallation(mapKey)
else switchInstallation('')
if (!selectedItems[0]) {
setPlant(undefined)
} else {
setPlant(mappedOptions[selectedItems[0]])
}
}}
/>
)
}

const mapInstallationCodeToName = (echoPlantInfoArray: EchoPlantInfo[]): Map<string, string> => {
var mapping = new Map<string, string>()
const mapInstallationCodeToName = (
echoPlantInfoArray: EchoPlantInfo[]
): { [plantDescription: string]: EchoPlantInfo } => {
var mapping: { [plantDescription: string]: EchoPlantInfo } = {}
echoPlantInfoArray.forEach((echoPlantInfo: EchoPlantInfo) => {
mapping.set(echoPlantInfo.projectDescription, echoPlantInfo.plantCode)
mapping[echoPlantInfo.projectDescription] = echoPlantInfo
})
return mapping
}
2 changes: 1 addition & 1 deletion frontend/src/components/Pages/FlotillaSite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { config } from 'config'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { FrontPage } from './FrontPage/FrontPage'
import { MissionPage } from './MissionPage/MissionPage'
import { InstallationProvider } from 'components/Contexts/InstallationContext'
import { InstallationProvider } from 'components/Contexts/PlantContext'
import { MissionHistoryPage } from './MissionHistoryPage/MissionHistoryPage'
import { RobotPage } from './RobotPage/RobotPage'
import { AuthProvider } from 'components/Contexts/AuthProvider'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { Button, Typography, Popover, Icon } from '@equinor/eds-core-react'
import { useLanguageContext } from 'components/Contexts/LanguageContext'
import { Icons } from 'utils/icons'
import { useRef, useState } from 'react'
import { useInstallationContext } from 'components/Contexts/InstallationContext'
import { usePlantContext } from 'components/Contexts/PlantContext'

export const CreateMissionButton = (): JSX.Element => {
const { TranslateText } = useLanguageContext()
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false)
const { installationCode } = useInstallationContext()
const { currentPlant } = usePlantContext()
const anchorRef = useRef<HTMLButtonElement>(null)
const echoURL = 'https://echo.equinor.com/missionplanner?instCode='

let timer: ReturnType<typeof setTimeout>
const openPopover = () => {
if (installationCode === '') setIsPopoverOpen(true)
if (!currentPlant) setIsPopoverOpen(true)
}

const closePopover = () => setIsPopoverOpen(false)
Expand All @@ -40,9 +40,9 @@ export const CreateMissionButton = (): JSX.Element => {
>
<Button
onClick={() => {
window.open(echoURL + installationCode)
window.open(echoURL + (currentPlant ? currentPlant.installationCode : ''))
}}
disabled={installationCode === ''}
disabled={currentPlant === undefined}
ref={anchorRef}
>
<>
Expand All @@ -55,7 +55,7 @@ export const CreateMissionButton = (): JSX.Element => {
<Popover
anchorEl={anchorRef.current}
onClose={handleClose}
open={isPopoverOpen && installationCode === ''}
open={isPopoverOpen && !currentPlant}
placement="top"
>
<Popover.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ScheduleMissionDialog } from './ScheduleMissionDialog'
import { Robot } from 'models/Robot'
import { RefreshProps } from '../FrontPage'
import { useLanguageContext } from 'components/Contexts/LanguageContext'
import { useInstallationContext } from 'components/Contexts/InstallationContext'
import { usePlantContext } from 'components/Contexts/PlantContext'
import { CreateMissionButton } from './CreateMissionButton'
import { MissionDefinition } from 'models/MissionDefinition'

Expand Down Expand Up @@ -59,15 +59,18 @@ export function MissionQueueView({ refreshInterval }: RefreshProps) {
const [scheduleButtonDisabled, setScheduleButtonDisabled] = useState<boolean>(true)
const [frontPageScheduleButtonDisabled, setFrontPageScheduleButtonDisabled] = useState<boolean>(true)
const [isFetchingEchoMissions, setIsFetchingEchoMissions] = useState<boolean>(false)
const { installationCode } = useInstallationContext()
const { currentPlant } = usePlantContext()

const fetchEchoMissions = () => {
setIsFetchingEchoMissions(true)
BackendAPICaller.getAvailableEchoMission(installationCode as string).then((missions) => {
const echoMissionsMap: Map<string, MissionDefinition> = mapEchoMissionToString(missions)
setEchoMissions(echoMissionsMap)
setIsFetchingEchoMissions(false)
})
// To fetch from the echo API using plantCode instead of installationCode we just need to use currentPlant.plantCode instead
BackendAPICaller.getAvailableEchoMission(currentPlant ? currentPlant.installationCode : ('' as string)).then(
(missions) => {
const echoMissionsMap: Map<string, MissionDefinition> = mapEchoMissionToString(missions)
setEchoMissions(echoMissionsMap)
setIsFetchingEchoMissions(false)
}
)
}

const onSelectedEchoMissions = (selectedEchoMissions: string[]) => {
Expand All @@ -88,7 +91,11 @@ export function MissionQueueView({ refreshInterval }: RefreshProps) {

selectedEchoMissions.forEach((mission: MissionDefinition) => {
// TODO: as a final parameter here we likely want mission.AreaName, and maybe also installation and deck codes
BackendAPICaller.postMission(mission.echoMissionId, selectedRobot.id, installationCode)
BackendAPICaller.postMission(
mission.echoMissionId,
selectedRobot.id,
currentPlant ? currentPlant.installationCode : ''
)
})

setSelectedEchoMissions([])
Expand Down Expand Up @@ -131,12 +138,12 @@ export function MissionQueueView({ refreshInterval }: RefreshProps) {
}, [selectedRobot, selectedEchoMissions])

useEffect(() => {
if (Array.from(robotOptions.keys()).length === 0 || installationCode === '') {
if (Array.from(robotOptions.keys()).length === 0 || !currentPlant) {
setFrontPageScheduleButtonDisabled(true)
} else {
setFrontPageScheduleButtonDisabled(false)
}
}, [robotOptions, installationCode])
}, [robotOptions, currentPlant])

var missionQueueDisplay = missionQueue.map(function (mission, index) {
return <MissionQueueCard key={index} mission={mission} onDeleteMission={onDeleteMission} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import styled from 'styled-components'
import { useLanguageContext } from 'components/Contexts/LanguageContext'
import { Icons } from 'utils/icons'
import { useRef, useState, useEffect } from 'react'
import { useInstallationContext } from 'components/Contexts/InstallationContext'
import { usePlantContext } from 'components/Contexts/PlantContext'
import { CreateMissionButton } from './CreateMissionButton'

interface IProps {
Expand Down Expand Up @@ -59,7 +59,7 @@ export const ScheduleMissionDialog = (props: IProps): JSX.Element => {
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false)
const [isScheduleMissionsPressed, setIsScheduleMissionsPressed] = useState<boolean>(false)
const anchorRef = useRef<HTMLButtonElement>(null)
const { installationCode } = useInstallationContext()
const { currentPlant } = usePlantContext()

useEffect(() => {
if (!props.isFetchingEchoMissions && isScheduleMissionsPressed) {
Expand Down Expand Up @@ -125,7 +125,7 @@ export const ScheduleMissionDialog = (props: IProps): JSX.Element => {
<Popover
anchorEl={anchorRef.current}
onClose={handleClose}
open={isPopoverOpen && installationCode === ''}
open={isPopoverOpen && !currentPlant}
placement="top"
>
<Popover.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useCallback, useEffect, useState } from 'react'
import styled from 'styled-components'
import { RefreshProps } from '../FrontPage'
import { RobotStatusCard, RobotStatusCardPlaceholder } from './RobotStatusCard'
import { useInstallationContext } from 'components/Contexts/InstallationContext'
import { usePlantContext } from 'components/Contexts/PlantContext'
import { useLanguageContext } from 'components/Contexts/LanguageContext'

const RobotCardSection = styled.div`
Expand All @@ -21,6 +21,7 @@ const RobotView = styled.div`
export function RobotStatusSection({ refreshInterval }: RefreshProps) {
const { TranslateText } = useLanguageContext()
const [robots, setRobots] = useState<Robot[]>([])
const { currentPlant } = usePlantContext()

const sortRobotsByStatus = useCallback((robots: Robot[]): Robot[] => {
const sortedRobots = robots.sort((robot, robotToCompareWith) =>
Expand All @@ -47,18 +48,17 @@ export function RobotStatusSection({ refreshInterval }: RefreshProps) {
return () => clearInterval(id)
}, [refreshInterval, updateRobots])

const { installationCode } = useInstallationContext()

var filteredRobots = robots.filter(function (robot) {
return (
robot.currentInstallation.toLocaleLowerCase() === installationCode.toLocaleLowerCase() ||
robot.currentInstallation.toLocaleLowerCase() ===
(currentPlant ? currentPlant.installationCode.toLocaleLowerCase() : '') ||
(typeof robot.currentInstallation === 'string' && robot.currentInstallation.includes('default')) ||
robot.currentInstallation === undefined
)
})

var robotDisplay
if (installationCode === '') {
if (!currentPlant) {
robotDisplay = robots.map(function (robot) {
return <RobotStatusCard key={robot.id} robot={robot} />
})
Expand Down
Loading

0 comments on commit 54343fd

Please sign in to comment.