Skip to content

Commit 2e45d9a

Browse files
committed
Code refactoring
1 parent 17fb454 commit 2e45d9a

File tree

13 files changed

+273
-186
lines changed

13 files changed

+273
-186
lines changed

src/NeoDash.js

Lines changed: 99 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,89 +2,108 @@ import React from "react";
22
import Section from "react-materialize/lib/Section";
33
import Row from "react-materialize/lib/Row";
44
import Container from "react-materialize/lib/Container";
5-
import {AddNeoCard, NeoCard} from "./card/NeoCard";
5+
import {AddNeoCard, NeoCardComponent} from "./card/NeoCard";
66
import Navbar from "react-materialize/lib/Navbar";
77
import Icon from "react-materialize/lib/Icon";
88
import NeoModal from "./component/NeoModal";
99
import Textarea from "react-materialize/lib/Textarea";
1010
import NavItem from "react-materialize/lib/NavItem";
1111
import Button from "react-materialize/lib/Button";
12-
import Col from "react-materialize/lib/Col";
1312
import NeoTextInput from "./component/NeoTextInput";
1413
import neo4j from "neo4j-driver";
15-
import {Checkbox} from "react-materialize";
1614
import NeoCheckBox from "./component/NeoCheckBox";
1715
import NeoTextButton from "./component/NeoTextButton";
18-
import defaultDashboard from './default_dashboard.json';
19-
16+
import defaultDashboard from './data/default_dashboard.json';
17+
import DesktopIntegration from './tools/DesktopIntegration';
18+
19+
20+
/**
21+
* Main class for the NeoDash dashboard builder component.
22+
*
23+
* This component handles:
24+
* - Connecting to Neo4j (through a Neo4j Desktop integration or manually)
25+
* - Loading/storing dashboards as JSON (optionally from the browser cache)
26+
* - The creation, ordering and deleting of the NeoCard components.
27+
* - Propagating global parameter changes ("Selection" reports) to each of the cards.
28+
*/
2029
class NeoDash extends React.Component {
2130
version = '1.0';
2231

2332
constructor(props) {
2433
super(props);
34+
this.stateChanged = this.stateChanged.bind(this);
35+
this.loadCardsFromJSON = this.loadCardsFromJSON.bind(this);
36+
this.connect = this.connect.bind(this);
2537

26-
// Neo4j Desktop integration
27-
let neo4jDesktopApi = window.neo4jDesktopApi;
28-
if (neo4jDesktopApi) {
29-
let promise = neo4jDesktopApi.getContext();
30-
let a = this;
31-
promise.then(function (context) {
32-
33-
let desktopIntegration = new Neo4jDesktopIntegration(context);
34-
let neo4j = desktopIntegration.getActiveDatabase();
35-
if (neo4j) {
36-
a.connection = {
37-
url: neo4j.connection.configuration.protocols.bolt.url,
38-
database: "",
39-
username: neo4j.connection.configuration.protocols.bolt.username,
40-
password: neo4j.connection.configuration.protocols.bolt.password,
41-
encryption: neo4j.connection.configuration.protocols.bolt.tlsLevel === "REQUIRED" ? "on" : "off"
42-
}
43-
a.connect()
38+
// Attempt to load an existing dashboard from the browser cache.
39+
this.loadDashboardfromBrowserCache();
4440

45-
} else {
46-
a.updateConnectionModal(a.connect, true);
47-
a.stateChanged({label: "HideError"})
48-
}
49-
});
41+
if (window.neo4jDesktopApi) {
42+
this.setConnectionDetailsFromDesktopIntegration();
43+
} else {
44+
// check the browser cache or use default values.
45+
this.setConnectionDetailsFromBrowserCache();
46+
}
47+
48+
}
5049

50+
/**
51+
* Sets the state of NeoDash based on
52+
*/
53+
loadDashboardfromBrowserCache() {
54+
this.state = {json: '{}', count: 0}
55+
if (localStorage.getItem('neodash-dashboard')) {
56+
this.state.json = localStorage.getItem('neodash-dashboard');
5157
}
58+
}
5259

53-
// check the browser cache or use default values.
60+
/**
61+
* Sets the connection details based on the data in the browser cache (if available).
62+
* Else, defaults to localhost:7867.
63+
*/
64+
setConnectionDetailsFromBrowserCache() {
5465
this.connection = {
5566
url: (localStorage.getItem('neodash-url')) ? localStorage.getItem('neodash-url') : 'neo4j://localhost:7687',
5667
database: (localStorage.getItem('neodash-database')) ? localStorage.getItem('neodash-database') : '',
5768
username: (localStorage.getItem('neodash-username')) ? localStorage.getItem('neodash-username') : 'neo4j',
5869
password: (localStorage.getItem('neodash-password')) ? localStorage.getItem('neodash-password') : '',
5970
encryption: (localStorage.getItem('neodash-encryption')) ? localStorage.getItem('neodash-encryption') : 'off',
6071
}
72+
this.updateConnectionModal(this.connect, true);
73+
this.stateChanged({label: "HideError"})
74+
}
6175

62-
this.state = {json: '{}', count: 0}
63-
if (localStorage.getItem('neodash-dashboard')) {
64-
this.state.json = localStorage.getItem('neodash-dashboard');
65-
}
66-
67-
this.stateChanged = this.stateChanged.bind(this);
68-
this.loadJson = this.loadJson.bind(this);
69-
this.connect = this.connect.bind(this);
70-
71-
// If not running from desktop, always ask for connection details
72-
if (!neo4jDesktopApi) {
73-
this.updateConnectionModal(this.connect, true);
74-
} else {
75-
// If running from desktop, the constructor will set up a connection using the promise.
76-
this.stateChanged({label: "CreateError", value: "Trying to connect to your active database..."});
77-
}
78-
79-
76+
/**
77+
* Attempts to set the connection details using the Neo4j Desktop integration.
78+
* If NeoDash is running from Desktop, find the first active database and connect to it.
79+
* If no databases are active, default to a manually specified connection (possibly from browser cache)
80+
*/
81+
setConnectionDetailsFromDesktopIntegration() {
82+
let promise = window.neo4jDesktopApi.getContext();
83+
let neodash = this;
84+
promise.then(function (context) {
85+
let neo4jDesktopIntegration = new DesktopIntegration(context);
86+
let connection = neo4jDesktopIntegration.connection;
87+
if (connection) {
88+
neodash.connection = connection;
89+
neodash.stateChanged({label: "CreateError", value: "Trying to connect to your active database..."});
90+
neodash.connect();
91+
} else {
92+
neodash.setConnectionDetailsFromBrowserCache();
93+
}
94+
});
8095
}
8196

8297
componentDidMount() {
83-
this.loadJson()
98+
this.loadCardsFromJSON()
8499
}
85100

86101

87-
connect(e) {
102+
/**
103+
* Will try to connect to Neo4j given the specified connection parameters.
104+
* On failure, will produce an error message and show it to the user.
105+
*/
106+
connect() {
88107
try {
89108
var url = this.connection.url;
90109
if (!(url.startsWith("bolt://") || url.startsWith("bolt+routing://") || url.startsWith("neo4j://"))) {
@@ -104,11 +123,8 @@ class NeoDash extends React.Component {
104123
.then(result => {
105124
this.errorModal = null;
106125
this.connected = true;
107-
108-
109126
this.updateConnectionModal(this.connect, false);
110-
this.loadJson()
111-
127+
this.loadCardsFromJSON()
112128
localStorage.setItem('neodash-database', this.connection.database);
113129
localStorage.setItem('neodash-url', this.connection.url);
114130
localStorage.setItem('neodash-username', this.connection.username);
@@ -132,7 +148,7 @@ class NeoDash extends React.Component {
132148
}
133149

134150

135-
loadJson() {
151+
loadCardsFromJSON() {
136152
if (!this.connected) {
137153
this.state.title = 'NeoDash ⚡';
138154
return
@@ -158,22 +174,28 @@ class NeoDash extends React.Component {
158174
this.state.cardState = loaded.reports.map(c => []);
159175
this.state.cards = loaded.reports.map((report, index) => {
160176
if (report.type) {
161-
return <NeoCard
177+
return <NeoCardComponent
162178
connection={this.connection}
163179
globalParameters={this.state.globalParameters}
164-
page={report.page} width={report.width} height={report.height}
165-
kkey={this.state.count + index} key={this.state.count + index} id={index}
180+
page={report.page}
181+
width={report.width}
182+
height={report.height}
183+
kkey={this.state.count + index}
184+
key={this.state.count + index}
185+
id={index}
166186
session={this.session}
167187
onChange={this.stateChanged}
168188
editable={this.state.editable}
169-
type={report.type} propertiesSelected={report.properties}
189+
type={report.type}
190+
propertiesSelected={report.properties}
170191
title={report.title}
171-
query={report.query} parameters={report.parameters}
192+
query={report.query}
193+
parameters={report.parameters}
172194
refresh={report.refresh}/>
173195
} else if (this.state.editable) {
174196
return <AddNeoCard key={99999999} id={99999999} onClick={this.stateChanged}/>
175197
}
176-
return <div></div>
198+
return <div/>
177199
}
178200
);
179201
this.state.count = this.state.count + ((loaded.reports.length) ? loaded.reports.length : 0) - 1;
@@ -194,9 +216,8 @@ class NeoDash extends React.Component {
194216

195217

196218
setDefaultDashboard() {
197-
let state = this.state;
198219
this.state.json = JSON.stringify(defaultDashboard);
199-
this.loadJson()
220+
this.loadCardsFromJSON()
200221
}
201222

202223
stateChanged(update) {
@@ -272,21 +293,21 @@ class NeoDash extends React.Component {
272293
this.state.cardState.splice(index, 1);
273294
}
274295
if (update.label !== "SaveModalUpdated") {
275-
this.handleUpdateSavedJSON();
296+
this.buildJSONFromReportsState();
276297
}
277298
this.setState(this.state);
278299
}
279300

280301
handleNewCardCreate() {
281-
let newCard = <NeoCard connection={this.connection}
282-
globalParameters={this.state.globalParameters}
283-
kkey={this.state.count}
284-
session={this.session}
285-
width={4} height={4}
286-
id={this.state.count}
287-
editable={this.state.editable}
288-
key={this.state.count}
289-
onChange={this.stateChanged} type='table'/>;
302+
let newCard = <NeoCardComponent connection={this.connection}
303+
globalParameters={this.state.globalParameters}
304+
kkey={this.state.count}
305+
session={this.session}
306+
width={4} height={4}
307+
id={this.state.count}
308+
editable={this.state.editable}
309+
key={this.state.count}
310+
onChange={this.stateChanged} type='table'/>;
290311
this.state.count += 1;
291312
this.state.cards.splice(this.state.cards.length - 1, 0, newCard);
292313
this.state.cardState.splice(this.state.cardState.length - 1, 0, {
@@ -334,7 +355,7 @@ class NeoDash extends React.Component {
334355
* Helper function to convert a string with capital letters and spaces to a lowercase snake case verison.
335356
*/
336357
toLowerCaseSnakeCase(value) {
337-
return value.toLowerCase().replace(/ /g,"_");
358+
return value.toLowerCase().replace(/ /g, "_");
338359
}
339360

340361
handleError(content) {
@@ -364,7 +385,7 @@ class NeoDash extends React.Component {
364385
]}/>
365386
}
366387

367-
handleUpdateSavedJSON() {
388+
buildJSONFromReportsState() {
368389
if (!this.connected) {
369390
return
370391
}
@@ -441,8 +462,8 @@ class NeoDash extends React.Component {
441462
<NeoModal
442463
header={'Connect to Neo4j'}
443464
style={{'maxWidth': '520px'}}
444-
key={this.state.count}
445-
id={this.state.count}
465+
key={(this.state) ? this.state.count : 0}
466+
id={(this.state) ? this.state.count : 0}
446467
footerType={"modal-dark-footer"}
447468
open={open}
448469
root={document.getElementById("root")}
@@ -507,7 +528,8 @@ class NeoDash extends React.Component {
507528
}
508529

509530
render() {
510-
this.generateSaveLoadModal(this.loadJson);
531+
// This should not be called in render...
532+
this.generateSaveLoadModal(this.loadCardsFromJSON);
511533
let title = <Textarea disabled={!this.state.editable} noLayout={true}
512534
style={{"width": '500px'}}
513535
className="card-title editable-title"
@@ -540,24 +562,5 @@ class NeoDash extends React.Component {
540562
}
541563
}
542564

543-
class Neo4jDesktopIntegration {
544-
constructor(context) {
545-
this.desktopContext = context;
546-
}
547-
548-
getActiveDatabase() {
549-
550-
for (let pi = 0; pi < this.desktopContext.projects.length; pi++) {
551-
let prj = this.desktopContext.projects[pi];
552-
for (let gi = 0; gi < prj.graphs.length; gi++) {
553-
let grf = prj.graphs[gi];
554-
if (grf.status == 'ACTIVE') {
555-
return grf;
556-
}
557-
}
558-
}
559-
return null;
560-
}
561-
}
562565

563566
export default (NeoDash);

0 commit comments

Comments
 (0)