mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-06-29 09:39:54 +00:00
with loading HOC (#1181)
* withLoading * optional props * LoadingWrapper * pr comments * changes Co-authored-by: Leon <>
This commit is contained in:
parent
5f73c2d50a
commit
f3a6b3a9d4
@ -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>
|
||||
};
|
||||
|
@ -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 }
|
||||
|
6
ui-common/src/components/UI/withLoading/spinner.svg
Normal file
6
ui-common/src/components/UI/withLoading/spinner.svg
Normal 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 |
33
ui-common/src/components/UI/withLoading/withLoading.tsx
Normal file
33
ui-common/src/components/UI/withLoading/withLoading.tsx
Normal 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
|
@ -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,15 +233,16 @@ 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)}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls="response-content">
|
||||
<span className={styles.sectionHeader}>RESPONSE</span>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<AutoRepresentation representation={response} color={entryData.protocol.backgroundColor} openedTab={TabsEnum.Response} />
|
||||
</AccordionDetails>
|
||||
</Accordion>)}
|
||||
<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>
|
||||
<AccordionDetails>
|
||||
<AutoRepresentation representation={response} color={entryData.protocol.backgroundColor} openedTab={TabsEnum.Response} />
|
||||
</AccordionDetails>
|
||||
</Accordion>)}
|
||||
</LoadingWrapper>
|
||||
</div>
|
||||
</Box>
|
||||
</Fade>
|
||||
|
@ -96,8 +96,3 @@ $modalMargin-from-edge : 35px
|
||||
|
||||
.servicesFilterList
|
||||
height: calc(100% - 30px - 52px)
|
||||
|
||||
.spinnerContainer
|
||||
display: flex
|
||||
justify-content: center
|
||||
margin-bottom: 10px
|
||||
|
@ -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%" }}>
|
||||
<Graph
|
||||
graph={graphData}
|
||||
options={graphOptions}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<LoadingWrapper isLoading={isLoading} loaderHeight={50} loaderMargin={20}>
|
||||
<div style={{ height: "100%", width: "100%" }}>
|
||||
<Graph
|
||||
graph={graphData}
|
||||
options={graphOptions}
|
||||
/>
|
||||
</div>
|
||||
</LoadingWrapper>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user