fix(striker-ui): render async server screenshots

main
Tsu-ba-me 3 years ago
parent 4c4ce1834b
commit e06281bce0
  1. 39
      striker-ui/components/Display/Preview.tsx
  2. 73
      striker-ui/pages/index.tsx

@ -5,6 +5,7 @@ import {
PowerOffOutlined as PowerOffOutlinedIcon, PowerOffOutlined as PowerOffOutlinedIcon,
} from '@mui/icons-material'; } from '@mui/icons-material';
import API_BASE_URL from '../../lib/consts/API_BASE_URL';
import { BORDER_RADIUS, GREY } from '../../lib/consts/DEFAULT_THEME'; import { BORDER_RADIUS, GREY } from '../../lib/consts/DEFAULT_THEME';
import IconButton from '../IconButton'; import IconButton from '../IconButton';
@ -12,6 +13,8 @@ import { InnerPanel, InnerPanelHeader, Panel, PanelHeader } from '../Panels';
import { BodyText, HeaderText } from '../Text'; import { BodyText, HeaderText } from '../Text';
type PreviewOptionalProps = { type PreviewOptionalProps = {
externalPreview?: string;
isFetchScreenshot?: boolean;
isShowControls?: boolean; isShowControls?: boolean;
isUseInnerPanel?: boolean; isUseInnerPanel?: boolean;
setMode?: Dispatch<SetStateAction<boolean>> | null; setMode?: Dispatch<SetStateAction<boolean>> | null;
@ -23,6 +26,8 @@ type PreviewProps = PreviewOptionalProps & {
}; };
const PREVIEW_DEFAULT_PROPS: Required<PreviewOptionalProps> = { const PREVIEW_DEFAULT_PROPS: Required<PreviewOptionalProps> = {
externalPreview: '',
isFetchScreenshot: true,
isShowControls: true, isShowControls: true,
isUseInnerPanel: false, isUseInnerPanel: false,
setMode: null, setMode: null,
@ -56,33 +61,37 @@ const PreviewPanelHeader: FC<{ isUseInnerPanel: boolean; text: string }> = ({
); );
const Preview: FC<PreviewProps> = ({ const Preview: FC<PreviewProps> = ({
externalPreview = PREVIEW_DEFAULT_PROPS.externalPreview,
isFetchScreenshot = PREVIEW_DEFAULT_PROPS.isFetchScreenshot,
isShowControls = PREVIEW_DEFAULT_PROPS.isShowControls, isShowControls = PREVIEW_DEFAULT_PROPS.isShowControls,
isUseInnerPanel = PREVIEW_DEFAULT_PROPS.isUseInnerPanel, isUseInnerPanel = PREVIEW_DEFAULT_PROPS.isUseInnerPanel,
serverName, serverName,
setMode, setMode,
uuid, uuid,
}) => { }) => {
const [preview, setPreview] = useState<string>(); const [preview, setPreview] = useState<string>('');
useEffect(() => { useEffect(() => {
(async () => { if (isFetchScreenshot) {
try { (async () => {
const res = await fetch( try {
`${process.env.NEXT_PUBLIC_API_URL}/get_server_screenshot?server_uuid=${uuid}`, const response = await fetch(`${API_BASE_URL}/server/${uuid}?ss`, {
{
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}, });
); const { screenshot: fetchedScreenshot } = await response.json();
const { screenshot } = await res.json();
setPreview(screenshot); setPreview(fetchedScreenshot);
} catch { } catch {
setPreview(''); setPreview('');
} }
})(); })();
}, [uuid]); } else if (externalPreview) {
setPreview(externalPreview);
}
}, [externalPreview, isFetchScreenshot, uuid]);
return ( return (
<PreviewPanel isUseInnerPanel={isUseInnerPanel}> <PreviewPanel isUseInnerPanel={isUseInnerPanel}>

@ -11,8 +11,14 @@ import OutlinedInput from '../components/OutlinedInput';
import { Panel, PanelHeader } from '../components/Panels'; import { Panel, PanelHeader } from '../components/Panels';
import periodicFetch from '../lib/fetchers/periodicFetch'; import periodicFetch from '../lib/fetchers/periodicFetch';
import Spinner from '../components/Spinner'; 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[]) => (
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
@ -22,13 +28,19 @@ const createServerPreviewContainer = (servers: ServerOverviewMetadata[]) => (
'& > *': { '& > *': {
width: { xs: '20em', md: '30em' }, width: { xs: '20em', md: '30em' },
}, },
'& > :not(:last-child)': {
marginRight: '2em',
},
}} }}
> >
{servers.map(({ serverName, serverUUID }) => ( {servers.map(({ screenshot, serverName, serverUUID }) => (
<Preview <Preview
key={`server-preview-${serverUUID}`} key={`server-preview-${serverUUID}`}
isFetchScreenshot={false}
isShowControls={false} isShowControls={false}
isUseInnerPanel isUseInnerPanel
externalPreview={screenshot}
serverName={serverName} serverName={serverName}
uuid={serverUUID} uuid={serverUUID}
/> />
@ -36,18 +48,15 @@ const createServerPreviewContainer = (servers: ServerOverviewMetadata[]) => (
</Box> </Box>
); );
const filterServers = ( const filterServers = (allServers: ServerListItem[], searchTerm: string) =>
allServers: ServerOverviewMetadata[],
searchTerm: string,
) =>
searchTerm === '' searchTerm === ''
? { ? {
exclude: allServers, exclude: allServers,
include: [], include: [],
} }
: allServers.reduce<{ : allServers.reduce<{
exclude: ServerOverviewMetadata[]; exclude: ServerListItem[];
include: ServerOverviewMetadata[]; include: ServerListItem[];
}>( }>(
(reduceContainer, server) => { (reduceContainer, server) => {
const { serverName } = server; const { serverName } = server;
@ -64,13 +73,9 @@ const filterServers = (
); );
const Dashboard: FC = () => { const Dashboard: FC = () => {
const [allServers, setAllServers] = useState<ServerOverviewMetadata[]>([]); const [allServers, setAllServers] = useState<ServerListItem[]>([]);
const [excludeServers, setExcludeServers] = useState< const [excludeServers, setExcludeServers] = useState<ServerListItem[]>([]);
ServerOverviewMetadata[] const [includeServers, setIncludeServers] = useState<ServerListItem[]>([]);
>([]);
const [includeServers, setIncludeServers] = useState<
ServerOverviewMetadata[]
>([]);
const [inputSearchTerm, setInputSearchTerm] = useState<string>(''); const [inputSearchTerm, setInputSearchTerm] = useState<string>('');
@ -83,13 +88,42 @@ const Dashboard: FC = () => {
setIncludeServers(include); setIncludeServers(include);
}; };
const { isLoading } = periodicFetch<ServerOverviewMetadata[]>( const { isLoading } = periodicFetch<ServerListItem[]>(
`${API_BASE_URL}/server`, `${API_BASE_URL}/server`,
{ {
onSuccess: (data = []) => { onSuccess: (data = []) => {
setAllServers(data); const serverListItems: ServerListItem[] = (
data as ServerOverviewMetadata[]
updateServerList(data, inputSearchTerm); ).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, refreshInterval: 60000,
}, },
@ -111,7 +145,6 @@ const Dashboard: FC = () => {
placeholder="Search by server name" placeholder="Search by server name"
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
setInputSearchTerm(value); setInputSearchTerm(value);
updateServerList(allServers, value); updateServerList(allServers, value);
}} }}
value={inputSearchTerm} value={inputSearchTerm}

Loading…
Cancel
Save