diff --git a/src/app/AppLayout/AppLayout.tsx b/src/app/AppLayout/AppLayout.tsx index a1cf09692..6a7b6f458 100644 --- a/src/app/AppLayout/AppLayout.tsx +++ b/src/app/AppLayout/AppLayout.tsx @@ -1,8 +1,8 @@ /* * Copyright The Cryostat Authors - * + * * The Universal Permissive License (UPL), Version 1.0 - * + * * Subject to the condition set forth below, permission is hereby granted to any * person obtaining a copy of this software, associated documentation and/or data * (collectively the "Software"), free of charge and under any and all copyright @@ -10,23 +10,23 @@ * licensable by each licensor hereunder covering either (i) the unmodified * Software as contributed to or provided by such licensor, or (ii) the Larger * Works (as defined below), to deal in both - * + * * (a) the Software, and * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if * one is included with the Software (each a "Larger Work" to which the Software * is contributed by such licensors), - * + * * without restriction, including without limitation the rights to copy, create * derivative works of, display, perform, and distribute the Software and make, * use, sell, offer for sale, import, export, have made, and have sold the * Software and the Larger Work(s), and to sublicense the foregoing rights on * either these or other terms. - * + * * This license is subject to the following condition: * The above copyright notice and either this complete permission notice or at * a minimum a reference to the UPL must be included in all copies or * substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -39,7 +39,10 @@ import * as React from 'react'; import { ServiceContext } from '@app/Shared/Services/Services'; import { NotificationCenter } from '@app/Notifications/NotificationCenter'; import { IAppRoute, routes } from '@app/routes'; -import { Nav, NavItem, NavList, Page, PageHeader, PageSidebar, SkipToContent } from '@patternfly/react-core'; +import { AboutModal, Button, Nav, NavItem, NavList, Page, PageHeader, + PageHeaderTools, PageHeaderToolsGroup, PageHeaderToolsItem, PageSidebar, + SkipToContent, Text, TextContent, TextList, TextListItem } from '@patternfly/react-core'; +import { HelpIcon } from '@patternfly/react-icons'; import { NavLink, matchPath, useLocation } from 'react-router-dom'; import { AuthModal } from './AuthModal'; import { SslErrorModal} from './SslErrorModal'; @@ -59,6 +62,8 @@ const AppLayout: React.FunctionComponent = ({children}) => { const [isNavOpenMobile, setIsNavOpenMobile] = React.useState(false); const [showAuthModal, setShowAuthModal] = React.useState(false); const [showSslErrorModal, setShowSslErrorModal] = React.useState(false); + const [aboutModalOpen, setAboutModalOpen] = React.useState(false); + const [cryostatVersion, setCryostatVersion] = React.useState('unknown'); const location = useLocation(); React.useEffect(() => { @@ -68,6 +73,11 @@ const AppLayout: React.FunctionComponent = ({children}) => { return () => sub.unsubscribe(); }, [context.target]); + React.useEffect(() => { + const sub = context.api.cryostatVersion().subscribe(setCryostatVersion); + return () => sub.unsubscribe(); + }) + const dismissAuthModal = () => { setShowAuthModal(false); }; @@ -95,15 +105,75 @@ const AppLayout: React.FunctionComponent = ({children}) => { const mobileOnSelect = (selected) => { if(isMobileView) setIsNavOpenMobile(false) }; - const Header = ( + const handleAboutModalToggle = () => { + setAboutModalOpen(!aboutModalOpen); + }; + const HeaderTools = (<> + + + +