diff --git a/frontend/src/components/Header/Header.tsx b/frontend/src/components/Header/Header.tsx index 32eb2a086..c065f6dc4 100644 --- a/frontend/src/components/Header/Header.tsx +++ b/frontend/src/components/Header/Header.tsx @@ -7,10 +7,15 @@ import { Icons } from 'utils/icons' import { useAlertContext } from 'components/Contexts/AlertContext' import { AlertBanner } from 'components/Alerts/AlertsBanner' import { FrontPageSectionId } from 'models/FrontPageSectionId' +import { NavigationMenu } from './NavigationMenu' const StyledTopBar = styled(TopBar)` - align-items: center; + display: flex; box-shadow: none; + padding: 8px 24px 0px 24px; + justify-content: space-between; + align-items: center; + align-self: stretch; ` const StyledWrapper = styled.div` display: flex; @@ -64,6 +69,7 @@ export const Header = ({ page }: { page: string }) => { </StyledTopBarHeader> </TopBar.Header> </StyledWrapper> + <NavigationMenu /> <TopBar.Actions> <Button variant="ghost_icon" diff --git a/frontend/src/components/Header/NavigationMenu.tsx b/frontend/src/components/Header/NavigationMenu.tsx new file mode 100644 index 000000000..47e56f734 --- /dev/null +++ b/frontend/src/components/Header/NavigationMenu.tsx @@ -0,0 +1,62 @@ +import { Button, Icon, Menu } from '@equinor/eds-core-react' +import { useLanguageContext } from 'components/Contexts/LanguageContext' +import { config } from 'config' +import { useState } from 'react' +import { useNavigate } from 'react-router-dom' +import { styled } from 'styled-components' +import { Icons } from 'utils/icons' + +const StyledButton = styled(Button)` + width: 100px; + border-radius: 4px; +` + +export const NavigationMenu = () => { + const { TranslateText } = useLanguageContext() + const [isOpen, setIsOpen] = useState(false) + const [anchorEl, setAnchorEl] = useState(null) + const openMenu = () => { + setIsOpen(true) + } + const closeMenu = () => { + setIsOpen(false) + } + + const paths = [ + { path: 'frontPage', label: 'Front page' }, + { path: 'missionControl', label: 'Mission control' }, + { path: 'history', label: 'Mission history' }, + { path: 'inspectionPage', label: 'Deck overview' }, + { path: 'robotsPage', label: 'Robots' }, + ] + + let navigate = useNavigate() + const routeChange = (routePath: string) => { + const path = `${config.FRONTEND_BASE_ROUTE}/${routePath}` + navigate(path) + return + } + + return ( + <> + <StyledButton + id="menu" + variant="ghost" + ref={setAnchorEl} + aria-label="Menu" + aria-haspopup="true" + aria-expanded={isOpen} + aria-controls="menu" + onClick={() => (isOpen ? closeMenu() : openMenu())} + > + <Icon name={Icons.Menu} /> + {TranslateText('Menu')} + </StyledButton> + <Menu open={isOpen} id="menu" aria-labelledby="menu" onClose={closeMenu} anchorEl={anchorEl}> + {paths.map((page) => ( + <Menu.Item onClick={() => routeChange(page.path)}>{TranslateText(page.label)}</Menu.Item> + ))} + </Menu> + </> + ) +} diff --git a/frontend/src/components/Pages/FlotillaSite.tsx b/frontend/src/components/Pages/FlotillaSite.tsx index ca88800c2..e3989b5b4 100644 --- a/frontend/src/components/Pages/FlotillaSite.tsx +++ b/frontend/src/components/Pages/FlotillaSite.tsx @@ -7,6 +7,9 @@ import { RobotPage } from './RobotPage/RobotPage' import { APIUpdater } from 'components/Contexts/APIUpdater' import { MissionDefinitionPage } from './MissionDefinitionPage/MissionDefinitionPage' import { AssetSelectionPage } from './AssetSelectionPage/AssetSelectionPage' +import { MissionControlPage } from './FrontPage/MissionControlPage' +import { InspectionPage } from './InspectionPage/InspectionPage' +import { RobotsPage } from './RobotPage/RobotsPage' export const FlotillaSite = () => { return ( @@ -23,6 +26,9 @@ export const FlotillaSite = () => { /> <Route path={`${config.FRONTEND_BASE_ROUTE}/history`} element={<MissionHistoryPage />} /> <Route path={`${config.FRONTEND_BASE_ROUTE}/robot/:robotId`} element={<RobotPage />} /> + <Route path={`${config.FRONTEND_BASE_ROUTE}/missionControl`} element={<MissionControlPage />} /> + <Route path={`${config.FRONTEND_BASE_ROUTE}/inspectionPage`} element={<InspectionPage />} /> + <Route path={`${config.FRONTEND_BASE_ROUTE}/robotsPage`} element={<RobotsPage />} /> </Routes> </BrowserRouter> </APIUpdater> diff --git a/frontend/src/components/Pages/FrontPage/FrontPage.tsx b/frontend/src/components/Pages/FrontPage/FrontPage.tsx index 109582a6c..07808eae0 100644 --- a/frontend/src/components/Pages/FrontPage/FrontPage.tsx +++ b/frontend/src/components/Pages/FrontPage/FrontPage.tsx @@ -5,14 +5,12 @@ import { Header } from 'components/Header/Header' import styled from 'styled-components' import { InspectionOverviewSection } from 'components/Pages/InspectionPage/InspectionOverview' import { StopRobotDialog } from './MissionOverview/StopDialogs' -import { tokens } from '@equinor/eds-tokens' +import { StyledPage } from 'components/Styles/StyledComponents' -const StyledFrontPage = styled.div` +const StyledFrontPage = styled(StyledPage)` display: grid; grid-template-columns: repeat(auto-fill, minmax(100%, 1fr)); gap: 3rem; - padding: 15px 15px; - background-color: ${tokens.colors.ui.background__light.hex}; ` const HorizontalContent = styled.div` diff --git a/frontend/src/components/Pages/FrontPage/MissionControlPage.tsx b/frontend/src/components/Pages/FrontPage/MissionControlPage.tsx new file mode 100644 index 000000000..a98ddb878 --- /dev/null +++ b/frontend/src/components/Pages/FrontPage/MissionControlPage.tsx @@ -0,0 +1,37 @@ +import { MissionQueueView } from 'components/Pages/FrontPage/MissionOverview/MissionQueueView' +import { OngoingMissionView } from 'components/Pages/FrontPage/MissionOverview/OngoingMissionView' +import { Header } from 'components/Header/Header' +import styled from 'styled-components' +import { StopRobotDialog } from './MissionOverview/StopDialogs' +import { StyledPage } from 'components/Styles/StyledComponents' + +const HorizontalContent = styled.div` + display: flex; + flex-wrap: wrap; + grid-template-columns: auto auto; + gap: 2rem; +` + +const MissionsContent = styled.div` + display: flex; + flex-wrap: wrap; + flex-direction: row; + gap: 2rem; +` + +export const MissionControlPage = () => { + return ( + <> + <Header page={'missionControlPage'} /> + <StyledPage> + <StopRobotDialog /> + <HorizontalContent> + <MissionsContent> + <OngoingMissionView /> + <MissionQueueView /> + </MissionsContent> + </HorizontalContent> + </StyledPage> + </> + ) +} diff --git a/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusCard.tsx b/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusCard.tsx index a50e9c228..f2d5ad2b0 100644 --- a/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusCard.tsx +++ b/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusCard.tsx @@ -22,6 +22,7 @@ const StyledCard = styled(Card)` const HoverableStyledCard = styled(Card)` display: flex; flex-direction: column; + height: 300px; width: 280px; gap: 0px; background-color: ${tokens.colors.ui.background__default.hex}; diff --git a/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusSection.tsx b/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusSection.tsx index 1edb91dd9..fe1de14b0 100644 --- a/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusSection.tsx +++ b/frontend/src/components/Pages/FrontPage/RobotCards/RobotStatusSection.tsx @@ -10,9 +10,10 @@ const RobotCardSection = styled.div` gap: 2rem; ` const RobotView = styled.div` - display: grid; - grid-column: 1/ -1; - gap: 1rem; + display: flex; + padding-top: 1rem; + flex-direction: column; + gap: 1.5rem; ` export const RobotStatusSection = () => { diff --git a/frontend/src/components/Pages/InspectionPage/InspectionPage.tsx b/frontend/src/components/Pages/InspectionPage/InspectionPage.tsx new file mode 100644 index 000000000..593c7a3af --- /dev/null +++ b/frontend/src/components/Pages/InspectionPage/InspectionPage.tsx @@ -0,0 +1,14 @@ +import { Header } from 'components/Header/Header' +import { InspectionOverviewSection } from 'components/Pages/InspectionPage/InspectionOverview' +import { StyledPage } from 'components/Styles/StyledComponents' + +export const InspectionPage = () => { + return ( + <> + <Header page={'inspectionPage'} /> + <StyledPage> + <InspectionOverviewSection /> + </StyledPage> + </> + ) +} diff --git a/frontend/src/components/Pages/MissionHistoryPage/FilterSection.tsx b/frontend/src/components/Pages/MissionHistoryPage/FilterSection.tsx index fe2201b16..070fe35fd 100644 --- a/frontend/src/components/Pages/MissionHistoryPage/FilterSection.tsx +++ b/frontend/src/components/Pages/MissionHistoryPage/FilterSection.tsx @@ -26,7 +26,7 @@ const StyledHeader = styled.div` } ` -const StyledSerach = styled(Search)` +const StyledSearch = styled(Search)` display: flex; width: 288px; height: 36px; @@ -35,6 +35,9 @@ const StyledSerach = styled(Search)` border-bottom: none; border: 1px solid ${tokens.colors.ui.background__medium.hex}; --eds-input-background: white; + > div { + box-shadow: unset; + } ` const StyledButtonDiv = styled.div` @@ -85,7 +88,7 @@ export const FilterSection = () => { return ( <> <StyledHeader> - <StyledSerach + <StyledSearch value={filterState.missionName ?? ''} placeholder={TranslateText('Search for missions')} onChange={(changes: ChangeEvent<HTMLInputElement>) => { diff --git a/frontend/src/components/Pages/MissionHistoryPage/MissionHistoryPage.tsx b/frontend/src/components/Pages/MissionHistoryPage/MissionHistoryPage.tsx index d3a6b8540..f3fc0677b 100644 --- a/frontend/src/components/Pages/MissionHistoryPage/MissionHistoryPage.tsx +++ b/frontend/src/components/Pages/MissionHistoryPage/MissionHistoryPage.tsx @@ -2,26 +2,20 @@ import { MissionHistoryView } from './MissionHistoryView' import { BackButton } from 'utils/BackButton' import { Header } from 'components/Header/Header' import { StyledPage } from 'components/Styles/StyledComponents' -import { styled } from 'styled-components' -import { tokens } from '@equinor/eds-tokens' export type RefreshProps = { refreshInterval: number } - -const StyledMissionHistoryPage = styled(StyledPage)` - background-color: ${tokens.colors.ui.background__light.hex}; -` export const MissionHistoryPage = () => { const refreshInterval = 1000 return ( <> <Header page={'history'} /> - <StyledMissionHistoryPage> + <StyledPage> <BackButton /> <MissionHistoryView refreshInterval={refreshInterval} /> - </StyledMissionHistoryPage> + </StyledPage> </> ) } diff --git a/frontend/src/components/Pages/RobotPage/RobotsPage.tsx b/frontend/src/components/Pages/RobotPage/RobotsPage.tsx new file mode 100644 index 000000000..c8be568c1 --- /dev/null +++ b/frontend/src/components/Pages/RobotPage/RobotsPage.tsx @@ -0,0 +1,21 @@ +import { RobotStatusSection } from 'components/Pages/FrontPage/RobotCards/RobotStatusSection' +import { Header } from 'components/Header/Header' +import styled from 'styled-components' +import { StyledPage } from 'components/Styles/StyledComponents' + +const StyledRobotsPage = styled(StyledPage)` + display: grid; + grid-template-columns: repeat(auto-fill, minmax(100%, 1fr)); + gap: 3rem; +` + +export const RobotsPage = () => { + return ( + <> + <Header page={'robotsPage'} /> + <StyledRobotsPage> + <RobotStatusSection /> + </StyledRobotsPage> + </> + ) +} diff --git a/frontend/src/components/Styles/StyledComponents.tsx b/frontend/src/components/Styles/StyledComponents.tsx index 008ceea23..c87de3f6a 100644 --- a/frontend/src/components/Styles/StyledComponents.tsx +++ b/frontend/src/components/Styles/StyledComponents.tsx @@ -28,13 +28,13 @@ export const TextAlignedButton = styled(Button)` ` export const StyledPage = styled.div` display: flex; - flex-wrap: wrap; justify-content: start; flex-direction: column; gap: 1rem; - padding: 2rem; + padding: 15px 15px; @media (max-width: 600px) { padding: 0.7rem; } min-height: calc(100vh - 65px); + background-color: ${tokens.colors.ui.background__light.hex}; ` diff --git a/frontend/src/language/en.json b/frontend/src/language/en.json index dfdebd2f1..e5b07c1cd 100644 --- a/frontend/src/language/en.json +++ b/frontend/src/language/en.json @@ -259,5 +259,11 @@ "Failed to update inspection": "Failed to update inspection", "Battery": "Battery", "Recharging": "Recharging", - "Active Filters": "Active Filters" + "Active Filters": "Active Filters", + "Menu": "Menu", + "Front page": "Front page", + "Mission control": "Mission control", + "Mission history": "Mission history", + "Deck overview": "Deck overview", + "Robots": "Robots" } diff --git a/frontend/src/language/no.json b/frontend/src/language/no.json index 51049db3c..4faea80cd 100644 --- a/frontend/src/language/no.json +++ b/frontend/src/language/no.json @@ -259,5 +259,11 @@ "Failed to update inspection": "Kunne ikke oppdatere inspeksjon", "Battery": "Batteri", "Recharging": "Lader", - "Active Filters": "Aktive filtre" + "Active Filters": "Aktive filtre", + "Menu": "Meny", + "Front page": "Front page", + "Mission control": "Mission control", + "Mission history": "Historikk", + "Deck overview": "Dekkoversikt", + "Robots": "Roboter" } diff --git a/frontend/src/utils/icons.tsx b/frontend/src/utils/icons.tsx index 348272b70..02d75eba7 100644 --- a/frontend/src/utils/icons.tsx +++ b/frontend/src/utils/icons.tsx @@ -42,6 +42,7 @@ import { info_circle, blocked, close_circle_outlined, + menu, } from '@equinor/eds-icons' Icon.add({ @@ -87,6 +88,7 @@ Icon.add({ info_circle, blocked, close_circle_outlined, + menu, }) export enum Icons { @@ -132,4 +134,5 @@ export enum Icons { Info = 'info_circle', Blocked = 'blocked', ClosedCircleOutlined = 'close_circle_outlined', + Menu = 'menu', }