load routes, show spinner, load not exported on demand, refactored scroll to anchor
This commit is contained in:
parent
b230411b37
commit
462938db68
20
ui/src/app/components/navigation/hash.js
Normal file
20
ui/src/app/components/navigation/hash.js
Normal 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]);
|
||||
}
|
||||
|
@ -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} />;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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 />> Still loading routes, please be patient.</p>}
|
||||
{time >= 15 &&
|
||||
|
@ -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}>
|
||||
|
Loading…
x
Reference in New Issue
Block a user