Skip to content

Commit 6208b14

Browse files
authored
Merge pull request #28 from nielsdejong/develop
Release 1.1.2
2 parents b642053 + df82fd0 commit 6208b14

15 files changed

+435
-72
lines changed

.env.hosted

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
PUBLIC_URL=https://nielsdejong.nl/neodash
1+
PUBLIC_URL=https://neodash.graphapp.io

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ⚡ NeoDash - Neo4j Dashboard Builder
22
NeoDash is a lightweight web app to create Neo4j dashboards.
3-
Writing Cypher is all that's required to build your first dashboard in minutes. Want to give NeoDash a spin right away? Try it here: https://nielsdejong.nl/neodash/.
3+
Writing Cypher is all that's required to build your first dashboard in minutes. Want to give NeoDash a spin right away? Try it [online](https://neodash.graphapp.io/).
44

55
You can also install NeoDash on Neo4j Desktop from the [Graph App Gallery](https://install.graphapp.io/).
66

doc/developer-guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ NeoDash will automatically connect to your active database.
2222

2323
![Graph App Gallery](./img/graphapp.png)
2424
#### 2. Online
25-
The latest version of NeoDash will always be available at https://nielsdejong.nl/neodash.
25+
The latest version of NeoDash will always be available at https://neodash.graphapp.io.
2626
Your database credentials will only be cached in your browser.
2727

2828
#### 3. As a web app in your own hosted environment

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "neodash",
33
"description": "NeoDash - Neo4j Dashboard Builder",
4-
"version": "1.1.1",
4+
"version": "1.1.2",
55
"homepage": "./",
66
"neo4jDesktop": {
77
"apiVersion": "^1.2.0"

public/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ code {
124124
box-shadow: none !important;
125125
-webkit-box-shadow: none !important;
126126
}
127+
html { scroll-behavior: smooth; }
128+
129+
127130
.tab {
128131
width: 250px;
129132
-webkit-box-flex: 0 !important;

release-notes.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
### NeoDash 1.1.1 - Neo4j Dashboard Builder
2-
- Added dashboard sharing functionality.
3-
- Fixed unintuitive margins for bar chart reports.
4-
- Added abort button to save/load screen.
5-
- Added automatic fix for inconsistent DB url + encryption configurations.
1+
### NeoDash 1.1.2 - Neo4j Dashboard Builder
2+
- Changed base URL to https://neodash.graphapp.io
3+
- Resolved bug that didn't allow for connecting to a remote DBMS without encryption
4+
- Added customizable background color for dashboards using "background" Cypher parameter
5+
- Added option to hide table footers using "hideFooter" Cypher parameter
6+
- First experimental reports added

src/NeoDash.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,21 +157,19 @@ class NeoDash extends React.Component {
157157
var url = this.connection.url;
158158

159159
// When specifying an encrypted connection, we don't need the bolt+s / neo4j+s scheme.
160-
if (this.connection.encryption === "on" && url.startsWith("bolt+s://")){
160+
if (this.connection.encryption === "on" && url.startsWith("bolt+s://")) {
161161
url = url.replace("bolt+s://", "bolt://")
162162
this.connection.url = url;
163163
}
164-
if (this.connection.encryption === "on" && url.startsWith("neo4j+s://")){
164+
if (this.connection.encryption === "on" && url.startsWith("neo4j+s://")) {
165165
url = url.replace("neo4j+s://", "neo4j://")
166166
this.connection.url = url;
167167
}
168168

169169
if (!(url.startsWith("bolt://") || url.startsWith("bolt+routing://") || url.startsWith("neo4j://"))) {
170170
url = "neo4j://" + url;
171171
}
172-
let config = {
173-
encrypted: (this.connection.encryption === "on") ? 'ENCRYPTION_ON' : 'ENCRYPTION_OFF'
174-
};
172+
let config = (this.connection.encryption === "on") ? {encrypted: 'ENCRYPTION_ON'} : {}
175173

176174
var driver = neo4j.driver(
177175
url,
@@ -940,6 +938,7 @@ class NeoDash extends React.Component {
940938
value: e.target.value
941939
})}/>;
942940

941+
943942
// if the page titles are loaded, build the list of tabs
944943
let tabslist = (this.state.pageTitles) ? this.state.pageTitles.map((t, i) => {
945944
let deletePageButton = <Button className="btn-floating btn-remove-tab"
@@ -1006,9 +1005,9 @@ class NeoDash extends React.Component {
10061005
tabs
10071006
}
10081007
style={{backgroundColor: '#111'}}>
1008+
10091009
{saveLoadModal}{shareModal}
1010-
{(this.neoConnectionModal) ? this.neoConnectionModal : <div></div>
1011-
}
1010+
{(this.neoConnectionModal) ? this.neoConnectionModal : <div></div>}
10121011
</Navbar>;
10131012

10141013
}

src/card/NeoCard.js

Lines changed: 123 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import NeoPropertySelectReport from "./report/NeoPropertySelectReport";
1919
import NeoMapReport from "./report/NeoMapReport";
2020
import NeoMapFooter from "./footer/NeoMapFooter";
2121
import NeoIFrameReport from "./report/NeoIFrameReport";
22+
import NeoLiveTimeChartReport from "./report/experimental/NeoLiveTimeChartReport";
23+
import NeoSearchBarReport from "./report/experimental/NeoSearchBarReport";
24+
import NeoBigNumberReport from "./report/experimental/NeoBigNumberReport";
2225

2326

2427
let emptyAction = <div key={0}/>;
@@ -258,6 +261,15 @@ export class NeoCard extends React.Component {
258261
if (this.state.type === 'line') {
259262
this.setCardTypeToLineChart();
260263
}
264+
if (this.state.type === 'bignumber') {
265+
this.setCardTypeToBigNumberView();
266+
}
267+
if (this.state.type === 'searchbar') {
268+
this.setCardTypeToSearchBar();
269+
}
270+
if (this.state.type === 'time') {
271+
this.setCardTypeToTimeChart();
272+
}
261273
if (this.state.type === "graph") {
262274
this.setCardTypeToGraph();
263275
}
@@ -276,7 +288,7 @@ export class NeoCard extends React.Component {
276288
if (this.state.type === 'map') {
277289
this.setCardTypeToMap();
278290
}
279-
if (this.state.success === false || this.state.query === "" || this.state.query === "\n"){
291+
if (this.state.success === false || this.state.query === "" || this.state.query === "\n") {
280292
this.state.action = emptyAction;
281293
}
282294
return state
@@ -298,36 +310,54 @@ export class NeoCard extends React.Component {
298310
setCardTypeToTableView() {
299311
this.state.content =
300312
<NeoTableReport connection={this.props.connection}
301-
rows={this.state.height == 4 ? NeoTableReport.normalRowCount : NeoTableReport.tallRowCount}
302-
page={this.state.page}
303-
query={this.state.query}
304-
stateChanged={this.stateChanged}
305-
params={this.state.parsedParameters}
306-
refresh={this.state.refresh}
313+
rows={this.state.height == 4 ? NeoTableReport.normalRowCount : NeoTableReport.tallRowCount}
314+
page={this.state.page}
315+
query={this.state.query}
316+
stateChanged={this.stateChanged}
317+
params={this.state.parsedParameters}
318+
refresh={this.state.refresh}
307319
/>
308-
320+
if (this.state.parsedParameters && !this.state.parsedParameters.hideFooter) {
309321
this.state.action =
310322
<NeoTableFooter page={this.state.page} key={0} data={this.state.data} onChange={this.stateChanged}/>
323+
}
311324

312325
}
313326

327+
/**
328+
* Updates the card's report to a table.
329+
*/
330+
setCardTypeToBigNumberView() {
331+
this.state.content =
332+
<NeoBigNumberReport connection={this.props.connection}
333+
page={this.state.page}
334+
query={this.state.query}
335+
stateChanged={this.stateChanged}
336+
onSelectionChange={this.onSelectionChange}
337+
params={this.state.parsedParameters}
338+
refresh={this.state.refresh}
339+
/>
340+
this.state.action = emptyAction;
341+
}
342+
343+
314344
/**
315345
* Updates the card's report to a bar chart.
316346
*/
317347
setCardTypeToBarChart() {
318348
this.state.content =
319349
<NeoBarChartReport connection={this.props.connection}
320-
page={this.state.page}
321-
query={this.state.query}
322-
clientWidth={(this.cardRef.current) ? this.cardRef.current.clientWidth : 0}
323-
id={this.props.id}
324-
stateChanged={this.stateChanged}
325-
propertiesSelected={this.state.propertiesSelected}
326-
onNodeLabelUpdate={this.updateBarPropertySelect}
327-
params={this.state.parsedParameters}
328-
refresh={this.state.refresh}
329-
width={this.state.width}
330-
height={this.state.height}
350+
page={this.state.page}
351+
query={this.state.query}
352+
clientWidth={(this.cardRef.current) ? this.cardRef.current.clientWidth : 0}
353+
id={this.props.id}
354+
stateChanged={this.stateChanged}
355+
propertiesSelected={this.state.propertiesSelected}
356+
onNodeLabelUpdate={this.updateBarPropertySelect}
357+
params={this.state.parsedParameters}
358+
refresh={this.state.refresh}
359+
width={this.state.width}
360+
height={this.state.height}
331361
/>
332362
}
333363

@@ -337,20 +367,42 @@ export class NeoCard extends React.Component {
337367
setCardTypeToLineChart() {
338368
this.state.content =
339369
<NeoLineChartReport connection={this.props.connection}
340-
page={this.state.page}
341-
query={this.state.query}
342-
clientWidth={(this.cardRef.current) ? this.cardRef.current.clientWidth : 0}
343-
id={this.props.id}
344-
stateChanged={this.stateChanged}
345-
propertiesSelected={this.state.propertiesSelected}
346-
onNodeLabelUpdate={this.updateLinePropertySelect}
347-
params={this.state.parsedParameters}
348-
refresh={this.state.refresh}
349-
width={this.state.width}
350-
height={this.state.height}
370+
page={this.state.page}
371+
query={this.state.query}
372+
clientWidth={(this.cardRef.current) ? this.cardRef.current.clientWidth : 0}
373+
id={this.props.id}
374+
stateChanged={this.stateChanged}
375+
propertiesSelected={this.state.propertiesSelected}
376+
onNodeLabelUpdate={this.updateLinePropertySelect}
377+
params={this.state.parsedParameters}
378+
refresh={this.state.refresh}
379+
width={this.state.width}
380+
height={this.state.height}
351381
/>
352382
}
353383

384+
/**
385+
* Updates the card's report to a line chart.
386+
*/
387+
setCardTypeToTimeChart() {
388+
this.state.content =
389+
<NeoLiveTimeChartReport connection={this.props.connection}
390+
page={this.state.page}
391+
query={this.state.query}
392+
clientWidth={(this.cardRef.current) ? this.cardRef.current.clientWidth : 0}
393+
id={this.props.id}
394+
stateChanged={this.stateChanged}
395+
propertiesSelected={this.state.propertiesSelected}
396+
onNodeLabelUpdate={function () {
397+
}}
398+
params={this.state.parsedParameters}
399+
refresh={this.state.refresh}
400+
width={this.state.width}
401+
height={this.state.height}
402+
/>
403+
this.state.action = emptyAction;
404+
}
405+
354406
/**
355407
* Updates the card's report to a graph visualization.
356408
*/
@@ -420,6 +472,20 @@ export class NeoCard extends React.Component {
420472
this.state.action = emptyAction;
421473
}
422474

475+
/**
476+
* Update the card's report to a search bar view.
477+
*/
478+
setCardTypeToSearchBar() {
479+
this.state.content =
480+
<NeoSearchBarReport
481+
connection={this.props.connection}
482+
query={'return true'}
483+
data={this.state.query}
484+
stateChanged={this.stateChanged}
485+
refresh={this.state.refresh}/>
486+
this.state.action = emptyAction;
487+
}
488+
423489
/**
424490
* Update the card's report to a Markdown view.
425491
*/
@@ -434,7 +500,7 @@ export class NeoCard extends React.Component {
434500
refresh={this.state.refresh}/>
435501
this.state.action = emptyAction;
436502
}
437-
503+
438504
/**
439505
* Update the card's report to a property selection.
440506
*/
@@ -483,6 +549,7 @@ RETURN DISTINCT n.\`${property}\` as value LIMIT 4`;
483549
* For selection reports, the selected value has changed. This should be propagated to other reports.
484550
*/
485551
onSelectionChange(label, property, propertyId, value) {
552+
486553
this.props.onChange({
487554
label: "GlobalParameterChanged",
488555
value: {label: label, property: property, propertyId: propertyId, value: value}
@@ -528,9 +595,9 @@ RETURN DISTINCT n.\`${property}\` as value LIMIT 4`;
528595
this.state.page += 1;
529596
this.state.action =
530597
<NeoBarChartFooter propertiesSelected={this.state.propertiesSelected} page={this.state.page} key={0}
531-
data={this.state.data}
532-
onChange={this.stateChanged}
533-
categories={labels} values={labels}
598+
data={this.state.data}
599+
onChange={this.stateChanged}
600+
categories={labels} values={labels}
534601
/>
535602
this.setState(this.state);
536603
}
@@ -542,9 +609,9 @@ RETURN DISTINCT n.\`${property}\` as value LIMIT 4`;
542609
this.state.page += 1;
543610
this.state.action =
544611
<NeoLineChartFooter propertiesSelected={this.state.propertiesSelected} page={this.state.page} key={0}
545-
data={this.state.data}
546-
onChange={this.stateChanged}
547-
categories={labels} values={labels}
612+
data={this.state.data}
613+
onChange={this.stateChanged}
614+
categories={labels} values={labels}
548615
/>
549616

550617
this.setState(this.state);
@@ -562,10 +629,10 @@ RETURN DISTINCT n.\`${property}\` as value LIMIT 4`;
562629

563630

564631
this.state.action = <NeoMapFooter key={0} nodeLabels={Object.keys(labels)}
565-
width={this.props.width}
566-
params={this.state.parsedParameters}
632+
width={this.props.width}
633+
params={this.state.parsedParameters}
567634

568-
onChange={this.stateChanged}/>;
635+
onChange={this.stateChanged}/>;
569636

570637
}
571638

@@ -591,29 +658,33 @@ RETURN DISTINCT n.\`${property}\` as value LIMIT 4`;
591658

592659

593660
this.state.action = <NeoGraphVisFooter key={0} nodeLabels={Object.keys(labels)}
594-
width={this.props.width}
595-
params={this.state.parsedParameters}
596-
properties={Object.values(labels).map((labelChoices, index) => {
597-
let options = {}
598-
labelChoices.forEach(choice =>
599-
options[(index + "-" + choice)] = choice
600-
)
601-
return options;
602-
})}
603-
onChange={this.stateChanged}/>;
661+
width={this.props.width}
662+
params={this.state.parsedParameters}
663+
properties={Object.values(labels).map((labelChoices, index) => {
664+
let options = {}
665+
labelChoices.forEach(choice =>
666+
options[(index + "-" + choice)] = choice
667+
)
668+
return options;
669+
})}
670+
onChange={this.stateChanged}/>;
604671

605672
}
606673

607674
/**
608675
* Render the NeoCard component with the currently selected report.
609676
*/
610677
render() {
678+
let backgroundColor = (this.state.parsedParameters.background) ? this.state.parsedParameters.background + "" : "";
611679
return <Col l={this.state.width} m={12} s={12}>
612680
<div ref={this.cardRef}>
613681
<Card
614682
actions={[this.state.action]}
615-
style={{height: (this.state.height * 100 + 22 * ((this.state.height / 4) - 1)) + 'px'}}
616-
className={"neo-card medium white darken-5 paginated-card"}
683+
style={{
684+
backgroundColor: backgroundColor,
685+
height: (this.state.height * 100 + 22 * ((this.state.height / 4) - 1)) + 'px'
686+
}}
687+
className={"neo-card medium darken-5 paginated-card"}
617688
closeIcon={this.closeIcon}
618689
revealIcon={(this.props.editable) ? <Icon>more_vert</Icon> : <div></div>}
619690
textClassName="black-text"

src/card/NeoCardSettings.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ class NeoCardSettings extends React.Component {
2020
'map': 'Map',
2121
'select': 'Selection',
2222
'iframe': 'iFrame',
23-
'text': 'Markdown',
23+
'text': 'Markdown'
2424
};
2525

2626
// A dictionary of available card sizes.
2727
sizeOptions = {
28+
// 3: 'Tiny (3x4)',
2829
4: 'Small (4x4)',
2930
6: 'Medium (6x4)',
3031
8: 'Large (8x4)',

0 commit comments

Comments
 (0)