diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3222b1e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{*.md,*.snap}] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.gitignore b/.gitignore index e984fd2..c9f21ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ node_modules neuler*.tgz -.idea \ No newline at end of file +.idea +.DS_STORE +.eslintcache +*.swp +*~ \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..3bfc4d0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6102d25 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "editor.rulers": [80], + "files.exclude": { + "**/.git": true, + "**/node_modules": true, + "**/build": true + }, + "editor.formatOnSave": true, + "javascript.validate.enable": false, + "prettier.eslintIntegration": true, + "prettier.trailingComma": "es5", + "prettier.singleQuote": true +} diff --git a/package.json b/package.json index 379b097..cf719bb 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,9 @@ "uuid": "^3.3.2", "vis": "^4.21.0" }, + "devDependencies": { + "prettier": "^1.17.1" + }, "scripts": { "start": "react-scripts start", "buildLocal": "rm neuler*.tgz && rm -rf dist && react-scripts build && mv build dist", diff --git a/src/components/AlgoResults.js b/src/components/AlgoResults.js index 83502d7..1bda047 100644 --- a/src/components/AlgoResults.js +++ b/src/components/AlgoResults.js @@ -1,232 +1,309 @@ -import React, { Component } from 'react' -import { Button, Header, Icon, Segment, Menu, Loader, Message, Image } from 'semantic-ui-react' -import { connect } from "react-redux" -import GraphVisualiser from './visualisation/GraphVisualiser' -import { getAlgorithmDefinitions } from "./algorithmsLibrary" -import Chart from './visualisation/Chart' -import CodeView from './CodeView' - -import { ADDED, completeTask, FAILED, runTask } from "../ducks/tasks" -import html2canvas from "html2canvas"; -import {ReImg } from 'reimg' -import {v4 as generateId} from 'uuid' +import React, { Component } from 'react'; +import { + Button, + Header, + Icon, + Segment, + Menu, + Loader, + Message, + Image, +} from 'semantic-ui-react'; +import { connect } from 'react-redux'; +import GraphVisualiser from './visualisation/GraphVisualiser'; +import { getAlgorithmDefinitions } from './algorithmsLibrary'; +import Chart from './visualisation/Chart'; +import CodeView from './CodeView'; + +import { ADDED, completeTask, FAILED, runTask } from '../ducks/tasks'; +import html2canvas from 'html2canvas'; +import { ReImg } from 'reimg'; +import { v4 as generateId } from 'uuid'; const tabContentStyle = { height: '85vh', overflowY: 'auto', - overflowX: 'hidden' -} + overflowX: 'hidden', +}; const TableView = ({ task }) => { - const { ResultView } = getAlgorithmDefinitions(task.group, task.algorithm) - return
- -
-} + const { ResultView } = getAlgorithmDefinitions(task.group, task.algorithm); + return ( +
+ +
+ ); +}; const VisView = ({ task, active }) => (
- +
-) - -const LoaderExampleInlineCentered = ({ active }) => Fetching Data +); +const LoaderExampleInlineCentered = ({ active }) => ( + + Fetching Data + +); const ChartView = ({ task }) => { if (task.result && task.result.length > 0) { - return ({ - name: result.properties.name || 'Node', - score: result.score - }))}/> + return ( + ({ + name: result.properties.name || 'Node', + score: result.score, + }))} + /> + ); } else { - return + return ; } -} +}; class HorizontalAlgoTab extends Component { constructor(props) { super(props); - this.panelRef = React.createRef() + this.panelRef = React.createRef(); } - state = { - activeItem: this.props.error ? 'Error' : 'Table' - } + activeItem: this.props.error ? 'Error' : 'Table', + }; - handleMenuItemClick = (e, { name }) => this.setState({ activeItem: name }) + handleMenuItemClick = (e, { name }) => this.setState({ activeItem: name }); componentDidMount() { if (this.props.task.error) { - this.setState({ activeItem: 'Error' }) + this.setState({ activeItem: 'Error' }); } } componentWillReceiveProps(nextProps, nextContext) { if (nextProps.task.error) { - this.setState({ activeItem: 'Error' }) + this.setState({ activeItem: 'Error' }); } else if (this.state.activeItem === 'Error') { - this.setState({ activeItem: 'Table' }) + this.setState({ activeItem: 'Table' }); } } render() { - const { task, prevResult, nextResult, currentPage, totalPages } = this.props - let activeItem = this.state.activeItem - - const activeGroup = task.group - const getStyle = name => name === activeItem - ? ({ - display: '' - }) - : ({ - display: 'none' - }) + const { + task, + prevResult, + nextResult, + currentPage, + totalPages, + } = this.props; + let activeItem = this.state.activeItem; + + const activeGroup = task.group; + const getStyle = name => + name === activeItem + ? { + display: '', + } + : { + display: 'none', + }; return (
{task.completed && task.status === FAILED ? ( -
- - - - - -
- - Algorithm failed to complete -

{task.error}

-
-
-
- -
-
-
- ) - : - +
+ + + + + +
+ + Algorithm failed to complete +

{task.error}

+
+
+
+ +
+
+
+ ) : ( + +
- - - - {activeGroup === 'Centralities' ? - - : null} - - {!(activeGroup === 'Path Finding' || activeGroup === 'Similarity') ? - - : null - } - - - - printElement(this.panelRef.current)).bind(this)}> - - + + + {activeGroup === 'Centralities' ? ( + + ) : null} + + {!( + activeGroup === 'Path Finding' || activeGroup === 'Similarity' + ) ? ( + + ) : null} + + + + printElement(this.panelRef.current)} + > + -
-
- -
- {`${task.algorithm} Started at: ${task.startTime.toLocaleTimeString()} - (${currentPage} / ${totalPages})`} +
+ {`${ + task.algorithm + } Started at: ${task.startTime.toLocaleTimeString()} - (${currentPage} / ${totalPages})`}
-
-
- +
- +
- +
- {!(activeGroup === 'Path Finding' || activeGroup === 'Similarity') ? + {!( + activeGroup === 'Path Finding' || activeGroup === 'Similarity' + ) ? (
- -
: null} - - {activeGroup === 'Centralities' ? + +
+ ) : null} + + {activeGroup === 'Centralities' ? (
- -
: null} + +
+ ) : null} - } + )} - ) + ); } } class TabExampleVerticalTabular extends Component { state = { - page: 0 - } + page: 0, + }; prevResult() { - this.setState(({ page }) => ({ page: Math.max(0, page - 1) })) + this.setState(({ page }) => ({ page: Math.max(0, page - 1) })); } nextResult() { - const length = (this.props.tasks || []).length - this.setState(({ page }) => ({ page: Math.min(length - 1, page + 1) })) + const length = (this.props.tasks || []).length; + this.setState(({ page }) => ({ page: Math.min(length - 1, page + 1) })); } componentWillReceiveProps(nextProps, nextContext) { if (nextProps.tasks.length !== this.props.tasks.length) { - this.setState({ page: 0 }) - const task = nextProps.tasks[0] + this.setState({ page: 0 }); + const task = nextProps.tasks[0]; if (task.status === ADDED) { - this.onRunAlgo(task) + this.onRunAlgo(task); } } } onRunAlgo(task) { - const { taskId, group, algorithm, parameters, persisted } = task + const { taskId, group, algorithm, parameters, persisted } = task; let algorithmDefinition = getAlgorithmDefinitions(group, algorithm); - const { service, getFetchQuery } = algorithmDefinition + const { service, getFetchQuery } = algorithmDefinition; - let fetchCypher = getFetchQuery(parameters.label) + let fetchCypher = getFetchQuery(parameters.label); - let streamQuery = algorithmDefinition.streamQuery - let storeQuery = algorithmDefinition.storeQuery + let streamQuery = algorithmDefinition.streamQuery; + let storeQuery = algorithmDefinition.storeQuery; - if (group === "Similarity") { - const { itemLabel, relationshipType, categoryLabel } = parameters - streamQuery = streamQuery(itemLabel, relationshipType, categoryLabel) - storeQuery = storeQuery(itemLabel, relationshipType, categoryLabel) - fetchCypher = getFetchQuery(itemLabel, parameters.config.writeRelationshipType) + if (group === 'Similarity') { + const { itemLabel, relationshipType, categoryLabel } = parameters; + streamQuery = streamQuery(itemLabel, relationshipType, categoryLabel); + storeQuery = storeQuery(itemLabel, relationshipType, categoryLabel); + fetchCypher = getFetchQuery( + itemLabel, + parameters.config.writeRelationshipType + ); - delete parameters.itemLabel - delete parameters.relationshipType - delete parameters.categoryLabel + delete parameters.itemLabel; + delete parameters.relationshipType; + delete parameters.categoryLabel; } service({ @@ -234,61 +311,70 @@ class TabExampleVerticalTabular extends Component { storeCypher: storeQuery, fetchCypher, parameters: { ...parameters, limit: this.props.limit }, - persisted - }).then(result => { - this.props.completeTask(taskId, result) - if (persisted) { - this.props.onComplete() - } - }).catch(exc => { - console.log('ERROR IN SERVICE', exc) - this.props.completeTask(taskId, [], exc.toString()) - + persisted, }) - - this.props.runTask(taskId, persisted ? [storeQuery, fetchCypher] : [streamQuery]) + .then(result => { + this.props.completeTask(taskId, result); + if (persisted) { + this.props.onComplete(); + } + }) + .catch(exc => { + console.log('ERROR IN SERVICE', exc); + this.props.completeTask(taskId, [], exc.toString()); + }); + + this.props.runTask( + taskId, + persisted ? [storeQuery, fetchCypher] : [streamQuery] + ); } render() { - const tasks = this.props.tasks - const page = this.state.page + const tasks = this.props.tasks; + const page = this.state.page; if (tasks && tasks.length > 0) { - const currentTask = tasks[this.state.page] - return + const currentTask = tasks[this.state.page]; + return ( + + ); } else { - return null + return null; } } } const mapStateToProps = state => ({ tasks: state.tasks, - limit: state.settings.limit -}) + limit: state.settings.limit, +}); const mapDispatchToProps = (dispatch, ownProps) => ({ runTask: (taskId, query) => { - dispatch(runTask({ taskId, query })) + dispatch(runTask({ taskId, query })); }, completeTask: (taskId, result, error) => { - dispatch(completeTask({ taskId, result, error })) + dispatch(completeTask({ taskId, result, error })); }, onComplete: () => { - ownProps.onComplete() - } -}) + ownProps.onComplete(); + }, +}); const printElement = element => { - html2canvas(element).then(function (canvas) { - const guid = generateId() + html2canvas(element).then(function(canvas) { + const guid = generateId(); ReImg.fromCanvas(canvas).downloadPng(`neuler-${guid}.png`); - }) -} + }); +}; -export default connect(mapStateToProps, mapDispatchToProps)(TabExampleVerticalTabular) +export default connect( + mapStateToProps, + mapDispatchToProps +)(TabExampleVerticalTabular); diff --git a/src/components/Centralities/CentralityForm.js b/src/components/Centralities/CentralityForm.js index 7a3ece5..60217d1 100644 --- a/src/components/Centralities/CentralityForm.js +++ b/src/components/Centralities/CentralityForm.js @@ -1,67 +1,99 @@ -import React from 'react' -import { Form, Input, Dropdown } from "semantic-ui-react" +import React from "react"; +import { Form, Input, Dropdown } from "semantic-ui-react"; -export default ({onChange, direction, persist, writeProperty, weightProperty, concurrency, label, labelOptions, relationshipTypeOptions}) => ( +export default ({ + onChange, + direction, + persist, + writeProperty, + weightProperty, + concurrency, + label, + labelOptions, + relationshipTypeOptions +}) => ( - onChange("label", data.value)} /> + onChange("label", data.value)} + /> - onChange("relationshipType", data.value)} /> + onChange("relationshipType", data.value)} + /> - + onChange('direction', 'Outgoing')} + label="Out" + name="radioGroup" + value="Outgoing" + checked={direction === "Outgoing"} + onChange={() => onChange("direction", "Outgoing")} /> onChange('direction', 'Incoming')} + label="In" + name="radioGroup" + value="Incoming" + checked={direction === "Incoming"} + onChange={() => onChange("direction", "Incoming")} /> onChange('direction', 'Both')} + label="Both" + name="radioGroup" + value="Both" + checked={direction === "Both"} + onChange={() => onChange("direction", "Both")} /> - - { - onChange('persist', evt.target.checked) - }}/> + + { + onChange("persist", evt.target.checked); + }} + /> - { - persist ? - - onChange('writeProperty', evt.target.value)}/> - - : null - } + {persist ? ( + + onChange("writeProperty", evt.target.value)} + /> + + ) : null} - + onChange('concurrency', evt.target.value)} - style={{ 'width': '10em' }} + onChange={evt => onChange("concurrency", evt.target.value)} + style={{ width: "10em" }} /> -) +); diff --git a/src/components/CheckGraphAlgorithmsInstalled.js b/src/components/CheckGraphAlgorithmsInstalled.js index b8520d3..982ac73 100644 --- a/src/components/CheckGraphAlgorithmsInstalled.js +++ b/src/components/CheckGraphAlgorithmsInstalled.js @@ -1,31 +1,43 @@ -import React, { Component } from 'react' -import { Container, Menu, Segment, Dimmer, Loader, Header } from "semantic-ui-react" +import React, { Component } from 'react'; +import { + Container, + Menu, + Segment, + Dimmer, + Loader, + Header, +} from 'semantic-ui-react'; -import {checkGraphAlgorithmsInstalled} from "../services/installation" +import { checkGraphAlgorithmsInstalled } from '../services/installation'; class CheckGraphAlgorithmsInstalled extends Component { constructor(props) { - super(props) + super(props); this.state = { - algorithmsInstalled: false - } + algorithmsInstalled: false, + }; checkGraphAlgorithmsInstalled().then(result => { this.setState({ - algorithmsInstalled: result - }) + algorithmsInstalled: result, + }); }); } render() { - if(this.state.algorithmsInstalled) { + if (this.state.algorithmsInstalled) { return this.props.children; - } else { - return - This application relies on the Graph Algorithms plugin. You can install it via the 'Plugins' tab in the project view. - - } + } else { + return ( + + + This application relies on the Graph Algorithms plugin. You can + install it via the 'Plugins' tab in the project view. + + + ); + } } } -export default CheckGraphAlgorithmsInstalled +export default CheckGraphAlgorithmsInstalled; diff --git a/yarn.lock b/yarn.lock index f291f22..bb102aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8269,6 +8269,11 @@ prettier@^1.14.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== +prettier@^1.17.1: + version "1.17.1" + resolved "https://neo.jfrog.io/neo/api/npm/npm/prettier/-/prettier-1.17.1.tgz#ed64b4e93e370cb8a25b9ef7fef3e4fd1c0995db" + integrity sha1-7WS06T43DLiiW573/vPk/RwJlds= + pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"