mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-14 14:43:46 +00:00
UI/feature flag for replay modal (#1186)
* context added * import added * chnages * ui enabled * moved to Consts * changes to recoil * change * new useEffect Co-authored-by: Leon <>
This commit is contained in:
parent
d857935889
commit
38c05a6634
@ -6,6 +6,7 @@ import { ReactComponent as ReplayIcon } from './replay.svg';
|
|||||||
import styles from './EntryViewer.module.sass';
|
import styles from './EntryViewer.module.sass';
|
||||||
import { Tabs } from "../../UI";
|
import { Tabs } from "../../UI";
|
||||||
import replayRequestModalOpenAtom from "../../../recoil/replayRequestModalOpen";
|
import replayRequestModalOpenAtom from "../../../recoil/replayRequestModalOpen";
|
||||||
|
import entryDetailedConfigAtom, { EntryDetailedConfig } from "../../../recoil/entryDetailedConfig";
|
||||||
|
|
||||||
const enabledProtocolsForReplay = ["http"]
|
const enabledProtocolsForReplay = ["http"]
|
||||||
|
|
||||||
@ -16,10 +17,11 @@ export enum TabsEnum {
|
|||||||
|
|
||||||
export const AutoRepresentation: React.FC<any> = ({ representation, color, openedTab = TabsEnum.Request, isDisplayReplay = false }) => {
|
export const AutoRepresentation: React.FC<any> = ({ representation, color, openedTab = TabsEnum.Request, isDisplayReplay = false }) => {
|
||||||
const entryData = useRecoilValue(entryDataAtom)
|
const entryData = useRecoilValue(entryDataAtom)
|
||||||
|
const { isReplayEnabled } = useRecoilValue<EntryDetailedConfig>(entryDetailedConfigAtom)
|
||||||
const setIsOpenRequestModal = useSetRecoilState(replayRequestModalOpenAtom)
|
const setIsOpenRequestModal = useSetRecoilState(replayRequestModalOpenAtom)
|
||||||
const isReplayDisplayed = useCallback(() => {
|
const isReplayDisplayed = useCallback(() => {
|
||||||
return enabledProtocolsForReplay.find(x => x === entryData.protocol.name) && isDisplayReplay
|
return enabledProtocolsForReplay.find(x => x === entryData.protocol.name) && isDisplayReplay && isReplayEnabled
|
||||||
}, [entryData.protocol.name, isDisplayReplay])
|
}, [entryData.protocol.name, isDisplayReplay, isReplayEnabled])
|
||||||
|
|
||||||
const { request, response } = JSON.parse(representation);
|
const { request, response } = JSON.parse(representation);
|
||||||
|
|
||||||
@ -31,12 +33,10 @@ export const AutoRepresentation: React.FC<any> = ({ representation, color, opene
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
arr.push(
|
arr.push({
|
||||||
{
|
tab: 'Response',
|
||||||
tab: 'Response',
|
badge: null
|
||||||
badge: null
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr
|
return arr
|
||||||
|
@ -22,6 +22,7 @@ import leftOffTopAtom from "../../recoil/leftOffTop";
|
|||||||
import { DEFAULT_LEFTOFF, DEFAULT_FETCH, DEFAULT_FETCH_TIMEOUT_MS } from '../../hooks/useWS';
|
import { DEFAULT_LEFTOFF, DEFAULT_FETCH, DEFAULT_FETCH_TIMEOUT_MS } from '../../hooks/useWS';
|
||||||
import ReplayRequestModalContainer from "../modals/ReplayRequestModal/ReplayRequestModal";
|
import ReplayRequestModalContainer from "../modals/ReplayRequestModal/ReplayRequestModal";
|
||||||
import replayRequestModalOpenAtom from "../../recoil/replayRequestModalOpen";
|
import replayRequestModalOpenAtom from "../../recoil/replayRequestModalOpen";
|
||||||
|
import entryDetailedConfigAtom, { EntryDetailedConfig } from "../../recoil/entryDetailedConfig";
|
||||||
|
|
||||||
const useLayoutStyles = makeStyles(() => ({
|
const useLayoutStyles = makeStyles(() => ({
|
||||||
details: {
|
details: {
|
||||||
@ -51,18 +52,22 @@ interface TrafficViewerProps {
|
|||||||
webSocketUrl: string,
|
webSocketUrl: string,
|
||||||
shouldCloseWebSocket: boolean,
|
shouldCloseWebSocket: boolean,
|
||||||
setShouldCloseWebSocket: (flag: boolean) => void,
|
setShouldCloseWebSocket: (flag: boolean) => void,
|
||||||
isDemoBannerView: boolean
|
isDemoBannerView: boolean,
|
||||||
|
entryDetailedConfig: EntryDetailedConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
||||||
trafficViewerApiProp,
|
trafficViewerApiProp,
|
||||||
actionButtons, isShowStatusBar, webSocketUrl,
|
webSocketUrl,
|
||||||
shouldCloseWebSocket, setShouldCloseWebSocket, isDemoBannerView
|
actionButtons,
|
||||||
}) => {
|
isShowStatusBar, isDemoBannerView,
|
||||||
|
shouldCloseWebSocket, setShouldCloseWebSocket,
|
||||||
|
entryDetailedConfig }) => {
|
||||||
|
|
||||||
const classes = useLayoutStyles();
|
const classes = useLayoutStyles();
|
||||||
const setEntries = useSetRecoilState(entriesAtom);
|
const setEntries = useSetRecoilState(entriesAtom);
|
||||||
const setFocusedEntryId = useSetRecoilState(focusedEntryIdAtom);
|
const setFocusedEntryId = useSetRecoilState(focusedEntryIdAtom);
|
||||||
|
const setEntryDetailedConfigAtom = useSetRecoilState(entryDetailedConfigAtom)
|
||||||
const query = useRecoilValue(queryAtom);
|
const query = useRecoilValue(queryAtom);
|
||||||
const setTrafficViewerApiState = useSetRecoilState(trafficViewerApiAtom as RecoilState<TrafficViewerApi>)
|
const setTrafficViewerApiState = useSetRecoilState(trafficViewerApiAtom as RecoilState<TrafficViewerApi>)
|
||||||
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
|
const [tappingStatus, setTappingStatus] = useRecoilState(tappingStatusAtom);
|
||||||
@ -183,6 +188,10 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setEntryDetailedConfigAtom(entryDetailedConfig)
|
||||||
|
}, [entryDetailedConfig, setEntryDetailedConfigAtom])
|
||||||
|
|
||||||
const getConnectionIndicator = () => {
|
const getConnectionIndicator = () => {
|
||||||
switch (wsReadyState) {
|
switch (wsReadyState) {
|
||||||
case WebSocket.OPEN:
|
case WebSocket.OPEN:
|
||||||
@ -258,7 +267,7 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.details} id="rightSideContainer">
|
<div className={classes.details} id="rightSideContainer">
|
||||||
<EntryDetailed/>
|
<EntryDetailed />
|
||||||
</div>
|
</div>
|
||||||
</div>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
@ -266,25 +275,19 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const MemorizedTrafficViewer = React.memo(TrafficViewer)
|
const MemorizedTrafficViewer = React.memo(TrafficViewer)
|
||||||
const TrafficViewerContainer: React.FC<TrafficViewerProps> = ({
|
const TrafficViewerContainer: React.FC<TrafficViewerProps> = (props) => {
|
||||||
trafficViewerApiProp,
|
|
||||||
actionButtons, isShowStatusBar = true,
|
|
||||||
webSocketUrl, shouldCloseWebSocket, setShouldCloseWebSocket, isDemoBannerView
|
|
||||||
}) => {
|
|
||||||
return <RecoilRoot>
|
return <RecoilRoot>
|
||||||
<MemorizedTrafficViewer actionButtons={actionButtons} isShowStatusBar={isShowStatusBar} webSocketUrl={webSocketUrl}
|
<MemorizedTrafficViewer {...props} />
|
||||||
shouldCloseWebSocket={shouldCloseWebSocket} setShouldCloseWebSocket={setShouldCloseWebSocket} trafficViewerApiProp={trafficViewerApiProp}
|
|
||||||
isDemoBannerView={isDemoBannerView}/>
|
|
||||||
<ToastContainer enableMultiContainer containerId={TOAST_CONTAINER_ID}
|
<ToastContainer enableMultiContainer containerId={TOAST_CONTAINER_ID}
|
||||||
position="bottom-right"
|
position="bottom-right"
|
||||||
autoClose={5000}
|
autoClose={5000}
|
||||||
hideProgressBar={false}
|
hideProgressBar={false}
|
||||||
newestOnTop={false}
|
newestOnTop={false}
|
||||||
closeOnClick
|
closeOnClick
|
||||||
rtl={false}
|
rtl={false}
|
||||||
pauseOnFocusLoss
|
pauseOnFocusLoss
|
||||||
draggable
|
draggable
|
||||||
pauseOnHover/>
|
pauseOnHover />
|
||||||
<ReplayRequestModalContainer />
|
<ReplayRequestModalContainer />
|
||||||
</RecoilRoot>
|
</RecoilRoot>
|
||||||
}
|
}
|
||||||
|
12
ui-common/src/recoil/entryDetailedConfig/atom.ts
Normal file
12
ui-common/src/recoil/entryDetailedConfig/atom.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { atom } from "recoil";
|
||||||
|
|
||||||
|
const entryDetailedConfigAtom = atom({
|
||||||
|
key: "entryDetailedConfigAtom",
|
||||||
|
default: null
|
||||||
|
});
|
||||||
|
|
||||||
|
export type EntryDetailedConfig = {
|
||||||
|
isReplayEnabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default entryDetailedConfigAtom;
|
3
ui-common/src/recoil/entryDetailedConfig/index.ts
Normal file
3
ui-common/src/recoil/entryDetailedConfig/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import atom from "./atom"
|
||||||
|
export type { EntryDetailedConfig } from "./atom"
|
||||||
|
export default atom
|
@ -12,6 +12,7 @@ import serviceMap from "../../assets/serviceMap.svg";
|
|||||||
import services from "../../assets/services.svg";
|
import services from "../../assets/services.svg";
|
||||||
import trafficStatsIcon from "../../assets/trafficStats.svg";
|
import trafficStatsIcon from "../../assets/trafficStats.svg";
|
||||||
import trafficStatsModalOpenAtom from "../../../recoil/trafficStatsModalOpen";
|
import trafficStatsModalOpenAtom from "../../../recoil/trafficStatsModalOpen";
|
||||||
|
import { REPLAY_ENABLED } from "../../../consts";
|
||||||
|
|
||||||
const api = Api.getInstance();
|
const api = Api.getInstance();
|
||||||
|
|
||||||
@ -40,39 +41,41 @@ export const TrafficPage: React.FC = () => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const actionButtons = <div style={{ display: 'flex', height: "100%" }}>
|
const actionButtons = <div style={{ display: 'flex', height: "100%" }}>
|
||||||
{window["isOasEnabled"] && <Button
|
{window["isOasEnabled"] && <Button
|
||||||
startIcon={<img className="custom" src={services} alt="services" />}
|
startIcon={<img className="custom" src={services} alt="services" />}
|
||||||
size="large"
|
size="large"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
style={{ marginRight: 25, textTransform: 'unset' }}
|
style={{ marginRight: 25, textTransform: 'unset' }}
|
||||||
onClick={handleOpenOasModal}>
|
onClick={handleOpenOasModal}>
|
||||||
Service Catalog
|
Service Catalog
|
||||||
</Button>}
|
</Button>}
|
||||||
{window["isServiceMapEnabled"] && <Button
|
{window["isServiceMapEnabled"] && <Button
|
||||||
startIcon={<img src={serviceMap} className="custom" alt="service-map" style={{ marginRight: "8%" }} />}
|
startIcon={<img src={serviceMap} className="custom" alt="service-map" style={{ marginRight: "8%" }} />}
|
||||||
size="large"
|
size="large"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
onClick={openServiceMapModalDebounce}
|
onClick={openServiceMapModalDebounce}
|
||||||
style={{ marginRight: 25, textTransform: 'unset' }}>
|
style={{ marginRight: 25, textTransform: 'unset' }}>
|
||||||
Service Map
|
Service Map
|
||||||
</Button>}
|
</Button>}
|
||||||
<Button
|
<Button
|
||||||
startIcon={<img className="custom" src={trafficStatsIcon} alt="services" />}
|
startIcon={<img className="custom" src={trafficStatsIcon} alt="services" />}
|
||||||
size="large"
|
size="large"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||||
style={{ textTransform: 'unset' }}
|
style={{ textTransform: 'unset' }}
|
||||||
onClick={handleOpenStatsModal}>
|
onClick={handleOpenStatsModal}>
|
||||||
Traffic Stats
|
Traffic Stats
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TrafficViewer webSocketUrl={MizuWebsocketURL} shouldCloseWebSocket={shouldCloseWebSocket} setShouldCloseWebSocket={setShouldCloseWebSocket}
|
<TrafficViewer webSocketUrl={MizuWebsocketURL} shouldCloseWebSocket={shouldCloseWebSocket} setShouldCloseWebSocket={setShouldCloseWebSocket}
|
||||||
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!(openOasModal || serviceMapModalOpen || trafficStatsModalOpen)} isDemoBannerView={false} />
|
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!(openOasModal || serviceMapModalOpen || trafficStatsModalOpen)} isDemoBannerView={false} entryDetailedConfig={{
|
||||||
|
isReplayEnabled: REPLAY_ENABLED
|
||||||
|
}} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export const adminUsername = "admin";
|
export const adminUsername = "admin";
|
||||||
export const TOAST_CONTAINER_ID = "Community";
|
export const TOAST_CONTAINER_ID = "Community";
|
||||||
|
export const REPLAY_ENABLED = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user