diff --git a/src/browser/modules/D3Visualization/components/Explorer.jsx b/src/browser/modules/D3Visualization/components/Explorer.jsx index 523eb39705a..3831373bdb2 100644 --- a/src/browser/modules/D3Visualization/components/Explorer.jsx +++ b/src/browser/modules/D3Visualization/components/Explorer.jsx @@ -68,7 +68,7 @@ export class ExplorerComponent extends Component { - + diff --git a/src/browser/modules/D3Visualization/components/Graph.jsx b/src/browser/modules/D3Visualization/components/Graph.jsx index 3a16ab93bfc..72fe5d9628b 100644 --- a/src/browser/modules/D3Visualization/components/Graph.jsx +++ b/src/browser/modules/D3Visualization/components/Graph.jsx @@ -2,6 +2,7 @@ import { Component } from 'preact' import {createGraph, mapNodes, mapRelationships, getGraphStats} from '../mapper' import {GraphEventHandler} from '../GraphEventHandler' import '../lib/visualization/index' +import { dim } from 'browser-styles/constants' export class GraphComponent extends Component { @@ -9,11 +10,21 @@ export class GraphComponent extends Component { this.state.el = el } + getVisualAreaHeight () { + if (this.props.frameHeight && this.props.fullscreen) { + return this.props.frameHeight - (dim.frameStatusbarHeight + dim.frameTitlebarHeight * 2) + } else { + return this.state.el.parentNode.offsetHeight + } + } + componentDidMount () { if (this.state.el != null) { if (!this.graphView) { let NeoConstructor = neo.graphView - let measureSize = () => { return {width: this.state.el.offsetWidth, height: this.state.el.parentNode.offsetHeight} } + let measureSize = () => { + return {width: this.state.el.offsetWidth, height: this.getVisualAreaHeight()} + } this.graph = createGraph(this.props.nodes, this.props.relationships) this.graphView = new NeoConstructor(this.state.el, measureSize, this.graph, this.props.graphStyle) new GraphEventHandler(this.graph, @@ -40,6 +51,18 @@ export class GraphComponent extends Component { this.graphView.update() this.state.currentStyleRules = nextProps.graphStyle.toString() } + + if (this.props.fullscreen !== nextProps.fullscreen || this.props.frameHeight !== nextProps.frameHeight) { + this.setState({shouldResize: true}) + } else { + this.setState({shouldResize: false}) + } + } + + componentDidUpdate () { + if (this.state.shouldResize) { + this.graphView.resize() + } } render () { diff --git a/src/browser/modules/D3Visualization/lib/visualization/index.js b/src/browser/modules/D3Visualization/lib/visualization/index.js index 0dc9ceaaa51..ee69fdf5cab 100644 --- a/src/browser/modules/D3Visualization/lib/visualization/index.js +++ b/src/browser/modules/D3Visualization/lib/visualization/index.js @@ -5,7 +5,6 @@ import '../../lib/visualization/components/graphGeometry' import '../../lib/visualization/components/graphView' import '../../lib/visualization/components/layout' import '../../lib/visualization/components/node' -import '../../lib/visualization/components/queryPlan' import '../../lib/visualization/components/relationship' import '../../lib/visualization/components/renderer' import '../../lib/visualization/components/style' diff --git a/src/browser/modules/Stream/CypherFrame.jsx b/src/browser/modules/Stream/CypherFrame.jsx index 7f7fc064323..c1c225ea23c 100644 --- a/src/browser/modules/Stream/CypherFrame.jsx +++ b/src/browser/modules/Stream/CypherFrame.jsx @@ -12,12 +12,13 @@ import bolt from 'services/bolt/bolt' import Visualization from './Visualization' import FrameError from './FrameError' import * as viewTypes from 'shared/modules/stream/frameViewTypes' +import { StyledFrameBody } from './styled' class CypherFrame extends Component { constructor (props) { super(props) this.state = { - openView: 'visualization', + openView: viewTypes.VISUALIZATION, plan: null, notifications: null } @@ -122,6 +123,18 @@ class CypherFrame extends Component { ) } + getDisplayStyle (viewType) { + return this.state.openView === viewType ? {display: 'block'} : {display: 'none'} + } + + onResize (fullscreen, collapse, frameHeight) { + if (frameHeight) { + this.setState({fullscreen, collapse, frameHeight}) + } else { + this.setState({fullscreen, collapse}) + } + } + render () { const frame = this.props.frame const errors = this.props.request.status === 'error' ? this.props.request.result : false @@ -144,29 +157,15 @@ class CypherFrame extends Component { if (result.records && result.records.length > 0) { this.state.rows = this.state.rows || bolt.recordsToTableArray(result.records) } - - switch (this.state.openView) { - case viewTypes.TEXT: - frameContents = - break - case viewTypes.TABLE: - frameContents = - break - case viewTypes.VISUALIZATION: - frameContents = - break - case viewTypes.CODE: - frameContents = - break - case viewTypes.PLAN: - frameContents = - break - case viewTypes.WARNINGS: - frameContents = - break - default: - frameContents = - } + frameContents = + + + + + + + + } else if (result) { frameContents = (
@@ -187,6 +186,7 @@ class CypherFrame extends Component { contents={frameContents} exportData={this.state.rows} statusbar={statusBar} + onResize={this.onResize.bind(this)} /> ) } diff --git a/src/browser/modules/Stream/FrameTemplate.jsx b/src/browser/modules/Stream/FrameTemplate.jsx index f724efb2d84..eeac2c84387 100644 --- a/src/browser/modules/Stream/FrameTemplate.jsx +++ b/src/browser/modules/Stream/FrameTemplate.jsx @@ -1,27 +1,33 @@ import { Component } from 'preact' import FrameTitlebar from './FrameTitlebar' import Visible from 'browser-components/Visible' -import { StyledFrame, StyledFullscreenFrame, StyledFrameBody, StyledFrameContents, StyledFrameStatusbar, StyledFrameMainSection } from './styled' +import { StyledFrame, StyledFrameBody, StyledFrameContents, StyledFrameStatusbar, StyledFrameMainSection } from './styled' class FrameTemplate extends Component { constructor (props) { super(props) this.state = { fullscreen: false, - collapse: false, - wasToggledToOrFromFullScreen: false - } + collapse: false} } toggleFullScreen () { - this.setState({fullscreen: !this.state.fullscreen, wasToggledToOrFromFullScreen: true}) + this.setState({fullscreen: !this.state.fullscreen}, () => this.props.onResize && this.props.onResize(this.state.fullscreen, this.state.collapse, this.lastHeight)) } toggleCollapse () { - this.setState({collapse: !this.state.collapse}) + this.setState({collapse: !this.state.collapse}, () => this.props.onResize && this.props.onResize(this.state.fullscreen, this.state.collapse, this.lastHeight)) + } + componentDidUpdate () { + if (this.frameContentElement && this.lastHeight !== this.frameContentElement.base.clientHeight) { + this.lastHeight = this.frameContentElement.base.clientHeight + this.props.onResize && this.props.onResize(this.state.fullscreen, this.state.collapse, this.lastHeight) + } + } + setFrameContentElement (el) { + this.frameContentElement = el } render () { - const FrameComponent = this.state.fullscreen ? StyledFullscreenFrame : StyledFrame return ( - + {(this.props.sidebar) ? this.props.sidebar() : null} - + {this.props.contents} @@ -41,7 +47,7 @@ class FrameTemplate extends Component { - + ) } } diff --git a/src/browser/modules/Stream/Planner/QueryPlan.jsx b/src/browser/modules/Stream/Planner/QueryPlan.jsx index 956119a1c17..4e62222da45 100644 --- a/src/browser/modules/Stream/Planner/QueryPlan.jsx +++ b/src/browser/modules/Stream/Planner/QueryPlan.jsx @@ -12,8 +12,12 @@ class QueryPlan extends Component { } render () { + if (!this.props.plan) { + return + } + return ( - + ) } } diff --git a/src/browser/modules/Stream/Views/AsciiView.jsx b/src/browser/modules/Stream/Views/AsciiView.jsx index 570f30881c0..c6e72817969 100644 --- a/src/browser/modules/Stream/Views/AsciiView.jsx +++ b/src/browser/modules/Stream/Views/AsciiView.jsx @@ -1,8 +1,11 @@ import asciitable from 'ascii-data-table' -const AsciiView = ({rows}) => { - if (!rows) return (No results found) - return
{asciitable.table(rows, 70)}
+const AsciiView = ({rows, style}) => { + if (!rows) { + return (
No results found
) + } + + return
{asciitable.table(rows, 70)}
} export default AsciiView diff --git a/src/browser/modules/Stream/Views/CodeView.jsx b/src/browser/modules/Stream/Views/CodeView.jsx index d5dfaa48412..3ccead0505d 100644 --- a/src/browser/modules/Stream/Views/CodeView.jsx +++ b/src/browser/modules/Stream/Views/CodeView.jsx @@ -1,8 +1,8 @@ import style from './code_style.css' -const CodeView = ({request, query}) => { +const CodeView = ({request, query, style: displayStyle}) => { return ( - +
diff --git a/src/browser/modules/Stream/Views/TableView.jsx b/src/browser/modules/Stream/Views/TableView.jsx index 624de619c6a..a916c120474 100644 --- a/src/browser/modules/Stream/Views/TableView.jsx +++ b/src/browser/modules/Stream/Views/TableView.jsx @@ -12,7 +12,7 @@ class TableView extends Component { } } render () { - if (!this.props.data) return (No results found) + if (!this.props.data) return (
No results found
) const tableHeader = this.state.columns.map((column, i) => ( ) ) @@ -44,7 +44,7 @@ class TableView extends Component { ) return ( -
Server version{column}
+
{tableHeader} diff --git a/src/browser/modules/Stream/Views/WarningsView.jsx b/src/browser/modules/Stream/Views/WarningsView.jsx index 7ed4f42c18c..e3383020545 100644 --- a/src/browser/modules/Stream/Views/WarningsView.jsx +++ b/src/browser/modules/Stream/Views/WarningsView.jsx @@ -11,7 +11,11 @@ const getWarningComponent = (severity) => { } } -const WarningsView = ({notifications, cypher}) => { +const WarningsView = ({notifications, cypher, style}) => { + if (!notifications || !cypher) { + return null + } + let cypherLines = cypher.split('\n') cypherLines[0] = cypherLines[0].replace(/^EXPLAIN /, '') @@ -34,7 +38,7 @@ const WarningsView = ({notifications, cypher}) => { ) }) return ( - + {notificationsList} ) } diff --git a/src/browser/modules/Stream/Visualization.jsx b/src/browser/modules/Stream/Visualization.jsx index 16ae7117e22..16ec09cd863 100644 --- a/src/browser/modules/Stream/Visualization.jsx +++ b/src/browser/modules/Stream/Visualization.jsx @@ -5,7 +5,7 @@ import { NevadaWrapper } from '../NevadaVisualization/NevadaWrapper' import bolt from 'services/bolt/bolt' import { withBus } from 'preact-suber' import { ExplorerComponent } from '../D3Visualization/components/Explorer' -import { StyledNevadaCanvas } from './styled' +import { StyledNevadaCanvas, StyledVisContainer } from './styled' import { getUseNewVisualization, getSettings } from 'shared/modules/settings/settingsDuck' import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' @@ -13,24 +13,44 @@ import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' export class Visualization extends Component { constructor (props) { super(props) - this.state = {} - this.state.useNewVis = this.props.useNewVis + + this.state = { + nodesAndRelationships: { + nodes: [], + relationships: [] + }, + justInitiated: true, + useNewVis: props.useNewVis + } + } + + componentWillMount () { + if (this.props.records && this.props.records.length > 0) { + this.populateDataToStateFromProps(this.props) + } } shouldComponentUpdate (nextProps) { - return nextProps.records !== this.props.records || nextProps.graphStyleData !== this.props.graphStyleData + return nextProps.records !== this.props.records || nextProps.graphStyleData !== this.props.graphStyleData || nextProps.style !== this.props.style } componentWillReceiveProps (nextProps) { if (nextProps.records !== this.props.records) { - if (this.state.useNewVis) { - this.setState({nodesAndRelationships: bolt.extractNodesAndRelationshipsFromRecords(this.props.records)}) - } else { - this.setState({nodesAndRelationships: bolt.extractNodesAndRelationshipsFromRecordsForOldVis(nextProps.records)}) - } + this.populateDataToStateFromProps(nextProps) + } + + if (nextProps.style.display !== this.props.style.display) { + this.setState({justInitiated: false}) } } + populateDataToStateFromProps (props) { + this.setState({nodesAndRelationships: this.state.useNewVis + ? bolt.extractNodesAndRelationshipsFromRecords(props.records) + : bolt.extractNodesAndRelationshipsFromRecordsForOldVis(props.records) + }) + } + getNeighbours (id, currentNeighbourIds = []) { let query = `MATCH path = (a)--(o) WHERE id(a)= ${id} @@ -60,18 +80,27 @@ export class Visualization extends Component { render () { if (this.state.useNewVis) { - this.state.nodesAndRelationships = this.state.nodesAndRelationships || bolt.extractNodesAndRelationshipsFromRecords(this.props.records) return ( - + ) - } else { - this.state.nodesAndRelationships = this.state.nodesAndRelationships || bolt.extractNodesAndRelationshipsFromRecordsForOldVis(this.props.records) - return ( - - ) } + + // This workaround is to overcome the issue that if the svg is initiated with in a style.display = none component, it does not become visible even display changed to block or so + if (this.state.justInitiated && this.props.style.display === 'none') { + return null + } + + return ( + + + + ) } } diff --git a/src/browser/modules/Stream/styled.jsx b/src/browser/modules/Stream/styled.jsx index 989b567831f..2a3bb15d9ea 100644 --- a/src/browser/modules/Stream/styled.jsx +++ b/src/browser/modules/Stream/styled.jsx @@ -25,22 +25,23 @@ const rollDownAnimation = keyframes` // Frames export const StyledFrame = styled.article` - margin: 10px 0px 10px 0px; width: auto; background-color: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.1); - animation: ${props => props.playIntroAnimation ? rollDownAnimation + '.2s linear' : 'none'}; + animation: ${rollDownAnimation} + .2s linear; border: ${props => props.theme.frameBorder}; + margin: ${props => props.fullscreen ? '0' : '10px 0px 10px 0px'}; + ${props => props.fullscreen ? 'position: fixed' : null}; + ${props => props.fullscreen ? 'left: 0' : null}; + ${props => props.fullscreen ? 'top: 0' : null}; + ${props => props.fullscreen ? 'bottom: 0' : null}; + ${props => props.fullscreen ? 'right: 0' : null}; + ${props => props.fullscreen ? 'z-index: 1030' : null}; ` -export const StyledFullscreenFrame = styled(StyledFrame)` - position: fixed; - left: 0; - top: 0; - bottom: 0; - right: 0; - margin: 0; - z-index: 1030; +export const StyledVisContainer = styled.div` + width: 100%; + display : ${props => props.style.display} ` export const StyledFrameBody = styled.div`