2020-10-29 20:54:17 +01:00
|
|
|
import {
|
|
|
|
Box,
|
|
|
|
Checkbox,
|
|
|
|
CircularProgress,
|
|
|
|
ClickAwayListener,
|
|
|
|
createStyles,
|
|
|
|
FormControlLabel,
|
|
|
|
InputBase,
|
|
|
|
makeStyles,
|
|
|
|
Paper,
|
|
|
|
Popper,
|
|
|
|
Theme,
|
|
|
|
Tooltip,
|
|
|
|
useTheme,
|
|
|
|
} from "@material-ui/core";
|
|
|
|
import IconButton from "@material-ui/core/IconButton";
|
|
|
|
import SearchIcon from "@material-ui/icons/Search";
|
|
|
|
import FilterListIcon from "@material-ui/icons/FilterList";
|
2020-11-28 15:48:19 +01:00
|
|
|
import DeleteIcon from "@material-ui/icons/Delete";
|
2020-10-29 20:54:17 +01:00
|
|
|
import React, { useRef, useState } from "react";
|
2020-11-28 15:48:19 +01:00
|
|
|
import { gql, useMutation, useQuery } from "@apollo/client";
|
2020-10-29 20:54:17 +01:00
|
|
|
import { withoutTypename } from "../../lib/omitTypename";
|
|
|
|
import { Alert } from "@material-ui/lab";
|
2020-11-28 15:48:19 +01:00
|
|
|
import { useClearHTTPRequestLog } from "./hooks/useClearHTTPRequestLog";
|
|
|
|
import {
|
|
|
|
ConfirmationDialog,
|
|
|
|
useConfirmationDialog,
|
|
|
|
} from "./ConfirmationDialog";
|
2020-10-29 20:54:17 +01:00
|
|
|
|
|
|
|
const FILTER = gql`
|
|
|
|
query HttpRequestLogFilter {
|
|
|
|
httpRequestLogFilter {
|
|
|
|
onlyInScope
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const SET_FILTER = gql`
|
|
|
|
mutation SetHttpRequestLogFilter($filter: HttpRequestLogFilterInput) {
|
|
|
|
setHttpRequestLogFilter(filter: $filter) {
|
|
|
|
onlyInScope
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const useStyles = makeStyles((theme: Theme) =>
|
|
|
|
createStyles({
|
|
|
|
root: {
|
|
|
|
padding: "2px 4px",
|
|
|
|
display: "flex",
|
|
|
|
alignItems: "center",
|
|
|
|
width: 400,
|
|
|
|
},
|
|
|
|
input: {
|
|
|
|
marginLeft: theme.spacing(1),
|
|
|
|
flex: 1,
|
|
|
|
},
|
|
|
|
iconButton: {
|
|
|
|
padding: 10,
|
|
|
|
},
|
|
|
|
filterPopper: {
|
|
|
|
width: 400,
|
|
|
|
marginTop: 6,
|
|
|
|
zIndex: 99,
|
|
|
|
},
|
|
|
|
filterOptions: {
|
|
|
|
padding: theme.spacing(2),
|
|
|
|
},
|
|
|
|
filterLoading: {
|
|
|
|
marginRight: 1,
|
|
|
|
color: theme.palette.text.primary,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
export interface SearchFilter {
|
|
|
|
onlyInScope: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
function Search(): JSX.Element {
|
|
|
|
const classes = useStyles();
|
|
|
|
const theme = useTheme();
|
|
|
|
|
|
|
|
const { loading: filterLoading, error: filterErr, data: filter } = useQuery(
|
|
|
|
FILTER
|
|
|
|
);
|
|
|
|
|
|
|
|
const [
|
|
|
|
setFilterMutate,
|
|
|
|
{ error: setFilterErr, loading: setFilterLoading },
|
|
|
|
] = useMutation<{
|
|
|
|
setHttpRequestLogFilter: SearchFilter | null;
|
|
|
|
}>(SET_FILTER, {
|
2020-11-28 15:48:19 +01:00
|
|
|
update(cache, { data: { setHttpRequestLogFilter } }) {
|
|
|
|
cache.writeQuery({
|
2020-10-29 20:54:17 +01:00
|
|
|
query: FILTER,
|
|
|
|
data: {
|
|
|
|
httpRequestLogFilter: setHttpRequestLogFilter,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2020-11-28 15:48:19 +01:00
|
|
|
const [
|
|
|
|
clearHTTPRequestLog,
|
|
|
|
clearHTTPRequestLogResult,
|
|
|
|
] = useClearHTTPRequestLog();
|
|
|
|
const clearHTTPConfirmationDialog = useConfirmationDialog();
|
|
|
|
|
2020-10-29 20:54:17 +01:00
|
|
|
const filterRef = useRef<HTMLElement | null>();
|
|
|
|
const [filterOpen, setFilterOpen] = useState(false);
|
|
|
|
|
|
|
|
const handleSubmit = (e: React.SyntheticEvent) => {
|
|
|
|
e.preventDefault();
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleClickAway = (event: React.MouseEvent<EventTarget>) => {
|
|
|
|
if (filterRef.current.contains(event.target as HTMLElement)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setFilterOpen(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2020-11-28 15:48:19 +01:00
|
|
|
<Box>
|
|
|
|
<Error prefix="Error fetching filter" error={filterErr} />
|
|
|
|
<Error prefix="Error setting filter" error={setFilterErr} />
|
|
|
|
<Error
|
|
|
|
prefix="Error clearing all HTTP logs"
|
|
|
|
error={clearHTTPRequestLogResult.error}
|
|
|
|
/>
|
|
|
|
<Box style={{ display: "flex", flex: 1 }}>
|
|
|
|
<ClickAwayListener onClickAway={handleClickAway}>
|
|
|
|
<Paper
|
|
|
|
component="form"
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
ref={filterRef}
|
|
|
|
className={classes.root}
|
|
|
|
>
|
|
|
|
<Tooltip title="Toggle filter options">
|
|
|
|
<IconButton
|
|
|
|
className={classes.iconButton}
|
|
|
|
onClick={() => setFilterOpen(!filterOpen)}
|
|
|
|
style={{
|
|
|
|
color:
|
|
|
|
filter?.httpRequestLogFilter !== null
|
|
|
|
? theme.palette.secondary.main
|
|
|
|
: "inherit",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{filterLoading || setFilterLoading ? (
|
|
|
|
<CircularProgress
|
|
|
|
className={classes.filterLoading}
|
|
|
|
size={23}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<FilterListIcon />
|
|
|
|
)}
|
|
|
|
</IconButton>
|
|
|
|
</Tooltip>
|
|
|
|
<InputBase
|
|
|
|
className={classes.input}
|
|
|
|
placeholder="Search proxy logs…"
|
|
|
|
onFocus={() => setFilterOpen(true)}
|
|
|
|
/>
|
|
|
|
<Tooltip title="Search">
|
|
|
|
<IconButton type="submit" className={classes.iconButton}>
|
|
|
|
<SearchIcon />
|
|
|
|
</IconButton>
|
|
|
|
</Tooltip>
|
|
|
|
<Popper
|
|
|
|
className={classes.filterPopper}
|
|
|
|
open={filterOpen}
|
|
|
|
anchorEl={filterRef.current}
|
|
|
|
placement="bottom-start"
|
2020-10-29 20:54:17 +01:00
|
|
|
>
|
2020-11-28 15:48:19 +01:00
|
|
|
<Paper className={classes.filterOptions}>
|
|
|
|
<FormControlLabel
|
|
|
|
control={
|
|
|
|
<Checkbox
|
|
|
|
checked={
|
|
|
|
filter?.httpRequestLogFilter?.onlyInScope ? true : false
|
|
|
|
}
|
|
|
|
disabled={filterLoading || setFilterLoading}
|
|
|
|
onChange={(e) =>
|
|
|
|
setFilterMutate({
|
|
|
|
variables: {
|
|
|
|
filter: {
|
|
|
|
...withoutTypename(filter?.httpRequestLogFilter),
|
|
|
|
onlyInScope: e.target.checked,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
/>
|
2020-10-29 20:54:17 +01:00
|
|
|
}
|
2020-11-28 15:48:19 +01:00
|
|
|
label="Only show in-scope requests"
|
2020-10-29 20:54:17 +01:00
|
|
|
/>
|
2020-11-28 15:48:19 +01:00
|
|
|
</Paper>
|
|
|
|
</Popper>
|
2020-10-29 20:54:17 +01:00
|
|
|
</Paper>
|
2020-11-28 15:48:19 +01:00
|
|
|
</ClickAwayListener>
|
|
|
|
<Box style={{ marginLeft: "auto" }}>
|
|
|
|
<Tooltip title="Clear all">
|
|
|
|
<IconButton onClick={clearHTTPConfirmationDialog.open}>
|
|
|
|
<DeleteIcon />
|
|
|
|
</IconButton>
|
|
|
|
</Tooltip>
|
|
|
|
</Box>
|
2020-10-29 20:54:17 +01:00
|
|
|
</Box>
|
2020-11-28 15:48:19 +01:00
|
|
|
<ConfirmationDialog
|
|
|
|
isOpen={clearHTTPConfirmationDialog.isOpen}
|
|
|
|
onClose={clearHTTPConfirmationDialog.close}
|
|
|
|
onConfirm={clearHTTPRequestLog}
|
|
|
|
>
|
|
|
|
All proxy logs are going to be removed. This action cannot be undone.
|
|
|
|
</ConfirmationDialog>
|
|
|
|
</Box>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function Error(props: { prefix: string; error?: Error }) {
|
|
|
|
if (!props.error) return null;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Box mb={4}>
|
|
|
|
<Alert severity="error">
|
|
|
|
{props.prefix}: {props.error.message}
|
|
|
|
</Alert>
|
|
|
|
</Box>
|
2020-10-29 20:54:17 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Search;
|