Ui/TRA-4586_add-insertion-filter-to-settings-page (#1127)

* working query input

* removed prop

* splited to diffrent events

* export alias

* PR comments

Co-authored-by: Leon <>
This commit is contained in:
leon-up9 2022-06-06 16:40:23 +03:00 committed by GitHub
parent 71db792a4e
commit 6e6bcec77e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 68 deletions

View File

@ -1,36 +1,43 @@
import React, {useRef, useState} from "react";
import React, { FC, useEffect, useMemo, useRef, useState } from "react";
import styles from '../style/Filters.module.sass';
import {Button, Grid, Modal, Box, Typography, Backdrop, Fade, Divider} from "@material-ui/core";
import { Button, Grid, Modal, Box, Typography, Backdrop, Fade, Divider, debounce } from "@material-ui/core";
import CodeEditor from '@uiw/react-textarea-code-editor';
import MenuBookIcon from '@material-ui/icons/MenuBook';
import {SyntaxHighlighter} from "../UI/SyntaxHighlighter/index";
import { SyntaxHighlighter } from "../UI/SyntaxHighlighter/index";
import filterUIExample1 from "assets/filter-ui-example-1.png"
import filterUIExample2 from "assets/filter-ui-example-2.png"
import variables from '../../variables.module.scss';
import {useRecoilState, useRecoilValue} from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";
import queryAtom from "../../recoil/query";
import useKeyPress from "../../hooks/useKeyPress"
import shortcutsKeyboard from "../../configs/shortcutsKeyboard"
import trafficViewerApiAtom from "../../recoil/TrafficViewerApi"
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
interface FiltersProps {
backgroundColor: string
reopenConnection: any;
}
export const Filters: React.FC<FiltersProps> = ({backgroundColor, reopenConnection}) => {
export const Filters: React.FC<FiltersProps> = ({ reopenConnection }) => {
const [query, setQuery] = useRecoilState(queryAtom);
const api: any = useRecoilValue(TrafficViewerApiAtom)
return <div className={styles.container}>
<QueryForm
backgroundColor={backgroundColor}
query={query}
reopenConnection={reopenConnection}
/>
onQueryChange={(query) => { setQuery(query?.trim()); }} validateQuery={api?.validateQuery} />
</div>;
};
type OnQueryChange = { valid: boolean, message: string, query: string }
interface QueryFormProps {
backgroundColor: string
reopenConnection: any;
reopenConnection?: any;
query: string
onQueryChange?: (query: string) => void
validateQuery: (query: string) => Promise<{ valid: boolean, message: string }>;
onValidationChanged?: (event: OnQueryChange) => void
}
export const modalStyle = {
@ -47,20 +54,57 @@ export const modalStyle = {
color: '#000',
};
export const QueryForm: React.FC<QueryFormProps> = ({backgroundColor, reopenConnection}) => {
export const CodeEditorWrap: FC<QueryFormProps> = ({ query, onQueryChange, validateQuery, onValidationChanged }) => {
const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5");
const handleQueryChange = useMemo(
() =>
debounce(async (query: string) => {
if (!query) {
setQueryBackgroundColor("#f5f5f5");
onValidationChanged && onValidationChanged({ query: query, message: "", valid: true })
} else {
const data = await validateQuery(query);
if (!data) {
return;
}
if (data.valid) {
setQueryBackgroundColor("#d2fad2");
} else {
setQueryBackgroundColor("#fad6dc");
}
onValidationChanged && onValidationChanged({ query: query, message: data.message, valid: data.valid })
}
}, 500),
[onValidationChanged, validateQuery]
) as (query: string) => void;
useEffect(() => {
handleQueryChange(query);
}, [query, handleQueryChange]);
return <CodeEditor
value={query}
language="py"
placeholder="Mizu Filter Syntax"
onChange={(event) => onQueryChange(event.target.value)}
padding={8}
style={{
fontSize: 14,
backgroundColor: `${queryBackgroundColor}`,
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace',
}}
/>
}
export const QueryForm: React.FC<QueryFormProps> = ({ validateQuery, reopenConnection, query, onQueryChange, onValidationChanged }) => {
const formRef = useRef<HTMLFormElement>(null);
const [query, setQuery] = useRecoilState(queryAtom);
const [openModal, setOpenModal] = useState(false);
const handleOpenModal = () => setOpenModal(true);
const handleCloseModal = () => setOpenModal(false);
const handleChange = async (e) => {
setQuery(e.target.value.trim());
}
const handleSubmit = (e) => {
reopenConnection();
e.preventDefault();
@ -86,18 +130,7 @@ export const QueryForm: React.FC<QueryFormProps> = ({backgroundColor, reopenConn
}}
>
<label>
<CodeEditor
value={query}
language="py"
placeholder="Mizu Filter Syntax"
onChange={handleChange}
padding={8}
style={{
fontSize: 14,
backgroundColor: `${backgroundColor}`,
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace',
}}
/>
<CodeEditorWrap validateQuery={validateQuery} query={query} onQueryChange={onQueryChange} onValidationChanged={onValidationChanged} />
</label>
</Grid>
<Grid item xs={4}>

View File

@ -1,24 +1,23 @@
import React, {useEffect, useMemo, useRef, useState} from "react";
import {Filters} from "./Filters";
import {EntriesList} from "./EntriesList";
import {makeStyles} from "@material-ui/core";
import React, { useEffect, useRef, useState } from "react";
import { Filters } from "./Filters";
import { EntriesList } from "./EntriesList";
import { makeStyles } from "@material-ui/core";
import TrafficViewerStyles from "./TrafficViewer.module.sass";
import styles from '../style/EntriesList.module.sass';
import {EntryDetailed} from "./EntryDetailed";
import { EntryDetailed } from "./EntryDetailed";
import playIcon from 'assets/run.svg';
import pauseIcon from 'assets/pause.svg';
import variables from '../../variables.module.scss';
import {ToastContainer} from 'react-toastify';
import debounce from 'lodash/debounce';
import {RecoilRoot, RecoilState, useRecoilState, useRecoilValue, useSetRecoilState} from "recoil";
import { ToastContainer } from 'react-toastify';
import { RecoilRoot, RecoilState, useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import entriesAtom from "../../recoil/entries";
import focusedEntryIdAtom from "../../recoil/focusedEntryId";
import queryAtom from "../../recoil/query";
import trafficViewerApiAtom from "../../recoil/TrafficViewerApi"
import TrafficViewerApi from "./TrafficViewerApi";
import {StatusBar} from "../UI/StatusBar";
import { StatusBar } from "../UI/StatusBar";
import tappingStatusAtom from "../../recoil/tappingStatus/atom";
import {TOAST_CONTAINER_ID} from "../../configs/Consts";
import { TOAST_CONTAINER_ID } from "../../configs/Consts";
import leftOffTopAtom from "../../recoil/leftOffTop";
import { DEFAULT_LEFTOFF, DEFAULT_FETCH, DEFAULT_FETCH_TIMEOUT_MS } from '../../hooks/useWS';
@ -70,34 +69,12 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
const [isSnappedToBottom, setIsSnappedToBottom] = useState(true);
const [wsReadyState, setWsReadyState] = useState(0);
const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5");
const setLeftOffTop = useSetRecoilState(leftOffTopAtom);
const scrollableRef = useRef(null);
const handleQueryChange = useMemo(
() =>
debounce(async (query: string) => {
if (!query) {
setQueryBackgroundColor("#f5f5f5");
} else {
const data = await trafficViewerApiProp.validateQuery(query);
if (!data) {
return;
}
if (data.valid) {
setQueryBackgroundColor("#d2fad2");
} else {
setQueryBackgroundColor("#fad6dc");
}
}
}, 500),
[]
) as (query: string) => void;
useEffect(() => {
handleQueryChange(query);
}, [query, handleQueryChange]);
useEffect(() => {
if(shouldCloseWebSocket){
@ -262,7 +239,6 @@ export const TrafficViewer: React.FC<TrafficViewerProps> = ({
{<div className={TrafficViewerStyles.TrafficPageContainer}>
<div className={TrafficViewerStyles.TrafficPageListContainer}>
<Filters
backgroundColor={queryBackgroundColor}
reopenConnection={reopenConnection}
/>
<div className={styles.container}>

View File

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

View File

@ -5,6 +5,7 @@ import useWS, { DEFAULT_LEFTOFF } from './hooks/useWS';
import OasModal from './components/OasModal/OasModal';
import { ServiceMapModal } from './components/ServiceMapModal/ServiceMapModal';
export { CodeEditorWrap as QueryForm } from './components/TrafficViewer/Filters';
export { UI, StatusBar, OasModal, ServiceMapModal }
export { useWS, DEFAULT_LEFTOFF }
export default TrafficViewer;

View File

@ -3,7 +3,7 @@ import TrafficViewerApi from "../../components/TrafficViewer/TrafficViewerApi";
const TrafficViewerApiAtom = atom({
key: "TrafficViewerApiAtom",
default: {} as TrafficViewerApi
default: {}
});
export default TrafficViewerApiAtom;