diff --git a/striker-ui/components/Display/Preview.tsx b/striker-ui/components/Display/Preview.tsx index f505e5b5..4afef796 100644 --- a/striker-ui/components/Display/Preview.tsx +++ b/striker-ui/components/Display/Preview.tsx @@ -5,6 +5,7 @@ import { PowerOffOutlined as PowerOffOutlinedIcon, } from '@mui/icons-material'; +import API_BASE_URL from '../../lib/consts/API_BASE_URL'; import { BORDER_RADIUS, GREY } from '../../lib/consts/DEFAULT_THEME'; import IconButton from '../IconButton'; @@ -12,6 +13,8 @@ import { InnerPanel, InnerPanelHeader, Panel, PanelHeader } from '../Panels'; import { BodyText, HeaderText } from '../Text'; type PreviewOptionalProps = { + externalPreview?: string; + isFetchScreenshot?: boolean; isShowControls?: boolean; isUseInnerPanel?: boolean; setMode?: Dispatch> | null; @@ -23,6 +26,8 @@ type PreviewProps = PreviewOptionalProps & { }; const PREVIEW_DEFAULT_PROPS: Required = { + externalPreview: '', + isFetchScreenshot: true, isShowControls: true, isUseInnerPanel: false, setMode: null, @@ -56,33 +61,37 @@ const PreviewPanelHeader: FC<{ isUseInnerPanel: boolean; text: string }> = ({ ); const Preview: FC = ({ + externalPreview = PREVIEW_DEFAULT_PROPS.externalPreview, + isFetchScreenshot = PREVIEW_DEFAULT_PROPS.isFetchScreenshot, isShowControls = PREVIEW_DEFAULT_PROPS.isShowControls, isUseInnerPanel = PREVIEW_DEFAULT_PROPS.isUseInnerPanel, serverName, setMode, uuid, }) => { - const [preview, setPreview] = useState(); + const [preview, setPreview] = useState(''); useEffect(() => { - (async () => { - try { - const res = await fetch( - `${process.env.NEXT_PUBLIC_API_URL}/get_server_screenshot?server_uuid=${uuid}`, - { + if (isFetchScreenshot) { + (async () => { + try { + const response = await fetch(`${API_BASE_URL}/server/${uuid}?ss`, { method: 'GET', headers: { 'Content-Type': 'application/json', }, - }, - ); - const { screenshot } = await res.json(); - setPreview(screenshot); - } catch { - setPreview(''); - } - })(); - }, [uuid]); + }); + const { screenshot: fetchedScreenshot } = await response.json(); + + setPreview(fetchedScreenshot); + } catch { + setPreview(''); + } + })(); + } else if (externalPreview) { + setPreview(externalPreview); + } + }, [externalPreview, isFetchScreenshot, uuid]); return ( diff --git a/striker-ui/pages/index.tsx b/striker-ui/pages/index.tsx index 98891276..103439b7 100644 --- a/striker-ui/pages/index.tsx +++ b/striker-ui/pages/index.tsx @@ -11,8 +11,14 @@ import OutlinedInput from '../components/OutlinedInput'; import { Panel, PanelHeader } from '../components/Panels'; import periodicFetch from '../lib/fetchers/periodicFetch'; import Spinner from '../components/Spinner'; +import fetchJSON from '../lib/fetchers/fetchJSON'; -const createServerPreviewContainer = (servers: ServerOverviewMetadata[]) => ( +type ServerListItem = ServerOverviewMetadata & { + isScreenshotStale?: boolean; + screenshot: string; +}; + +const createServerPreviewContainer = (servers: ServerListItem[]) => ( ( '& > *': { width: { xs: '20em', md: '30em' }, }, + + '& > :not(:last-child)': { + marginRight: '2em', + }, }} > - {servers.map(({ serverName, serverUUID }) => ( + {servers.map(({ screenshot, serverName, serverUUID }) => ( @@ -36,18 +48,15 @@ const createServerPreviewContainer = (servers: ServerOverviewMetadata[]) => ( ); -const filterServers = ( - allServers: ServerOverviewMetadata[], - searchTerm: string, -) => +const filterServers = (allServers: ServerListItem[], searchTerm: string) => searchTerm === '' ? { exclude: allServers, include: [], } : allServers.reduce<{ - exclude: ServerOverviewMetadata[]; - include: ServerOverviewMetadata[]; + exclude: ServerListItem[]; + include: ServerListItem[]; }>( (reduceContainer, server) => { const { serverName } = server; @@ -64,13 +73,9 @@ const filterServers = ( ); const Dashboard: FC = () => { - const [allServers, setAllServers] = useState([]); - const [excludeServers, setExcludeServers] = useState< - ServerOverviewMetadata[] - >([]); - const [includeServers, setIncludeServers] = useState< - ServerOverviewMetadata[] - >([]); + const [allServers, setAllServers] = useState([]); + const [excludeServers, setExcludeServers] = useState([]); + const [includeServers, setIncludeServers] = useState([]); const [inputSearchTerm, setInputSearchTerm] = useState(''); @@ -83,13 +88,42 @@ const Dashboard: FC = () => { setIncludeServers(include); }; - const { isLoading } = periodicFetch( + const { isLoading } = periodicFetch( `${API_BASE_URL}/server`, { onSuccess: (data = []) => { - setAllServers(data); - - updateServerList(data, inputSearchTerm); + const serverListItems: ServerListItem[] = ( + data as ServerOverviewMetadata[] + ).map((serverOverview) => { + const { serverUUID } = serverOverview; + const previousScreenshot: string = + allServers.find(({ serverUUID: uuid }) => uuid === serverUUID) + ?.screenshot || ''; + const item: ServerListItem = { + ...serverOverview, + screenshot: previousScreenshot, + }; + + fetchJSON<{ screenshot: string }>( + `${API_BASE_URL}/server/${serverUUID}?ss`, + ) + .then(({ screenshot }) => { + item.screenshot = screenshot; + + const allServersWithScreenshots = [...serverListItems]; + + setAllServers(allServersWithScreenshots); + updateServerList(allServersWithScreenshots, inputSearchTerm); + }) + .catch(() => { + item.isScreenshotStale = true; + }); + + return item; + }); + + setAllServers(serverListItems); + updateServerList(serverListItems, inputSearchTerm); }, refreshInterval: 60000, }, @@ -111,7 +145,6 @@ const Dashboard: FC = () => { placeholder="Search by server name" onChange={({ target: { value } }) => { setInputSearchTerm(value); - updateServerList(allServers, value); }} value={inputSearchTerm}