Skip to content

Commit

Permalink
Added support for explicit lambdas
Browse files Browse the repository at this point in the history
    - Added new dep @neo4j/browser-lambda-parser
    - Updated existing cmd utils to use parser for all things lambda
    - Standardized and cleaned up error frames appearance regardless of source
    - Added new help text for :param
    - Standardized appearance of :help buttons and Error frames
  • Loading branch information
huboneo committed Aug 27, 2019
1 parent 2aad3e3 commit a999616
Show file tree
Hide file tree
Showing 15 changed files with 328 additions and 91 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
"xml2js": "^0.4.19"
},
"dependencies": {
"@neo4j/browser-lambda-parser": "1.0.0",
"ascii-data-table": "^2.1.1",
"classnames": "^2.2.5",
"codemirror": "^5.29.0",
Expand All @@ -136,6 +137,7 @@
"firebase": "^5.8.3",
"isomorphic-fetch": "^2.2.1",
"jsonic": "^0.3.0",
"lodash-es": "^4.17.15",
"mockdate": "^2.0.5",
"neo4j-driver": "^1.7.5",
"react": "^16.9.0",
Expand Down
4 changes: 1 addition & 3 deletions src/browser/components/Directives.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ export const Directives = props => {
const elems = elem.querySelectorAll(directive.selector)
Array.from(elems).forEach(e => {
if (e.firstChild.nodeName !== 'I') {
directive.selector === '[help-topic]'
? prependHelpIcon(e)
: prependPlayIcon(e)
prependPlayIcon(e)
}

e.onclick = () => {
Expand Down
6 changes: 6 additions & 0 deletions src/browser/modules/Help/html/param.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
<code>:param x => 1</code> and to set it as a float, do
<code>:param x => 1.0</code>.
</p>
<p>
If you need more fine-grained control or advanced Cypher queries, you can use the explicit syntax: <code>x => { ... RETURN 1 as foo }</code>
<br/> Explicit returns yield a list of records, matching that of your Cypher query: <code>x => { RETURN 1 as foo }</code> yields <code>$x = [{foo: 1}]</code>
<br/> You can pick out individual values from your result using destructuring: <code> [{foo}] => { RETURN 1 as foo }</code> yields <code>$foo = 1</code>
<br/> You can also rename destructured params: <code> [{foo: bar}] => { RETURN 1 as foo }</code> yields <code>$bar = 1</code>
</p>
<p>Cypher query example with a param:&nbsp;
<code>MATCH (n:Person) WHERE n.name = $name</code>
</p>
Expand Down
22 changes: 7 additions & 15 deletions src/browser/modules/Main/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,17 @@ import {
import Editor from '../Editor/Editor'
import Stream from '../Stream/Stream'
import Render from 'browser-components/Render'
import ClickToCode from '../ClickToCode'
import {
StyledMain,
WarningBanner,
ErrorBanner,
NotAuthedBanner,
StyledCodeBlockAuthBar,
StyledCodeBlockErrorBar
NotAuthedBanner
} from './styled'
import SyncReminderBanner from './SyncReminderBanner'
import SyncConsentBanner from './SyncConsentBanner'
import ErrorBoundary from 'browser-components/ErrorBoundary'
import { useSlowConnectionState } from './main.hooks'
import AutoExecButton from '../Stream/auto-exec-button'

const Main = React.memo(function Main (props) {
const [past5Sec, past10Sec] = useSlowConnectionState(props)
Expand All @@ -51,11 +49,8 @@ const Main = React.memo(function Main (props) {
<Render if={props.showUnknownCommandBanner}>
<ErrorBanner>
Type&nbsp;
<ClickToCode CodeComponent={StyledCodeBlockErrorBar}>
{props.cmdchar}
help commands
</ClickToCode>
&nbsp; for a list of available commands.
<AutoExecButton cmd={`${props.cmdchar}help commands`} />
&nbsp;for a list of available commands.
</ErrorBanner>
</Render>
<Render if={props.errorMessage}>
Expand All @@ -66,13 +61,10 @@ const Main = React.memo(function Main (props) {
<Render if={props.connectionState === DISCONNECTED_STATE}>
<NotAuthedBanner data-testid='disconnectedBanner'>
Database access not available. Please use&nbsp;
<ClickToCode
<AutoExecButton
cmd={`${props.cmdchar}server connect`}
data-testid='disconnectedBannerCode'
CodeComponent={StyledCodeBlockAuthBar}
>
{props.cmdchar}
server connect
</ClickToCode>
/>
&nbsp; to establish connection. There's a graph waiting for you.
</NotAuthedBanner>
</Render>
Expand Down
6 changes: 3 additions & 3 deletions src/browser/modules/Stream/CypherFrame/ErrorsView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { errorMessageFormater } from './../errorMessageFormater'
import {
StyledCypherErrorMessage,
StyledHelpContent,
StyledH4,
StyledErrorH4,
StyledPreformattedArea,
StyledHelpDescription,
StyledDiv,
Expand All @@ -54,14 +54,14 @@ export class ErrorsView extends Component {
if (!error || !error.code) {
return null
}
const fullError = errorMessageFormater(error.code, error.message)
const fullError = errorMessageFormater(null, error.message)

return (
<StyledHelpFrame>
<StyledHelpContent>
<StyledHelpDescription>
<StyledCypherErrorMessage>ERROR</StyledCypherErrorMessage>
<StyledH4>{error.code}</StyledH4>
<StyledErrorH4>{error.code}</StyledErrorH4>
</StyledHelpDescription>
<StyledDiv>
<StyledPreformattedArea>{fullError.message}</StyledPreformattedArea>
Expand Down
5 changes: 3 additions & 2 deletions src/browser/modules/Stream/CypherFrame/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,14 @@ export class CypherFrame extends Component {
this.getFrameContents(request, result, query)
)
const statusBar =
this.state.openView !== viewTypes.VISUALIZATION
this.state.openView !== viewTypes.VISUALIZATION &&
requestStatus !== 'error'
? this.getStatusbar(result)
: null

return (
<FrameTemplate
sidebar={this.sidebar}
sidebar={requestStatus !== 'error' ? this.sidebar : null}
header={frame}
contents={frameContents}
statusbar={statusBar}
Expand Down
22 changes: 18 additions & 4 deletions src/browser/modules/Stream/ErrorFrame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react'

import FrameTemplate from './FrameTemplate'
import * as e from 'services/exceptionMessages'
import { createErrorObject } from 'services/exceptions'
import { createErrorObject, UnknownCommandError } from 'services/exceptions'
import { errorMessageFormater } from './errorMessageFormater'
import {
StyledCypherErrorMessage,
StyledHelpContent,
StyledH4,
StyledErrorH4,
StyledPreformattedArea,
StyledHelpDescription,
StyledDiv,
StyledHelpFrame
} from './styled'
import AutoExecButton from './auto-exec-button'

export const ErrorView = ({ frame }) => {
if (!frame) return null
Expand All @@ -41,18 +43,30 @@ export const ErrorView = ({ frame }) => {
const eObj = createErrorObject(errorCode, error)
errorContents = eObj.message
}
const fullError = errorMessageFormater(errorCode, errorContents)
const fullError = errorMessageFormater(null, errorContents)
return (
<StyledHelpFrame>
<StyledHelpContent>
<StyledHelpDescription>
<StyledCypherErrorMessage>ERROR</StyledCypherErrorMessage>
<StyledH4>{errorCode}</StyledH4>
<StyledErrorH4>{errorCode}</StyledErrorH4>
</StyledHelpDescription>
<StyledDiv>
<StyledPreformattedArea>{fullError.message}</StyledPreformattedArea>
</StyledDiv>
</StyledHelpContent>
{frame.showHelpForCmd ? (
<>
Use <AutoExecButton cmd={`help ${frame.showHelpForCmd}`} /> for more
information.
</>
) : null}
{errorCode === UnknownCommandError.name ? (
<>
Use <AutoExecButton cmd={'help commands'} /> to list available
commands.
</>
) : null}
</StyledHelpFrame>
)
}
Expand Down
9 changes: 3 additions & 6 deletions src/browser/modules/Stream/ParamsFrame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { stringifyMod } from 'services/utils'
import FrameTemplate from './FrameTemplate'
import { PaddedDiv, ErrorText, SuccessText, StyledStatsBar } from './styled'
import { applyGraphTypes } from 'services/bolt/boltMappings'
import ClickToCode from 'browser/modules/ClickToCode'
import AutoExecButton from './auto-exec-button'

const ParamsFrame = ({ frame }) => {
const params = applyGraphTypes(frame.params)
Expand All @@ -38,11 +38,8 @@ const ParamsFrame = ({ frame }) => {
</pre>
</Render>
<div style={{ marginTop: '20px' }}>
See{' '}
<ClickToCode code=':help param' execute>
:help param
</ClickToCode>{' '}
for usage of the <code>:param</code> command.
See <AutoExecButton cmd='help param' /> for usage of the{' '}
<code>:param</code> command.
</div>
</PaddedDiv>
)
Expand Down
65 changes: 65 additions & 0 deletions src/browser/modules/Stream/auto-exec-button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2002-2019 "Neo4j,"
* Neo4j Sweden AB [http://neo4j.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 React, { useCallback } from 'react'
import { connect } from 'react-redux'
import { withBus } from 'react-suber'
import styled from 'styled-components'

import { executeCommand } from '../../../shared/modules/commands/commandsDuck'

const StyledAutoExecButton = styled.button`
border-radius: 3px;
border: 1px solid #dadada;
display: inline-block;
font-family: Monaco, 'Courier New', Terminal, monospace;
font-size: 12px;
line-height: 18px;
padding: 0 4px;
color: #428bca;
cursor: pointer;
text-decoration: none;
background-color: #f8f8f8;
outline: transparent;
`

function AutoExecButtonComponent ({ bus, cmd, cmdChar }) {
const onClick = useCallback(
() => {
const action = executeCommand(`${cmdChar}${cmd}`)

bus.send(action.type, action)
},
[cmd]
)

return (
<StyledAutoExecButton type='button' onClick={onClick}>
<i className='fa fa-play-circle-o' /> {cmdChar}
{cmd}
</StyledAutoExecButton>
)
}

const mapStateToProps = ({ settings }) => ({
cmdChar: settings.cmdchar
})
const AutoExecButton = withBus(
connect(mapStateToProps)(AutoExecButtonComponent)
)

export default AutoExecButton
4 changes: 4 additions & 0 deletions src/browser/modules/Stream/styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ export const StyledInfoMessage = styled(StyledCypherMessage)`

export const StyledH4 = styled.h4``

export const StyledErrorH4 = styled.h4`
display: inline-block;
`

export const StyledBr = styled.br``

export const StyledPreformattedArea = styled.pre`
Expand Down
1 change: 1 addition & 0 deletions src/shared/modules/commands/commandsDuck.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export const showErrorMessage = errorMessage => ({
type: SHOW_ERROR_MESSAGE,
errorMessage: errorMessage
})

export const clearErrorMessage = () => ({
type: CLEAR_ERROR_MESSAGE
})
Expand Down
Loading

0 comments on commit a999616

Please sign in to comment.