diff --git a/ui/webui/src/components/AnacondaAboutModal.jsx b/ui/webui/src/components/AnacondaAboutModal.jsx new file mode 100644 index 000000000000..278d6177fc0a --- /dev/null +++ b/ui/webui/src/components/AnacondaAboutModal.jsx @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; + +import React, { useState, useEffect } from "react"; +import { + AboutModal, + Button, + Flex, + TextContent, + TextList, + TextListItem, +} from "@patternfly/react-core"; +import { ExternalLinkAltIcon } from "@patternfly/react-icons"; + +import { read_os_release as readOsRelease } from "os-release.js"; +import { getAnacondaVersion } from "../helpers/product"; + +const _ = cockpit.gettext; + +const AboutModalVersions = ({ anacondaVersion }) => { + const arr = [["Anaconda", anacondaVersion], ["Blivet", "XXX"], ["Pykickstart", "XXX"], ["Python", "XXX"]]; + + return ( + <> + +

{_("Powered by Anaconda")}

+
+ + + + {arr.map((item) => ( + + {item[0]} + {item[1]} + + ))} + + + + ); +}; + +export const AnacondaAboutModal = ({ isModalOpen, setIsAboutModalOpen }) => { + const toggleModal = () => { + setIsAboutModalOpen(!isModalOpen); + }; + + const [anacondaVersion, setAnacondaVersion] = useState(""); + const [prettyName, setPrettyName] = useState(""); + useEffect(() => { + getAnacondaVersion().then(content => setAnacondaVersion(content)); + readOsRelease().then(osRelease => setPrettyName(osRelease.PRETTY_NAME)); + }, []); + + return ( + <> + + + + + + + + + ); +}; diff --git a/ui/webui/src/components/AnacondaHeader.jsx b/ui/webui/src/components/AnacondaHeader.jsx index 5d900bc8f233..8361d5bfb9a9 100644 --- a/ui/webui/src/components/AnacondaHeader.jsx +++ b/ui/webui/src/components/AnacondaHeader.jsx @@ -26,6 +26,7 @@ import { TextContent, Text, TextVariants } from "@patternfly/react-core"; import { InfoCircleIcon } from "@patternfly/react-icons"; +import { HeaderKebab } from "./HeaderKebab"; const _ = cockpit.gettext; @@ -66,6 +67,7 @@ export const AnacondaHeader = ({ beta, title }) => { {title} {betanag} + ); diff --git a/ui/webui/src/components/HeaderKebab.jsx b/ui/webui/src/components/HeaderKebab.jsx new file mode 100644 index 000000000000..593f581e1ed5 --- /dev/null +++ b/ui/webui/src/components/HeaderKebab.jsx @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import React, { useState } from "react"; +import { Dropdown, DropdownItem, DropdownPosition, KebabToggle } from "@patternfly/react-core"; +import { AnacondaAboutModal } from "./AnacondaAboutModal"; + +export const HeaderKebab = () => { + const [isOpen, setIsOpen] = useState(false); + const [isAboutModalOpen, setIsAboutModalOpen] = useState(false); + + const onToggle = isOpen => { + setIsOpen(isOpen); + }; + const onFocus = () => { + const element = document.getElementById("toggle-kebab"); + element.focus(); + }; + const onSelect = () => { + setIsOpen(false); + onFocus(); + }; + + const handleAboutModal = () => { + setIsAboutModalOpen(true); + }; + + const dropdownItems = [ + + About + , + ]; + return ( + <> + + } + isOpen={isOpen} + isPlain + dropdownItems={dropdownItems} + /> + {isAboutModalOpen && + } + + + ); +}; diff --git a/ui/webui/src/components/aboutmodal.scss b/ui/webui/src/components/aboutmodal.scss new file mode 100644 index 000000000000..1e107e569564 --- /dev/null +++ b/ui/webui/src/components/aboutmodal.scss @@ -0,0 +1,53 @@ +@import "global-variables"; + +.pf-c-about-modal-box__strapline { + padding-top: 0; + } + + /* Scale down the about box to be a little smaller */ + @media only screen and (min-width: 992px) { + .pf-c-about-modal-box { + --pf-c-about-modal-box--lg--MaxWidth: 62rem; + --pf-c-about-modal-box--lg--MaxHeight: 38rem; + grid-template-rows: 3rem max-content auto; + grid-template-columns: 1fr 0fr; + } + } + + /* Hide the logo and side graphic */ + .pf-c-about-modal-box__brand, + .pf-c-about-modal-box__hero { + display: none; + } + + /* Make the close button more obvious, since we hide the side graphic*/ + .pf-c-about-modal-box__close .pf-c-button.pf-m-plain { + --pf-c-about-modal-box__close--c-button--BackgroundColor: var(--pf-global--BackgroundColor--dark-200); + position: absolute; + } + .pf-c-about-modal-box__close .pf-c-button.pf-m-plain:hover { + --pf-c-about-modal-box__close--c-button--BackgroundColor: var(--pf-global--BackgroundColor--dark-400); + } + + #about-modal-flex{ + position: static; + margin-top: 10rem; + } + + .pf-c-about-modal-box__content { + margin-top: 0; + } + + #anaconda-page-button { + padding-left: 0; + } + + #subtitle { + margin-bottom: 48px; + } + + #about-modal-content { + font-size: large; + } + + \ No newline at end of file diff --git a/ui/webui/src/helpers/product.js b/ui/webui/src/helpers/product.js new file mode 100644 index 000000000000..101aed4d696e --- /dev/null +++ b/ui/webui/src/helpers/product.js @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with This program; If not, see . + */ +import cockpit from "cockpit"; + +export const getAnacondaVersion = () => { + return cockpit.spawn(["anaconda", "--version"]) + .then(content => content.split(" ").slice(-1)[0].replace("\n", "")) + .then(content => { return content }); +}; diff --git a/ui/webui/src/index.js b/ui/webui/src/index.js index 18cafa5aa3e4..0c2e645ea031 100644 --- a/ui/webui/src/index.js +++ b/ui/webui/src/index.js @@ -32,6 +32,7 @@ import cockpit from "cockpit"; */ import "../pkg/lib/patternfly/patternfly-4-overrides.scss"; import "./components/app.scss"; +import "./components/aboutmodal.scss"; document.addEventListener("DOMContentLoaded", function () { const root = createRoot(document.getElementById("app"));