Skip to content
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

Fix :style / GraSS regressions #772

Merged
merged 6 commits into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
57 changes: 57 additions & 0 deletions e2e_tests/integration/style.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/* global Cypress, cy, test, expect */

describe(':style', () => {
it('can connect', () => {
const password = Cypress.env('BROWSER_NEW_PASSWORD') || 'newpassword'
cy.connect('neo4j', password)
})
it('print the current style', () => {
cy.executeCommand(':clear')
cy.executeCommand('CREATE (n:Style) RETURN n') // To generate any style
const query = ':style'
cy.executeCommand(query)
cy
.get('[data-test-id="frameCommand"]', { timeout: 10000 })
.first()
.should('contain', query)
cy
.get('[data-test-id="frameContents"]', { timeout: 10000 })
.first()
.should('contain', 'node {')
.should('contain', 'relationship {')
.should('contain', '"<type>"')
})
it('can reset style with button', () => {
cy.executeCommand(':clear')
cy.executeCommand(':style')
cy.get('[data-test-id="exportGrassButton"]', { timeout: 10000 })
cy
.get('[data-test-id="styleResetButton"]', { timeout: 10000 })
.first()
.click()
cy
.get('[data-test-id="frameContents"]', { timeout: 10000 })
.first()
.should('contain', 'No style generated or set yet')
})
})
4 changes: 4 additions & 0 deletions src/browser/components/icons/Icons.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,7 @@ export const Spinner = () => (
export const ExclamationTriangleIcon = () => (
<IconContainer suppressIconStyles className='fa fa-exclamation-triangle' />
)

export const FireExtinguisherIcon = ({ title = 'Reset' }) => (
<IconContainer className='fa fa-fire-extinguisher' title={title} />
)
2 changes: 1 addition & 1 deletion src/browser/modules/Sidebar/FileDrop.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { connect } from 'preact-redux'
import Dropzone from 'react-dropzone'

import { addFavorite } from 'shared/modules/favorites/favoritesDuck'
import { parseGrass } from 'shared/modules/commands/helpers/grass'
import { parseGrass } from 'shared/services/grassUtils'
import { updateGraphStyleData } from 'shared/modules/grass/grassDuck'
import { showErrorMessage } from 'shared/modules/commands/commandsDuck'

Expand Down
37 changes: 27 additions & 10 deletions src/browser/modules/Stream/FrameTitlebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,24 @@ class FrameTitlebar extends Component {
const { svgElement, graphElement, type } = this.props.visElement
downloadPNGFromSVG(svgElement, graphElement, type)
}

exportSVG () {
const { svgElement, graphElement, type } = this.props.visElement
downloadSVG(svgElement, graphElement, type)
}

exportGrass (data) {
var blob = new Blob([data], {
type: 'text/plain;charset=utf-8'
})
saveAs(blob, 'style.grass')
}
canExport = () => {
let props = this.props
const { frame = {} } = props
return (
(frame.type === 'cypher' && (this.hasData() || props.visElement)) ||
(frame.type === 'style' && this.hasData())
)
}
render () {
let props = this.props
const { frame = {} } = props
Expand All @@ -104,9 +116,7 @@ class FrameTitlebar extends Component {
</DottedLineHover>
</StyledFrameCommand>
<FrameTitlebarButtonSection>
<Render
if={frame.type === 'cypher' && (this.hasData() || props.visElement)}
>
<Render if={this.canExport()}>
<DropdownButton>
<DownloadIcon />
<DropdownList>
Expand All @@ -121,13 +131,21 @@ class FrameTitlebar extends Component {
</DropdownItem>
</span>
</Render>
<Render if={this.hasData()}>
<Render if={this.hasData() && frame.type === 'cypher'}>
<DropdownItem
onClick={() => this.exportCSV(props.getRecords())}
>
Export CSV
</DropdownItem>
</Render>
<Render if={this.hasData() && frame.type === 'style'}>
<DropdownItem
data-test-id='exportGrassButton'
onClick={() => this.exportGrass(props.getRecords())}
>
Export GraSS
</DropdownItem>
</Render>
</DropdownContent>
</DropdownList>
</DropdownButton>
Expand All @@ -142,9 +160,7 @@ class FrameTitlebar extends Component {
>
<PinIcon />
</FrameButton>
<Render
if={['cypher', 'play', 'play-remote'].indexOf(frame.type) > -1}
>
<Render if={['cypher', 'play', 'play-remote'].includes(frame.type)}>
<FrameButton
title={props.fullscreen ? 'Close fullscreen' : 'Fullscreen'}
onClick={() => props.fullscreenToggle()}
Expand All @@ -158,8 +174,9 @@ class FrameTitlebar extends Component {
>
{expandCollapseIcon}
</FrameButton>
<Render if={frame.type === 'cypher'}>
<Render if={['cypher', 'style'].includes(frame.type)}>
<FrameButton
data-test-id='rerunFrameButton'
title='Rerun'
onClick={() =>
props.onReRunClick(frame.cmd, frame.id, frame.requestId)}
Expand Down
50 changes: 50 additions & 0 deletions src/browser/modules/Stream/InfoView.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component } from 'preact'
import {
StyledInfoMessage,
StyledHelpContent,
StyledH4,
StyledHelpDescription,
StyledDiv,
StyledHelpFrame
} from './styled'

export class InfoView extends Component {
shouldComponentUpdate (props, state) {
return false
}
render () {
const { title, description } = this.props
return (
<StyledHelpFrame>
<StyledHelpContent>
<StyledHelpDescription>
<StyledInfoMessage>INFO</StyledInfoMessage>
<StyledH4>{title}</StyledH4>
</StyledHelpDescription>
<StyledDiv>
<StyledHelpDescription>{description}</StyledHelpDescription>
</StyledDiv>
</StyledHelpContent>
</StyledHelpFrame>
)
}
}
2 changes: 2 additions & 0 deletions src/browser/modules/Stream/Stream.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import ParamsFrame from './ParamsFrame'
import ErrorFrame from './ErrorFrame'
import HelpFrame from './HelpFrame'
import SchemaFrame from './SchemaFrame'
import StyleFrame from './StyleFrame'
import SysInfoFrame from './SysInfoFrame'
import ConnectionFrame from './Auth/ConnectionFrame'
import DisconnectFrame from './Auth/DisconnectFrame'
Expand Down Expand Up @@ -67,6 +68,7 @@ const getFrame = type => {
status: ServerStatusFrame,
'switch-success': ServerSwitchFrame,
'switch-fail': ServerSwitchFrame,
style: StyleFrame,
default: Frame
}
return trans[type] || trans['default']
Expand Down
101 changes: 101 additions & 0 deletions src/browser/modules/Stream/StyleFrame.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) 2002-2018 "Neo4j, Inc"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { connect } from 'preact-redux'
import FrameTemplate from './FrameTemplate'
import {
PaddedDiv,
StyledOneRowStatsBar,
StyledRightPartial,
FrameTitlebarButtonSection
} from './styled'
import { FrameButton } from 'browser-components/buttons'
import { objToCss } from 'services/grassUtils'
import {
executeSystemCommand,
executeCommand
} from 'shared/modules/commands/commandsDuck'
import { getCmdChar } from 'shared/modules/settings/settingsDuck'
import { FireExtinguisherIcon } from 'browser-components/icons/Icons'
import { InfoView } from './InfoView'

const StyleFrame = ({ frame }) => {
let grass = ''
let contents = (
<InfoView
title='No styles yet'
description='No style generated or set yet. Run a query and return a few nodes and
relationships to generate some styling.'
/>
)
if (frame.result) {
grass = objToCss(frame.result)
contents = (
<PaddedDiv>
<pre>
{grass ||
'Something went wrong when parsing the GraSS. Please reset and try again.'}
</pre>
</PaddedDiv>
)
}
return (
<FrameTemplate
header={frame}
numRecords={1}
getRecords={() => grass}
contents={contents}
statusbar={<Statusbar frame={frame} />}
/>
)
}

const StyleStatusbar = ({ resetStyleAction, rerunAction, onResetClick }) => {
return (
<StyledOneRowStatsBar>
<StyledRightPartial>
<FrameTitlebarButtonSection>
<FrameButton
data-test-id='styleResetButton'
onClick={() => onResetClick(resetStyleAction, rerunAction)}
>
<FireExtinguisherIcon title='Reset style' />
</FrameButton>
</FrameTitlebarButtonSection>
</StyledRightPartial>
</StyledOneRowStatsBar>
)
}

const mapStateToProps = (state, ownProps) => {
return {
resetStyleAction: executeSystemCommand(`${getCmdChar(state)}style reset`),
rerunAction: executeCommand(ownProps.frame.cmd, ownProps.frame.id)
}
}
const mapDispatchToProps = dispatch => ({
onResetClick: (resetStyleAction, rerunAction) => {
dispatch(resetStyleAction)
dispatch(rerunAction)
}
})

const Statusbar = connect(mapStateToProps, mapDispatchToProps)(StyleStatusbar)

export default StyleFrame
8 changes: 6 additions & 2 deletions src/browser/modules/Stream/styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,16 @@ export const StyledCypherMessage = styled.div`
float: left;
`
export const StyledCypherWarningMessage = styled(StyledCypherMessage)`
background-color: #ffa500;
background-color: ${props => props.theme.warning};
color: #ffffff;
`

export const StyledCypherErrorMessage = styled(StyledCypherMessage)`
background-color: #e74c3c;
background-color: ${props => props.theme.error};
color: #ffffff;
`
export const StyledInfoMessage = styled(StyledCypherMessage)`
background-color: ${props => props.theme.info};
color: #ffffff;
`

Expand Down
1 change: 1 addition & 0 deletions src/browser/styles/themes.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const base = {
error: '#E74C3C',
warning: '#FD952C',
auth: '#428BCA',
info: '#428BCA',

// Buttons
primaryButtonText: '#fff',
Expand Down
4 changes: 2 additions & 2 deletions src/shared/modules/commands/commandsDuck.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,8 @@ describe('commandsDuck', () => {
{ type: commands.KNOWN_COMMAND },
frames.add({
...action,
type: 'pre',
result: JSON.stringify({ node: { color: '#000' } }, null, 2)
type: 'style',
result: { node: { color: '#000' } }
}),
{ type: 'NOOP' }
])
Expand Down
Loading