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:
leon-up9 2022-07-06 11:19:46 +03:00 committed by GitHub
parent d857935889
commit 38c05a6634
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 57 deletions

View File

@ -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

View File

@ -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>
} }

View File

@ -0,0 +1,12 @@
import { atom } from "recoil";
const entryDetailedConfigAtom = atom({
key: "entryDetailedConfigAtom",
default: null
});
export type EntryDetailedConfig = {
isReplayEnabled: boolean
}
export default entryDetailedConfigAtom;

View File

@ -0,0 +1,3 @@
import atom from "./atom"
export type { EntryDetailedConfig } from "./atom"
export default atom

View File

@ -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
}} />
</> </>
); );
}; };

View File

@ -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;