load routes, show spinner, load not exported on demand, refactored scroll to anchor

This commit is contained in:
Annika Hannig 2022-07-20 16:36:20 +02:00
parent b230411b37
commit 462938db68
6 changed files with 135 additions and 32 deletions

View File

@ -0,0 +1,20 @@
import { useEffect }
from 'react';
import { useLocation }
from 'react-router-dom';
/**
* ScrollToAnchor effect
*/
export const useScrollToAnchor = (refs) => {
const { hash } = useLocation();
useEffect(() => {
const ref = refs[hash];
if (ref?.current) {
ref.current.scrollIntoView();
}
}, [refs, hash]);
}

View File

@ -1,10 +1,6 @@
import { useLocation }
from 'react-router-dom';
import { useRef
, useMemo
, useEffect
}
from 'react';
@ -13,6 +9,9 @@ import { useQuery }
import { useNeighbors }
from 'app/context/neighbors';
import { useScrollToAnchor }
from 'app/components/navigation/hash';
import NeighborsTable
from 'app/components/neighbors/NeighborsTable';
import LoadingIndicator
@ -67,7 +66,6 @@ const filterNeighbors = (protocols, filter) => {
const Neighbors = () => {
const { hash } = useLocation();
const [ query ] = useQuery();
const filter = query.q;
@ -103,20 +101,10 @@ const Neighbors = () => {
}, [filtered]);
// Scroll to anchor
useEffect(() => {
if (hash === "#sessions-down") {
if (!refDown.current) {
return;
}
refDown.current.scrollIntoView();
}
if (hash === "#sessions-up") {
if (!refUp.current) {
return;
}
refUp.current.scrollIntoView();
}
}, [hash, refDown, refUp, filtered]);
useScrollToAnchor({
"#sessions-down": refDown,
"#sessions-up": refUp,
})
if (isLoading) {
return <LoadingIndicator show={true} />;

View File

@ -1,7 +1,19 @@
import { useRef }
import { useRef
, useEffect
, useMemo
}
from 'react';
import { Link
}
from 'react-router-dom';
import { useConfig }
from 'app/context/config';
import { useQuery
, useQueryLink
}
from 'app/context/query';
import { ROUTES_RECEIVED
, ROUTES_FILTERED
, ROUTES_NOT_EXPORTED
@ -12,6 +24,9 @@ import { ROUTES_RECEIVED
}
from 'app/context/routes';
import { useScrollToAnchor }
from 'app/components/navigation/hash';
import QuickLinks
from 'app/components/routes/QuickLinks';
import EmptyResults
@ -22,9 +37,13 @@ import Paginator
from 'app/components/pagination/Paginator';
import PaginationInfo
from 'app/components/pagination/PaginationInfo';
import LoadingIndicator
from 'app/components/spinners/LoadingIndicator';
import WaitingText
from 'app/components/spinners/WaitingText';
export const RoutesHeader = ({type}) => {
const RoutesHeader = ({type}) => {
const rtype = {
[ROUTES_RECEIVED]: "accepted",
[ROUTES_FILTERED]: "filtered",
@ -34,6 +53,14 @@ export const RoutesHeader = ({type}) => {
return (<p className={cls}>Routes {rtype}</p>);
};
const RoutesLoading = () => {
return (
<div className={`card routes-view`}>
<LoadingIndicator />
<WaitingText />
</div>
);
};
const createRoutesSet = (type, useRoutes) => () => {
const results = useRoutes();
@ -48,6 +75,16 @@ const createRoutesSet = (type, useRoutes) => () => {
[ROUTES_NOT_EXPORTED]: 'routes-not-exported',
}[type];
if (!results.requested) {
return null;
}
if (results.loading) {
return <RoutesLoading />;
}
if (results.totalResults === 0) {
return null; // Nothing to show here.
}
// Render the routes card
return (
<div className={`card routes-view ${type}`}>
@ -80,6 +117,61 @@ const RoutesFiltered = createRoutesSet(
useRoutesFiltered,
);
const RoutesNotExported = createRoutesSet(
ROUTES_NOT_EXPORTED,
useRoutesNotExported,
);
/**
* Show a button to load routes not exported on demand.
* IF config states loading routes shoud be done automatically
* update the query parameter.
*/
const RoutesNotExportedRequest = () => {
const { noexport } = useConfig();
const [, setQuery] = useQuery();
const [, makeLocation ] = useQueryLink();
const { requested } = useRoutesNotExported();
const onDemand = noexport?.load_on_demand;
const request = useMemo(() =>
({
...makeLocation({ne: 1}),
hash: "#routes-not-exported"
}),
[makeLocation]);
useEffect(() => {
if (onDemand === false) {
setQuery({ne: 1});
}
}, [onDemand, setQuery]);
if (requested) {
return null;
}
return (
<div className="card routes-view routes-not-exported">
<div className="row">
<div className="col-md-6">
<RoutesHeader type={ROUTES_NOT_EXPORTED} />
</div>
</div>
<p className="help">
Due to the potentially high amount of routes not exported,
they are only fetched on demand.
</p>
<Link to={request}
className="btn btn-block btn-danger">
Load Routes Not Exported
</Link>
</div>
);
}
/**
* Show all routes
@ -89,6 +181,14 @@ const Routes = () => {
const refFiltered = useRef();
const refNotExported = useRef();
// Scroll to anchor
useScrollToAnchor({
"#routes-received": refReceived,
"#routes-filtered": refFiltered,
"#routes-not-exported": refNotExported,
});
return (
<div className="routes-view">
@ -103,8 +203,9 @@ const Routes = () => {
<RoutesReceived />
</div>
<div ref={refNotExported}>
<RoutesNotExportedRequest />
<RoutesNotExported />
</div>
</div>

View File

@ -6,13 +6,13 @@ import GridLoader
* Render a loading indicator that will
* be visible if show is true
*/
const LoadingIndicator = ({show}) => {
const LoadingIndicator = ({show=true}) => {
if (!show) {
return null;
}
return (
<div className="loading-indicator">
<GridLoader loading={true} />
<GridLoader loading={true} size={10} />
</div>
);
}

View File

@ -4,10 +4,6 @@ import { useState
}
from 'react';
import LoadingIndicator
from 'app/components/spinners/LoadingIndicator';
const WaitingText = ({resource = "routes"}) => {
const [time, setTime] = useState(0);
@ -21,9 +17,7 @@ const WaitingText = ({resource = "routes"}) => {
}, []);
return (
<div className="routes-loading card">
<LoadingIndicator show={true} />
<div className="routes-loading">
{time >= 5 &&
<p><br />&gt; Still loading routes, please be patient.</p>}
{time >= 15 &&

View File

@ -142,7 +142,7 @@ const RoutesPage = () => {
ne: 0,
q: "",
});
const notExportedEnabled = query.ne === 1;
const notExportedEnabled = parseInt(query.ne, 10) === 1;
return (
<NeighborProvider neighborId={neighborId}>