with loading HOC (#1181)

* withLoading

* optional props

* LoadingWrapper

* pr comments

* changes

Co-authored-by: Leon <>
This commit is contained in:
leon-up9 2022-07-05 12:23:47 +03:00 committed by GitHub
parent 5f73c2d50a
commit f3a6b3a9d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 52 deletions

View File

@ -12,8 +12,8 @@ import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
import queryAtom from "../../recoil/query/atom";
import useWindowDimensions, { useRequestTextByWidth } from "../../hooks/WindowDimensionsHook";
import { TOAST_CONTAINER_ID } from "../../configs/Consts";
import spinner from "assets/spinner.svg";
import entryDataAtom from "../../recoil/entryData";
import { LoadingWrapper } from "../UI/withLoading/withLoading";
const useStyles = makeStyles(() => ({
entryTitle: {
@ -135,19 +135,11 @@ export const EntryDetailed = () => {
// eslint-disable-next-line
}, [focusedEntryId]);
return <React.Fragment>
{isLoading && <div style={{textAlign: "center", width: "100%", marginTop: 50}}><img alt="spinner" src={spinner} style={{height: 60}}/></div>}
{!isLoading && entryData && <EntryTitle
protocol={entryData.protocol}
data={entryData.data}
elapsedTime={entryData.data.elapsedTime}
/>}
{!isLoading && entryData && <EntrySummary entry={entryData.base} namespace={entryData.data.namespace} />}
<React.Fragment>
{!isLoading && entryData && <EntryViewer
representation={entryData.representation}
color={entryData.protocol.backgroundColor}
/>}
</React.Fragment>
</React.Fragment>
return <LoadingWrapper isLoading={isLoading} loaderMargin={50} loaderHeight={60}>
{entryData && <React.Fragment>
<EntryTitle protocol={entryData.protocol} data={entryData.data} elapsedTime={entryData.data.elapsedTime} />
<EntrySummary entry={entryData.base} namespace={entryData.data.namespace} />
<EntryViewer representation={entryData.representation} color={entryData.protocol.backgroundColor} />
</React.Fragment>}
</LoadingWrapper>
};

View File

@ -8,6 +8,7 @@ import CustomModal from "./CustomModal/CustomModal";
import { InformationIcon, Link } from "./InformationIcon/InformationIcon";
import SelectList from "./SelectList/SelectList";
import NoDataMessage from "./NoDataMessage/NoDataMessage";
import withLoading from "./withLoading/withLoading";
export { LoadingOverlay, Select, Tabs, Tooltip, Checkbox, CustomModal, InformationIcon, SelectList, NoDataMessage, Link };
export { LoadingOverlay, Select, Tabs, Tooltip, Checkbox, CustomModal, InformationIcon, SelectList, NoDataMessage, withLoading, Link };
export { StatusBar }

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" fill="none" stroke="#1d3f72" stroke-width="10" r="35" stroke-dasharray="164.93361431346415 56.97787143782138" transform="rotate(275.903 50 50)">
<animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" values="0 50 50;360 50 50" keyTimes="0;1"></animateTransform>
</circle>
<!-- [ldio] generated by https://loading.io/ --></svg>

After

Width:  |  Height:  |  Size: 673 B

View File

@ -0,0 +1,33 @@
import React from "react";
import spinner from 'spinner.svg';
export interface WithLoadingProps {
isLoading: boolean
loaderMargin?: number,
loaderHeight?: number
}
const Loader = ({ loaderMargin = 20, loaderHeight = 35 }: Omit<WithLoadingProps, "isLoading">) => {
return <div style={{ textAlign: "center", margin: loaderMargin }}>
<img alt="spinner" src={spinner} style={{ height: loaderHeight }} />
</div>
}
const withLoading = <P extends object>(
Component: React.ComponentType<P>
): React.FC<P & WithLoadingProps> => ({
isLoading,
loaderMargin,
loaderHeight,
...props
}: WithLoadingProps) => isLoading ?
<Loader loaderMargin={loaderMargin} loaderHeight={loaderHeight} /> :
<Component {...props as P} />;
export const LoadingWrapper: React.FC<WithLoadingProps> = ({ loaderMargin, loaderHeight, isLoading, children }) => {
return isLoading ?
<Loader loaderMargin={loaderMargin} loaderHeight={loaderHeight} /> :
<React.Fragment>{children}</React.Fragment>
}
export default withLoading

View File

@ -12,7 +12,6 @@ import { toast } from "react-toastify";
import { TOAST_CONTAINER_ID } from "../../../configs/Consts";
import styles from './ReplayRequestModal.module.sass'
import closeIcon from "assets/close.svg"
import spinnerImg from "assets/spinner.svg"
import refreshImg from "assets/refresh.svg"
import { formatRequestWithOutError } from "../../EntryDetailed/EntrySections/EntrySections";
import entryDataAtom from "../../../recoil/entryData";
@ -20,6 +19,7 @@ import { AutoRepresentation, TabsEnum } from "../../EntryDetailed/EntryViewer/Au
import useDebounce from "../../../hooks/useDebounce"
import replayRequestModalOpenAtom from "../../../recoil/replayRequestModalOpen";
import { Utils } from "../../../helpers/Utils";
import { LoadingWrapper } from "../../UI/withLoading/withLoading";
const modalStyle = {
position: 'absolute',
@ -233,8 +233,8 @@ const ReplayRequestModal: React.FC<ReplayRequestModalProps> = ({ isOpen, onClose
</div>
</AccordionDetails>
</Accordion>
{isLoading && <img alt="spinner" src={spinnerImg} style={{ height: 50 }} />}
{response && !isLoading && (<Accordion TransitionProps={{ unmountOnExit: true }} expanded={responseExpanded} onChange={() => setResponseExpanded(!responseExpanded)}>
<LoadingWrapper isLoading={isLoading} loaderMargin={10} loaderHeight={50}>
{response && (<Accordion TransitionProps={{ unmountOnExit: true }} expanded={responseExpanded} onChange={() => setResponseExpanded(!responseExpanded)}>
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="response-content">
<span className={styles.sectionHeader}>RESPONSE</span>
</AccordionSummary>
@ -242,6 +242,7 @@ const ReplayRequestModal: React.FC<ReplayRequestModalProps> = ({ isOpen, onClose
<AutoRepresentation representation={response} color={entryData.protocol.backgroundColor} openedTab={TabsEnum.Response} />
</AccordionDetails>
</Accordion>)}
</LoadingWrapper>
</div>
</Box>
</Fade>

View File

@ -96,8 +96,3 @@ $modalMargin-from-edge : 35px
.servicesFilterList
height: calc(100% - 30px - 52px)
.spinnerContainer
display: flex
justify-content: center
margin-bottom: 10px

View File

@ -1,7 +1,6 @@
import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Box, Fade, Modal, Backdrop, Button } from "@mui/material";
import { toast } from "react-toastify";
import spinnerImg from 'assets/spinner.svg';
import Graph from "react-graph-vis";
import debounce from 'lodash/debounce';
import ServiceMapOptions from './ServiceMapOptions'
@ -16,6 +15,7 @@ import { GraphData, ServiceMapGraph } from "./ServiceMapModalTypes"
import { Utils } from "../../../helpers/Utils";
import { TOAST_CONTAINER_ID } from "../../../configs/Consts";
import Resizeable from "../../UI/Resizeable/Resizeable"
import { LoadingWrapper } from "../../UI/withLoading/withLoading";
const modalStyle = {
position: 'absolute',
@ -197,14 +197,14 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onClos
<Fade in={isOpen}>
<Box sx={modalStyle}>
<div className={styles.closeIcon}>
<img src={closeIcon} alt="close" onClick={() => onClose()} style={{ cursor: "pointer", userSelect: "none" }}/>
<img src={closeIcon} alt="close" onClick={() => onClose()} style={{ cursor: "pointer", userSelect: "none" }} />
</div>
<div className={styles.headerContainer}>
<div className={styles.headerSection}>
<span className={styles.title}>Services</span>
<Button size="medium"
variant="contained"
startIcon={<img src={isFilterClicked ? filterIconClicked : filterIcon} className="custom" alt="refresh" style={{ height: "26px", width: "26px" }}/>}
startIcon={<img src={isFilterClicked ? filterIconClicked : filterIcon} className="custom" alt="refresh" style={{ height: "26px", width: "26px" }} />}
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton + ` ${isFilterClicked ? commonClasses.clickedButton : ""}`}
onClick={() => setIsFilterClicked(prevState => !prevState)}
style={{ textTransform: 'unset' }}>
@ -243,16 +243,14 @@ export const ServiceMapModal: React.FC<ServiceMapModalProps> = ({ isOpen, onClos
<div className={styles.graphSection}>
<div style={{ display: "flex", justifyContent: "space-between" }}>
</div>
{isLoading && <div className={styles.spinnerContainer}>
<img alt="spinner" src={spinnerImg} style={{ height: 50 }} />
</div>}
{!isLoading && <div style={{ height: "100%", width: "100%" }}>
<LoadingWrapper isLoading={isLoading} loaderHeight={50} loaderMargin={20}>
<div style={{ height: "100%", width: "100%" }}>
<Graph
graph={graphData}
options={graphOptions}
/>
</div>
}
</LoadingWrapper>
</div>
</div>
</Box>

View File

@ -4,9 +4,9 @@ import styles from "./TrafficStatsModal.module.sass";
import closeIcon from "assets/close.svg";
import { TrafficPieChart } from "./TrafficPieChart/TrafficPieChart";
import { TimelineBarChart } from "./TimelineBarChart/TimelineBarChart";
import spinnerImg from "assets/spinner.svg";
import refreshIcon from "assets/refresh.svg";
import { useCommonStyles } from "../../../helpers/commonStyle";
import { LoadingWrapper } from "../../UI/withLoading/withLoading";
const modalStyle = {
position: 'absolute',
@ -114,13 +114,12 @@ export const TrafficStatsModal: React.FC<TrafficStatsModalProps> = ({ isOpen, on
</div>
</div>
<div>
{isLoading ? <div style={{ textAlign: "center", marginTop: 20 }}>
<img alt="spinner" src={spinnerImg} style={{ height: 50 }} />
</div> :
<LoadingWrapper isLoading={isLoading} loaderMargin={20} loaderHeight={50}>
<div>
<TrafficPieChart pieChartMode={statsMode} data={pieStatsData} selectedProtocol={selectedProtocol}/>
<TimelineBarChart timeLineBarChartMode={statsMode} data={timelineStatsData} selectedProtocol={selectedProtocol}/>
</div>}
<TrafficPieChart pieChartMode={statsMode} data={pieStatsData} selectedProtocol={selectedProtocol} />
<TimelineBarChart timeLineBarChartMode={statsMode} data={timelineStatsData} selectedProtocol={selectedProtocol} />
</div>
</LoadingWrapper>
</div>
</div>
</Box>