GraphQL UI and Navigation (#335)
* chore(http): check for custom endpoint for caching Signed-off-by: --global <--global> * fix(ui) - typo * fix(migration): template file variable values * fix(install): minio download path Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com> * chore(nginx): precedence x-forward-for ip for geo location tagging Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com> * chore(kafka): change retention to 4 days Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com> * feat(ui) - graphql ui and navigation Co-authored-by: --global <--global> Co-authored-by: Mehdi Osman <estradino@users.noreply.github.com> Co-authored-by: rjshrjndrn <rjshrjndrn@gmail.com>
This commit is contained in:
parent
4eaee22d30
commit
e8a330c053
3 changed files with 122 additions and 52 deletions
|
|
@ -127,10 +127,6 @@ export default class Fetch extends React.PureComponent {
|
|||
<BottomBlock.Header>
|
||||
<h4 className="text-lg">Fetch</h4>
|
||||
<div className="flex items-center">
|
||||
{/* <div className="flex items-center mr-3 text-sm uppercase">
|
||||
<div className="p-2 cursor-pointer" onClick={this.goToPrevError}>Prev</div>
|
||||
<div className="p-2 cursor-pointer" onClick={this.goToNextError}>Next</div>
|
||||
</div> */}
|
||||
<Input
|
||||
className="input-small"
|
||||
placeholder="Filter"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { JSONTree } from 'UI'
|
||||
import { JSONTree, Button } from 'UI'
|
||||
import cn from 'classnames';
|
||||
|
||||
export default class GQLDetails extends React.PureComponent {
|
||||
|
|
@ -7,7 +7,14 @@ export default class GQLDetails extends React.PureComponent {
|
|||
gql: {
|
||||
variables,
|
||||
response,
|
||||
duration,
|
||||
operationKind,
|
||||
operationName,
|
||||
},
|
||||
nextClick,
|
||||
prevClick,
|
||||
first = false,
|
||||
last = false,
|
||||
} = this.props;
|
||||
|
||||
let jsonVars = undefined;
|
||||
|
|
@ -19,28 +26,52 @@ export default class GQLDetails extends React.PureComponent {
|
|||
jsonResponse = JSON.parse(response);
|
||||
} catch (e) {}
|
||||
return (
|
||||
<div className="ph-20" >
|
||||
<div className="divider"/>
|
||||
{ variables && variables !== "{}" &&
|
||||
<div>
|
||||
<div className="mt-6">
|
||||
<h5>{ 'Variables'}</h5>
|
||||
{ jsonVars === undefined
|
||||
? <div className="ml-3"> { variables } </div>
|
||||
: <JSONTree src={ jsonVars } />
|
||||
}
|
||||
<div className="px-4 pb-16">
|
||||
<h5 className="mb-2">{ 'Operation Name'}</h5>
|
||||
<div className={ cn('p-2 bg-gray-lightest rounded color-gray-darkest')}>{ operationName }</div>
|
||||
|
||||
<div className="flex items-center mt-4">
|
||||
<div className="w-4/12">
|
||||
<div className="font-medium mb-2">Operation Kind</div>
|
||||
<div>{operationKind}</div>
|
||||
</div>
|
||||
<div className="w-4/12">
|
||||
<div className="font-medium mb-2">Duration</div>
|
||||
<div>{parseInt(duration)} ms</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-start mt-6">
|
||||
<h5 className="mt-1 mr-1">{ 'Response' }</h5>
|
||||
</div>
|
||||
<div style={{ height: 'calc(100vh - 314px)', overflowY: 'auto' }}>
|
||||
{ variables && variables !== "{}" &&
|
||||
<div>
|
||||
<div className="mt-2">
|
||||
<h5>{ 'Variables'}</h5>
|
||||
{ jsonVars === undefined
|
||||
? <div className="ml-3"> { variables } </div>
|
||||
: <JSONTree src={ jsonVars } />
|
||||
}
|
||||
</div>
|
||||
<div className="divider"/>
|
||||
</div>
|
||||
<div className="divider"/>
|
||||
</div>
|
||||
}
|
||||
<div className="mt-6">
|
||||
<div className="flex justify-between items-start">
|
||||
<h5 className="mt-1 mr-1">{ 'Response' }</h5>
|
||||
</div>
|
||||
{ jsonResponse === undefined
|
||||
? <div className="ml-3"> { response } </div>
|
||||
: <JSONTree src={ jsonResponse } />
|
||||
}
|
||||
<div className="mt-3">
|
||||
{ jsonResponse === undefined
|
||||
? <div className="ml-3"> { response } </div>
|
||||
: <JSONTree src={ jsonResponse } />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between absolute bottom-0 left-0 right-0 p-3 border-t bg-white">
|
||||
<Button primary plain onClick={prevClick} disabled={first}>
|
||||
Prev
|
||||
</Button>
|
||||
<Button primary plain onClick={nextClick} disabled={last}>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
//import cn from 'classnames';
|
||||
import { Icon, NoContent, Input, SlideModal } from 'UI';
|
||||
import { Label, Icon, NoContent, Input, SlideModal, CloseButton } from 'UI';
|
||||
import { getRE } from 'App/utils';
|
||||
import { connectPlayer } from 'Player';
|
||||
import Autoscroll from '../Autoscroll';
|
||||
import { connectPlayer, pause, jump } from 'Player';
|
||||
import BottomBlock from '../BottomBlock';
|
||||
import TimeTable from '../TimeTable';
|
||||
import GQLDetails from './GQLDetails';
|
||||
|
|
@ -10,60 +8,105 @@ import GQLDetails from './GQLDetails';
|
|||
function renderDefaultStatus() {
|
||||
return "2xx-3xx";
|
||||
}
|
||||
|
||||
@connectPlayer(state => ({
|
||||
list: state.graphqlListNow,
|
||||
livePlay: state.livePlay,
|
||||
}))
|
||||
export default class GraphQL extends React.PureComponent {
|
||||
state = {
|
||||
filter: "",
|
||||
filter: "",
|
||||
filteredList: this.props.list,
|
||||
current: null,
|
||||
currentIndex: 0,
|
||||
showFetchDetails: false,
|
||||
hasNextError: false,
|
||||
hasPreviousError: false,
|
||||
}
|
||||
onFilterChange = (e, { value }) => this.setState({ filter: value })
|
||||
|
||||
setCurrent = (item) => {
|
||||
this.setState({ current: item });
|
||||
onFilterChange = (e, { value }) => {
|
||||
const { list } = this.props;
|
||||
const filterRE = getRE(value, 'i');
|
||||
const filtered = list
|
||||
.filter((r) => filterRE.test(r.name) || filterRE.test(r.url) || filterRE.test(r.method) || filterRE.test(r.status));
|
||||
this.setState({ filter: value, filteredList: value ? filtered : list, currentIndex: 0 });
|
||||
}
|
||||
|
||||
setCurrent = (item, index) => {
|
||||
if (!this.props.livePlay) {
|
||||
pause();
|
||||
jump(item.time)
|
||||
}
|
||||
this.setState({ current: item, currentIndex: index });
|
||||
}
|
||||
|
||||
closeModal = () => this.setState({ current: null, showFetchDetails: false });
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
const { filteredList } = prevState;
|
||||
if (nextProps.timelinePointer) {
|
||||
let activeItem = filteredList.find((r) => r.time >= nextProps.timelinePointer.time);
|
||||
activeItem = activeItem || filteredList[filteredList.length - 1];
|
||||
return {
|
||||
current: activeItem,
|
||||
currentIndex: filteredList.indexOf(activeItem),
|
||||
};
|
||||
}
|
||||
}
|
||||
closeModal = () => this.setState({ current: null})
|
||||
|
||||
render() {
|
||||
const { list } = this.props;
|
||||
const { filter, current } = this.state;
|
||||
const filterRE = getRE(filter, 'i');
|
||||
const filtered = list
|
||||
.filter(({ operationName = "", operationKind = "" }) => filterRE.test(operationName) || filterRE.test(operationKind));
|
||||
|
||||
const { current, currentIndex, filteredList } = this.state;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SlideModal
|
||||
size="middle"
|
||||
title={ current && <span><i className="color-gray-medium">{current.operationKind}</i> {current.operationName}</span> }
|
||||
right
|
||||
title = {
|
||||
<div className="flex justify-between">
|
||||
<h1>GraphQL</h1>
|
||||
<div className="flex items-center">
|
||||
<CloseButton onClick={ this.closeModal } size="18" className="ml-2" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
isDisplayed={ current != null }
|
||||
content={ current &&
|
||||
<GQLDetails gql={ current }/>
|
||||
<GQLDetails
|
||||
gql={ current }
|
||||
nextClick={this.nextClickHander}
|
||||
prevClick={this.prevClickHander}
|
||||
first={currentIndex === 0}
|
||||
last={currentIndex === filteredList.length - 1}
|
||||
/>
|
||||
}
|
||||
onClose={ this.closeModal }
|
||||
/>
|
||||
<BottomBlock>
|
||||
<BottomBlock.Header>
|
||||
<Input
|
||||
className="input-small"
|
||||
placeholder="Filter by Name or Type"
|
||||
icon="search"
|
||||
iconPosition="left"
|
||||
name="filter"
|
||||
onChange={ this.onFilterChange }
|
||||
/>
|
||||
<h4 className="text-lg">GraphQL</h4>
|
||||
<div className="flex items-center">
|
||||
<Input
|
||||
className="input-small"
|
||||
placeholder="Filter by Name or Type"
|
||||
icon="search"
|
||||
iconPosition="left"
|
||||
name="filter"
|
||||
onChange={ this.onFilterChange }
|
||||
/>
|
||||
</div>
|
||||
</BottomBlock.Header>
|
||||
<BottomBlock.Content>
|
||||
<NoContent
|
||||
size="small"
|
||||
show={ filtered.length === 0}
|
||||
show={ filteredList.length === 0}
|
||||
>
|
||||
<TimeTable
|
||||
rows={ filtered }
|
||||
rows={ filteredList }
|
||||
onRowClick={ this.setCurrent }
|
||||
hoverable
|
||||
navigation
|
||||
activeIndex={currentIndex}
|
||||
>
|
||||
{[
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue