Skip to content

Schema polling autoupdate #934

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Jan 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
a020b26
Merged from sdl-tabs https://github.com/Novvum/graphql-playground.git
Dec 3, 2018
56b0aa8
Added and integrated setting's key for 'schema.disableComments'
Dec 4, 2018
cd5f5d8
Merged changes from disableComments branch
Dec 4, 2018
9c2f2af
Fixes and style changes matching @kuldar's design specs. Details on h…
Dec 5, 2018
545b7e9
Still not able to cmd+save settings. Might be a deeper issue. However…
Dec 5, 2018
b8f4df9
Added tabWidth prop to SideTab.tsx to provide specific widths for dif…
Dec 5, 2018
88cbd48
Fix for Tab Spacing in collapsed state
Dec 6, 2018
79b3cb0
ugly version is done
rohit-ravikoti Dec 12, 2018
a8d3fe6
moved icons to the left
rohit-ravikoti Dec 13, 2018
7859efd
making polling global
rohit-ravikoti Dec 18, 2018
3f5d5e5
updated from v1.8.5
rohit-ravikoti Dec 18, 2018
60d9944
Updates for using 'esc' on keydown to close tabs
Dec 18, 2018
87d73dc
added polling config
rohit-ravikoti Dec 18, 2018
a4ecd48
Updated createSDL.tsx
Dec 19, 2018
daa6a82
Updated from parent/master
Dec 19, 2018
1174343
Fixed Electron
Dec 20, 2018
49ff157
Hiding reload icon if polling is enabled
rohit-ravikoti Dec 21, 2018
c5ac6a8
Initial Commit
Dec 21, 2018
a5337e6
* Updated schema polling icon
rohit-ravikoti Dec 22, 2018
6c8127e
code cleanup
rohit-ravikoti Jan 7, 2019
57d277f
Merged from sdl-tabs https://github.com/Novvum/graphql-playground.git
Dec 3, 2018
1fdef77
Added and integrated setting's key for 'schema.disableComments'
Dec 4, 2018
037002b
Merged changes from disableComments branch
Dec 4, 2018
3b4ff14
Fixes and style changes matching @kuldar's design specs. Details on h…
Dec 5, 2018
b4f3f7c
Added tabWidth prop to SideTab.tsx to provide specific widths for dif…
Dec 5, 2018
1fc04d4
Fix for Tab Spacing in collapsed state
Dec 6, 2018
222bb09
ugly version is done
rohit-ravikoti Dec 12, 2018
75cd23e
moved icons to the left
rohit-ravikoti Dec 13, 2018
a1f8e3b
making polling global
rohit-ravikoti Dec 18, 2018
22bd4e0
Updates for using 'esc' on keydown to close tabs
Dec 18, 2018
3a72782
added polling config
rohit-ravikoti Dec 18, 2018
5a56689
Updated createSDL.tsx
Dec 19, 2018
9a50be0
Fixed Electron
Dec 20, 2018
e462518
Hiding reload icon if polling is enabled
rohit-ravikoti Dec 21, 2018
6364849
* Updated schema polling icon
rohit-ravikoti Dec 22, 2018
cba7c3b
code cleanup
rohit-ravikoti Jan 7, 2019
ca54d41
removed questiomark
rohit-ravikoti Jan 7, 2019
96f175e
Merge branch 'schema-polling' of https://github.com/Novvum/gql-playgr…
rohit-ravikoti Jan 7, 2019
ca0d7d6
removed duplicate funciton
rohit-ravikoti Jan 7, 2019
12f0617
updated files from upstream
rohit-ravikoti Jan 7, 2019
77ac0db
yarn.lock from upstream
rohit-ravikoti Jan 7, 2019
54deb01
using printSchema instead of JSON.stringify to compare schemas
rohit-ravikoti Jan 15, 2019
495d163
reusing reload icon
rohit-ravikoti Jan 16, 2019
c3b6a00
"Refresh to see changes" feature in SCHEMA tab
rohit-ravikoti Jan 16, 2019
4a32a52
disabled animation for polling
rohit-ravikoti Jan 17, 2019
4a5b1ea
changed polling icon and moved back to right side.
rohit-ravikoti Jan 22, 2019
aa4c42a
automatically updating schema view without scrolling when schema updates
rohit-ravikoti Jan 23, 2019
c693704
moved reload icon back to the left
rohit-ravikoti Jan 23, 2019
3e8b147
automatically updating schema view without scrolling when schema updates
rohit-ravikoti Jan 23, 2019
1d642fe
Merge branch 'schema-polling-autoupdate' of https://github.com/Novvum…
rohit-ravikoti Jan 23, 2019
429e65e
more accurate schema diff checking
rohit-ravikoti Jan 23, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions packages/graphql-playground-react/src/components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from '../state/sessions/actions'
import { setConfigString } from '../state/general/actions'
import { initState } from '../state/workspace/actions'
import { GraphQLSchema } from 'graphql'
import { GraphQLSchema, printSchema } from 'graphql'
import { createStructuredSelector } from 'reselect'
import {
getIsConfigTab,
Expand Down Expand Up @@ -140,7 +140,11 @@ export class Playground extends React.PureComponent<Props & ReduxProps, State> {
if (props.schema) {
return
}
if (this.mounted && this.state.schema) {
if (
this.mounted &&
this.state.schema &&
!props.settings['schema.enablePolling']
) {
this.setState({ schema: undefined })
}
let first = true
Expand Down Expand Up @@ -240,6 +244,7 @@ export class Playground extends React.PureComponent<Props & ReduxProps, State> {
async schemaGetter(propsInput?: Props & ReduxProps) {
const props = this.props || propsInput
const endpoint = props.sessionEndpoint || props.endpoint
const currentSchema = this.state.schema
try {
const data = {
endpoint,
Expand All @@ -255,11 +260,11 @@ export class Playground extends React.PureComponent<Props & ReduxProps, State> {
data.endpoint === this.props.endpoint ||
data.endpoint === this.props.sessionEndpoint
) {
this.setState({ schema: newSchema })
this.updateSchema(currentSchema, newSchema, props)
}
})
if (schema) {
this.setState({ schema: schema.schema })
this.updateSchema(currentSchema, schema.schema, props)
this.props.schemaFetchingSuccess(data.endpoint, schema.tracingSupported)
this.backoff.stop()
}
Expand Down Expand Up @@ -346,6 +351,22 @@ export class Playground extends React.PureComponent<Props & ReduxProps, State> {
)
}

private updateSchema(
currentSchema: GraphQLSchema | undefined,
newSchema: GraphQLSchema,
props: Readonly<{ children?: React.ReactNode }> &
Readonly<Props & ReduxProps>,
) {
const currentSchemaStr = currentSchema ? printSchema(currentSchema) : null
const newSchemaStr = printSchema(newSchema)
if (
newSchemaStr !== currentSchemaStr ||
!props.settings['schema.enablePolling']
) {
this.setState({ schema: newSchema })
}
}

get httpApiPrefix() {
return this.props.endpoint.match(/(https?:\/\/.*?)\/?/)![1]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import { GraphQLSchema } from 'graphql'
import { GraphQLSchema, printSchema } from 'graphql'
import EditorWrapper from '../EditorWrapper'
import { styled } from '../../../styled'
import { getSDL } from '../util/createSDL'
Expand Down Expand Up @@ -64,10 +64,12 @@ class SDLEditor extends React.PureComponent<Props, { overflowY: boolean }> {
this.editor.on('scroll', this.handleScroll)
this.editor.refresh()
}

componentDidUpdate(prevProps: Props) {
const CodeMirror = require('codemirror')
if (this.props.schema !== prevProps.schema) {
const currentSchemaStr = this.props.schema && printSchema(this.props.schema)
const prevSchemaStr = prevProps.schema && printSchema(prevProps.schema)
if (currentSchemaStr !== prevSchemaStr) {
const initialScroll = this.editor.getScrollInfo()
this.cachedValue =
getSDL(
this.props.schema,
Expand All @@ -79,6 +81,9 @@ class SDLEditor extends React.PureComponent<Props, { overflowY: boolean }> {
this.props.settings['schema.disableComments'],
),
)
if (this.props.settings['schema.enablePolling']) {
this.editor.scrollTo(initialScroll.left, initialScroll.top)
}
CodeMirror.signal(this.editor, 'change', this.editor)
}
if (this.props.width !== prevProps.width) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ export default class SDLHeader extends React.Component<SDLHeaderProps, State> {

const SchemaHeader = styled.div`
display: flex;
flex-direction: row;
height: 64px;
width: 100%;
margin-right: 108px;
align-items: center;
justify-content: space-between;
justify-content: flex-start;
outline: none;
user-select: none;
`
Expand All @@ -99,7 +101,6 @@ const Box = styled.div`
`

const Title = styled.div`
flex: 1;
color: ${p => styleHelper(p).title};
cursor: default;
font-size: 14px;
Expand All @@ -109,6 +110,7 @@ const Title = styled.div`
letter-spacing: 1px;
user-select: none !important;
padding: 16px;
padding-right: 5px;
`

const Download = styled(Button)`
Expand Down Expand Up @@ -136,6 +138,7 @@ const styleHelper = p => {
if (p.theme.mode === 'dark') {
return {
title: 'white',
subtitle: '#8B959C',
download: {
text: p.open ? '#8B959C' : 'white',
button: p.theme.colours.darkBlue,
Expand All @@ -148,6 +151,7 @@ const styleHelper = p => {
}
return {
title: p.theme.colours.darkBlue,
subtitle: 'rgba(61, 88, 102, 0.5)',
download: {
text: p.open ? 'rgba(61, 88, 102, 0.5)' : p.theme.colours.darkBlue,
button: '#f6f6f6',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface DispatchFromProps {
toggleDocs: (sessionId: string) => any
setDocsVisible: (sessionId: string, open: boolean) => any
changeWidthDocs: (sessionId: string, width: number) => any
setSchemaUpdated: () => void
}

class SDLView extends React.Component<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react'
import PollingIcon from './PollingIcon'

export interface Props {
isPollingSchema: boolean
onReloadSchema: () => void
}

class SchemaPolling extends React.Component<Props> {
timer: any

componentDidMount() {
this.startPolling()
}
componentWillUnmount() {
this.clearTimer()
}
componentWillReceiveProps(nextProps: Props) {
if (nextProps.isPollingSchema !== this.props.isPollingSchema) {
this.startPolling(nextProps)
}
}

render() {
return <PollingIcon animate={true} />
}
private startPolling(props: Props = this.props) {
this.clearTimer()
if (props.isPollingSchema) {
this.timer = setInterval(() => props.onReloadSchema(), 2000)
}
}

private clearTimer() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
}
}

export default SchemaPolling
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as React from 'react'
import { styled, keyframes, css } from '../../../styled/index'
import BasePositioner from './Positioner'

export interface Props {
animate: boolean
disabled?: boolean
onClick?: () => void
}

const PollingIcon: React.SFC<Props> = props => (
<Positioner onClick={props.onClick} title="Polling Schema">
<Icon animate={props.animate} />
</Positioner>
)

export default PollingIcon

const pulse = keyframes`
0% {
box-shadow: 0 0 0 0 rgba(139, 149, 156, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(139, 149, 156, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(139, 149, 156, 0);
}
`

const Positioner = styled(BasePositioner)`
display: flex;
justify-content: center;
align-items: center;
`
const Icon = styled.div`
display: block;
width: 8px;
height: 8px;
border-radius: 50%;
background: ${p => p.theme.editorColours.pollingIcon};
box-shadow: 0 0 0 ${p => p.theme.editorColours.pollingIconShadow};
${p =>
p.animate
? css`
animation: ${pulse} 2s infinite;
`
: undefined};
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { styled } from '../../../styled/index'

export default styled.div`
width: 20px;
height: 20px;
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react'
import ReloadIcon from './ReloadIcon'

export interface Props {
isReloadingSchema: boolean
onReloadSchema?: () => void
}

const Reload: React.SFC<Props> = props => (
<ReloadIcon
animate={props.isReloadingSchema}
onClick={props.onReloadSchema}
/>
)

export default Reload
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
import * as React from 'react'
import { styled, keyframes } from '../../../styled/index'
import { styled, keyframes, css } from '../../../styled/index'
import BasePositioner from './Positioner'

export interface Props {
isReloadingSchema: boolean
onReloadSchema?: () => void
animate: boolean
disabled?: boolean
onClick?: () => void
}

const ReloadIcon: React.SFC<Props> = props => (
<Positioner onClick={props.onReloadSchema} title="Reload Schema">
<Svg viewBox="0 0 20 20">
<Positioner
onClick={props.onClick}
title="Reload Schema"
disabled={props.disabled}
>
<Svg viewBox="0 0 20 20" disabled={props.disabled}>
<Circle
cx="9.5"
cy="10"
r="6"
strokeWidth="1.5"
fill="none"
strokeLinecap="round"
isReloadingSchema={props.isReloadingSchema}
animate={props.animate}
/>
<Icon
d="M4.83 4.86a6.92 6.92 0 0 1 11.3 2.97l.41-1.23c.13-.4.56-.6.95-.47.4.13.6.56.47.95l-1.13 3.33a.76.76 0 0 1-.7.5.72.72 0 0 1-.43-.12l-2.88-1.92a.76.76 0 0 1-.2-1.04.75.75 0 0 1 1.03-.2l1.06.7A5.34 5.34 0 0 0 9.75 4.5a5.44 5.44 0 0 0-5.64 5.22 5.42 5.42 0 0 0 5.24 5.62c.41 0 .74.36.72.78a.75.75 0 0 1-.75.72H9.3a6.9 6.9 0 0 1-6.68-7.18 6.88 6.88 0 0 1 2.22-4.81z"
isReloadingSchema={props.isReloadingSchema}
animate={props.animate}
/>
</Svg>
</Positioner>
Expand Down Expand Up @@ -50,45 +56,42 @@ const refreshFrames = keyframes`
// again the animation
const reloadAction = props => keyframes`
0% {
transform: rotate(${props.isReloadingSchema ? 0 : 360}deg);
transform: rotate(${props.animate ? 0 : 360}deg);
}

100% {
transform: rotate(${props.isReloadingSchema ? 360 : 720}deg);
transform: rotate(${props.animate ? 360 : 720}deg);
}`

const Positioner = styled.div`
position: absolute;
right: 5px;
width: 20px;
height: 20px;
cursor: pointer;
transform: rotateY(180deg);
`

const Svg = styled.svg`
fill: ${p => p.theme.editorColours.icon};
transition: 0.1s linear all;

&:hover {
fill: ${p => p.theme.editorColours.iconHover};
}
${p =>
p.disabled
? undefined
: css`
&:hover {
fill: ${p => p.theme.editorColours.iconHover};
}
`};
`
const Positioner = styled(BasePositioner)`
cursor: ${({ disabled = false }) => (disabled ? 'auto' : 'pointer')};
transform: rotateY(180deg);
`

const Circle = styled<Props, 'circle'>('circle')`
fill: none;
stroke: ${p => p.theme.editorColours.icon};
stroke-dasharray: 37.68;
transition: opacity 0.3s ease-in-out;
opacity: ${p => (p.isReloadingSchema ? 1 : 0)};
opacity: ${p => (p.animate ? 1 : 0)};
transform-origin: 9.5px 10px;
animation: ${refreshFrames} 2s linear
${p => (p.isReloadingSchema ? 'infinite' : '')};
animation: ${refreshFrames} 2s linear ${p => (p.animate ? 'infinite' : '')};
`

const Icon = styled<Props, 'path'>('path')`
transition: opacity 0.3s ease-in-out;
opacity: ${p => (p.isReloadingSchema ? 0 : 1)};
opacity: ${p => (p.animate ? 0 : 1)};
transform-origin: 9.5px 10px;
animation: ${reloadAction} 0.5s linear;
`
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react'
import ReloadIcon from './Reload'
import PollingIcon from './Polling'

export interface Props {
isPollingSchema: boolean
isReloadingSchema: boolean
onReloadSchema: () => any
}

export default (props: Props) => {
if (props.isPollingSchema) {
return (
<PollingIcon
isPollingSchema={props.isPollingSchema}
onReloadSchema={props.onReloadSchema}
/>
)
}
return (
<ReloadIcon
isReloadingSchema={props.isReloadingSchema}
onReloadSchema={props.onReloadSchema}
/>
)
}
Loading