Load server extension data in separate context to speed up loading time

This commit is contained in:
Aurora Lahtela 2022-08-31 18:06:08 +03:00
parent e772713ac0
commit 019a3353ca
4 changed files with 89 additions and 50 deletions

View File

@ -0,0 +1,30 @@
import {createContext, useContext, useEffect, useState} from "react";
import {useDataRequest} from "./dataFetchHook";
import {fetchExtensionData} from "../service/serverService";
import {useParams} from "react-router-dom";
const ServerExtensionContext = createContext({});
export const ServerExtensionContextProvider = ({children}) => {
const {identifier} = useParams();
const [extensionData, setExtensionData] = useState(undefined);
const [extensionDataLoadingError, setExtensionDataLoadingError] = useState(undefined);
const {data, loadingError} = useDataRequest(fetchExtensionData, [identifier]);
useEffect(() => {
setExtensionData(data);
setExtensionDataLoadingError(loadingError);
}, [data, loadingError, setExtensionData, setExtensionDataLoadingError])
const sharedState = {extensionData, extensionDataLoadingError}
return (<ServerExtensionContext.Provider value={sharedState}>
{children}
</ServerExtensionContext.Provider>
)
}
export const useServerExtensionContext = () => {
return useContext(ServerExtensionContext);
}

View File

@ -1,6 +1,6 @@
import React, {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {Outlet, useOutletContext, useParams} from "react-router-dom"; import {Outlet, useParams} from "react-router-dom";
import {useNavigation} from "../../hooks/navigationHook"; import {useNavigation} from "../../hooks/navigationHook";
import { import {
faCampground, faCampground,
@ -25,27 +25,19 @@ import ErrorPage from "./ErrorPage";
import {SwitchTransition} from "react-transition-group"; import {SwitchTransition} from "react-transition-group";
import MainPageRedirect from "../../components/navigation/MainPageRedirect"; import MainPageRedirect from "../../components/navigation/MainPageRedirect";
import {useDataRequest} from "../../hooks/dataFetchHook"; import {useDataRequest} from "../../hooks/dataFetchHook";
import {fetchExtensionData, fetchServerIdentity} from "../../service/serverService"; import {fetchServerIdentity} from "../../service/serverService";
import ExtensionIcon from "../../components/extensions/ExtensionIcon"; import ExtensionIcon from "../../components/extensions/ExtensionIcon";
import {ServerExtensionContextProvider, useServerExtensionContext} from "../../hooks/serverExtensionDataContext";
const ServerPage = () => { const ServerSidebar = () => {
const {t, i18n} = useTranslation(); const {t, i18n} = useTranslation();
const {identifier} = useParams();
const {isProxy, serverName} = useMetadata();
const {
data: serverIdentity,
loadingError: identityLoadingError
} = useDataRequest(fetchServerIdentity, [identifier]);
const {
data: extensionData,
loadingError: extensionDataLoadingError
} = useDataRequest(fetchExtensionData, [identifier]);
const [error] = useState(undefined);
const [sidebarItems, setSidebarItems] = useState([]); const [sidebarItems, setSidebarItems] = useState([]);
const {extensionData} = useServerExtensionContext();
const {authRequired, loggedIn, user} = useAuth();
const {currentTab} = useNavigation(); const {isProxy} = useMetadata();
const showBackButton = isProxy
&& (!authRequired || (loggedIn && user.permissions.filter(perm => perm !== 'page.network').length));
useEffect(() => { useEffect(() => {
const items = [ const items = [
@ -84,10 +76,10 @@ const ServerPage = () => {
{name: 'html.label.performance', icon: faCogs, href: "performance"}, {name: 'html.label.performance', icon: faCogs, href: "performance"},
{}, {},
{name: 'html.label.plugins'}, {name: 'html.label.plugins'},
{name: 'html.label.pluginsOverview', icon: faCubes, href: "plugins-overview"}
] ]
if (extensionData) { if (extensionData) {
items.push({name: 'html.label.pluginsOverview', icon: faCubes, href: "plugins-overview"})
extensionData.extensions.filter(extension => extension.wide) extensionData.extensions.filter(extension => extension.wide)
.map(extension => extension.extensionInformation) .map(extension => extension.extensionInformation)
.map(info => { .map(info => {
@ -109,12 +101,27 @@ const ServerPage = () => {
window.document.title = `Plan | Server Analysis`; window.document.title = `Plan | Server Analysis`;
}, [t, i18n, extensionData]) }, [t, i18n, extensionData])
const {authRequired, loggedIn, user} = useAuth(); return (
<Sidebar items={sidebarItems} showBackButton={showBackButton}/>
)
}
const ServerPage = () => {
const {t} = useTranslation();
const {identifier} = useParams();
const {isProxy, serverName} = useMetadata();
const {
data: serverIdentity,
loadingError: identityLoadingError
} = useDataRequest(fetchServerIdentity, [identifier]);
const [error] = useState(undefined);
const {currentTab} = useNavigation();
const {authRequired, loggedIn} = useAuth();
if (authRequired && !loggedIn) return <MainPageRedirect/> if (authRequired && !loggedIn) return <MainPageRedirect/>
const showBackButton = isProxy && (!authRequired || user.permissions.filter(perm => perm !== 'page.network').length);
const getDisplayedServerName = () => { const getDisplayedServerName = () => {
if (serverIdentity) { if (serverIdentity) {
return serverIdentity.serverName; return serverIdentity.serverName;
@ -134,34 +141,28 @@ const ServerPage = () => {
error={{title: t('html.error.404NotFound'), message: t('html.error.serverNotSeen')}}/> error={{title: t('html.error.404NotFound'), message: t('html.error.serverNotSeen')}}/>
return <ErrorPage error={identityLoadingError}/> return <ErrorPage error={identityLoadingError}/>
} }
if (extensionDataLoadingError) {
return <ErrorPage error={extensionDataLoadingError}/>
}
if (!extensionData) return <></>
return ( return (
<> <>
<NightModeCss/> <NightModeCss/>
<Sidebar items={sidebarItems} showBackButton={showBackButton}/> <ServerExtensionContextProvider>
<div className="d-flex flex-column" id="content-wrapper"> <ServerSidebar/>
<Header page={displayedServerName} tab={currentTab}/> <div className="d-flex flex-column" id="content-wrapper">
<div id="content" style={{display: 'flex'}}> <Header page={displayedServerName} tab={currentTab}/>
<main className="container-fluid mt-4"> <div id="content" style={{display: 'flex'}}>
<SwitchTransition> <main className="container-fluid mt-4">
<Outlet context={extensionData}/> <SwitchTransition>
</SwitchTransition> <Outlet/>
</main> </SwitchTransition>
<aside> </main>
<ColorSelectorModal/> <aside>
</aside> <ColorSelectorModal/>
</aside>
</div>
</div> </div>
</div> </ServerExtensionContextProvider>
</> </>
) )
} }
export const useServer = () => {
return useOutletContext();
}
export default ServerPage; export default ServerPage;

View File

@ -1,13 +1,16 @@
import React, {useEffect} from 'react'; import React, {useEffect} from 'react';
import {useServer} from "../layout/ServerPage";
import Masonry from "masonry-layout"; import Masonry from "masonry-layout";
import LoadIn from "../../components/animation/LoadIn"; import LoadIn from "../../components/animation/LoadIn";
import {Card, Col, Row} from "react-bootstrap-v5"; import {Card, Col, Row} from "react-bootstrap-v5";
import ExtensionCard, {ExtensionCardWrapper} from "../../components/extensions/ExtensionCard"; import ExtensionCard, {ExtensionCardWrapper} from "../../components/extensions/ExtensionCard";
import Loader from "../../components/navigation/Loader";
import {useTranslation} from "react-i18next";
import {useServerExtensionContext} from "../../hooks/serverExtensionDataContext";
import ErrorView from "../ErrorView";
const ServerPluginData = () => { const ServerPluginData = () => {
const extensionData = useServer(); const {t} = useTranslation();
console.log(extensionData); const {extensionData, extensionDataLoadingError} = useServerExtensionContext();
const extensions = extensionData ? extensionData.extensions.filter(extension => !extension.wide) : []; const extensions = extensionData ? extensionData.extensions.filter(extension => !extension.wide) : [];
useEffect(() => { useEffect(() => {
@ -23,6 +26,8 @@ const ServerPluginData = () => {
} }
}, []) }, [])
if (extensionDataLoadingError) return <ErrorView error={extensionDataLoadingError}/>;
if (!extensions || !extensions.length) { if (!extensions || !extensions.length) {
return ( return (
<LoadIn> <LoadIn>
@ -31,7 +36,7 @@ const ServerPluginData = () => {
<Col md={12}> <Col md={12}>
<Card> <Card>
<Card.Body> <Card.Body>
<p>No Extension data</p> <p>{extensionData ? t('html.text.noExtensionData') : <Loader/>}</p>
</Card.Body> </Card.Body>
</Card> </Card>
</Col> </Col>

View File

@ -1,14 +1,17 @@
import React from 'react'; import React from 'react';
import {useServer} from "../layout/ServerPage";
import ErrorView from "../ErrorView"; import ErrorView from "../ErrorView";
import LoadIn from "../../components/animation/LoadIn"; import LoadIn from "../../components/animation/LoadIn";
import {Card, Col, Row} from "react-bootstrap-v5"; import {Card, Col, Row} from "react-bootstrap-v5";
import ExtensionCard from "../../components/extensions/ExtensionCard"; import ExtensionCard from "../../components/extensions/ExtensionCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useTranslation} from "react-i18next";
import Loader from "../../components/navigation/Loader";
import {useServerExtensionContext} from "../../hooks/serverExtensionDataContext";
const ServerWidePluginData = () => { const ServerWidePluginData = () => {
const {t} = useTranslation();
const {plugin} = useParams(); const {plugin} = useParams();
const {extensionData, extensionDataLoadingError} = useServer(); const {extensionData, extensionDataLoadingError} = useServerExtensionContext();
if (extensionDataLoadingError) return <ErrorView error={extensionDataLoadingError}/>; if (extensionDataLoadingError) return <ErrorView error={extensionDataLoadingError}/>;
@ -22,7 +25,7 @@ const ServerWidePluginData = () => {
<Col md={12}> <Col md={12}>
<Card> <Card>
<Card.Body> <Card.Body>
<p>No Extension data</p> <p>{extensionData ? t('html.text.noExtensionData') : <Loader/>}</p>
</Card.Body> </Card.Body>
</Card> </Card>
</Col> </Col>