import React, {useEffect, useRef, useState} from 'react'; import FormControl from "@material-ui/core/FormControl"; import {makeStyles} from "@material-ui/core/styles"; import AppBar from "@material-ui/core/AppBar"; import Toolbar from "@material-ui/core/Toolbar"; import Typography from "@material-ui/core/Typography"; import Autocomplete from '@material-ui/lab/Autocomplete'; import TextField from "@material-ui/core/TextField"; import Grid from "@material-ui/core/Grid"; import {BugReport, Close, Folder, Launch, MoodBadTwoTone, Settings} from "@material-ui/icons"; import Alert from "@material-ui/lab/Alert"; import {Card, CircularProgress} from "@material-ui/core"; import Avatar from "@material-ui/core/Avatar"; import CardHeader from "@material-ui/core/CardHeader"; import Button from "@material-ui/core/Button"; import createMuiTheme from "@material-ui/core/styles/createMuiTheme"; import {ThemeProvider} from "@material-ui/styles"; import Popper from "@material-ui/core/Popper"; import CardContent from "@material-ui/core/CardContent"; import IconButton from "@material-ui/core/IconButton"; import Select from "@material-ui/core/Select"; import MenuItem from "@material-ui/core/MenuItem"; import InputLabel from "@material-ui/core/InputLabel"; import whiteIcon from './whiteicon.png'; import blueIcon from './blueicon.png'; import Console from "./components/Console"; const useStyles = makeStyles(theme => ({ formControl: { margin: theme.spacing(1), color: '#fff', flexGrow: 1, }, selectEmpty: { marginTop: theme.spacing(2), }, title: { flexGrow: 1, "& small": { fontSize: 12, opacity: 0.7, verticalAlign: "text-top" } }, cardHeaderTitle: { minWidth: 10 }, inputRoot: { color: "white", "& .MuiOutlinedInput-notchedOutline": { borderColor: "white" }, "&:hover .MuiOutlinedInput-notchedOutline": { borderColor: "white" }, "&.Mui-focused .MuiOutlinedInput-notchedOutline": { borderColor: "white" }, }, endAdornment: { "& .MuiButtonBase-root": { color: "white" } }, inputLabelRoot: { color: "white" } })); const theme = createMuiTheme({ palette: { primary: {main: "rgb(50,109,230)"}, secondary: {main: "#ccc"} }, }); function usePrevious(value) { const ref = useRef(); useEffect(() => { ref.current = value; }); return ref.current; } function App() { const classes = useStyles(); const [namespaces, setNamespaces] = useState([]); const [selectedNamespaces, setSelectedNS] = useState([]); const [anchorEl, setAnchorEl] = useState(null); const prevSelectedNamespaces = usePrevious(selectedNamespaces); const [configFilePath, setConfigFilePath] = useState(null) const confPathEl = useRef(null) const [loading, setLoading] = useState(true); const [websites, setWebsites] = useState([]); const [showConfig, setShowConfig] = useState(false); const [configMessage, setConfigMessage] = useState(null); const [availableContexts, setAvailableContexts] = useState([]); const [currentContext, setCurrentContext] = useState(null); const [version, setVersion] = useState(null); const [showConsole, setShowConsole] = useState(false); // const prevContext = usePrevious(currentContext); console.log() useEffect(() => { window.backend.Client.GetCurrentConfigPath().then(cp => { if (cp) { setConfigFilePath(cp); refreshContext(); } else { Promise.all([window.backend.Client.GetAvailableContexts(), window.backend.Client.GetCurrentContext()]).then(([acs, cc]) => { console.log("current context", cc, ", available:", acs); setAvailableContexts(acs); setCurrentContext(cc); }); } }); window.backend.PortfallOS.GetVersion().then(v => { setVersion(v); }) }, []); const refreshContext = () => { setWebsites([]); setLoading(true); window.backend.Client.ListNamespaces().then((r) => { setNamespaces(r); setSelectedNS(["default"]); setLoading(false) }); Promise.all([window.backend.Client.GetAvailableContexts(), window.backend.Client.GetCurrentContext()]).then(([acs, cc]) => { console.log("current context", cc, ", available:", acs); setAvailableContexts(acs); setCurrentContext(cc); }); } useEffect(() => { if (selectedNamespaces !== null && prevSelectedNamespaces !== selectedNamespaces) { setLoading(true); // get ns to add const nsToAdd = selectedNamespaces.find(ns => !(prevSelectedNamespaces || []).includes(ns)); const namespacesToRemove = (prevSelectedNamespaces || []).filter(ns => !selectedNamespaces.includes(ns)); let newWebsites = websites; if (namespacesToRemove) { Promise.all(namespacesToRemove.map(ns => window.backend.Client.RemoveWebsitesInNamespace(ns))).then(() => { console.log("removed namespaces", namespacesToRemove) }); newWebsites = websites.filter(w => { if (namespacesToRemove.includes(w.namespace)) { return false } if (namespacesToRemove.includes("All Namespaces") && !selectedNamespaces.includes(w.namespace)) { return false } return true }); } if (nsToAdd) { console.log("adding ns", nsToAdd) window.backend.Client.GetWebsitesInNamespace(nsToAdd).then(results => { console.log("received websites in ns to add", results) // when we already have all namespaces there is no need to concat the results of the given website if (results && !(prevSelectedNamespaces || []).includes("All Namespaces")) { const resObj = JSON.parse(results) if (resObj) { newWebsites = newWebsites.concat(resObj); } } // if we just added All namespaces the portforwards will be reset so we sh setWebsites(newWebsites); setLoading(false); }); } else { setWebsites(newWebsites); setLoading(false) } } }, [selectedNamespaces, prevSelectedNamespaces, websites]); return ( Blue Portfall logo in background
White Portfall logo in toolbar Portfall {version ? {version} : null} {/* todo: arrange by namespace */} { // setSelectedNS(value) }} renderInput={params => ( ) }/>
{!configFilePath ? ( } severity="error"> No config file found ) : null} {(configFilePath && websites.length === 0 && namespaces.length) ? ( } severity="info"> No websites found to port-forward in the selected namespace(s) ) : null} {(configFilePath && !namespaces.length) ? ( } severity="warning"> Invalid context, try updating your config or switching context ) : null} {websites.map(({localPort, podPort, title, iconRemoteUrl}) => ( } title={{title}} subheader={{localPort}:{podPort}} action={ }/> ))} {loading ? : null}
{ setShowConsole(!showConsole); setAnchorEl(e.currentTarget); setShowConfig(false); }} > { setAnchorEl(e.currentTarget); setShowConfig(!showConfig) setShowConsole(false); }} > setShowConsole(false)} disablePortal={false} modifiers={{ flip: { enabled: true, }, arrow: { enabled: false, // element: arrowRef, }, }}> setShowConsole(false)}>}/> setShowConfig(false)} disablePortal={false} modifiers={{ flip: { enabled: true, }, arrow: { enabled: false, // element: arrowRef, }, }}> setShowConfig(false)}>}/> {(availableContexts && currentContext) ? Config context : null} {configMessage ? ( { setConfigMessage(null) }}> {configMessage.message} ) : null}
); } export default App;