Skip to content

Commit

Permalink
feat: get db schema to improve cmd hints (#61)
Browse files Browse the repository at this point in the history
Co-authored-by: Adrián Insua Yañez <[email protected]>
  • Loading branch information
AdrianInsua and adrianiy authored Apr 26, 2020
1 parent 9f6b5b3 commit 8a28f03
Show file tree
Hide file tree
Showing 18 changed files with 262 additions and 210 deletions.
14 changes: 9 additions & 5 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@ import Comander from './components/comander/Comander';
import Header from './components/header/Header';

import { doLogout } from './service/neo.service';
import { getDBSchema } from './service/schema.service';
import { cls } from './global/utils';

import './App.css';
import allActions from './global/utils/store/actions';
import actions from './global/utils/store/actions';
import { useAsyncDispatch } from './global/utils/hooks/dispatch';

function App() {
const [cookies, setCookie] = useCookies(["neo4jDash.sess"]);
const [loading, setLoading] = useState(true);
const [theme, user] = useSelector(state => [state.currentTheme, state.currentUser]);

const dispatch = useDispatch();
const asyncDispatch = useAsyncDispatch();

const loginHandler = useCallback((response) => {
setCookie("neo4jDash.sess", JSON.stringify(response));
dispatch(allActions.userActions.setUser(response));
}, [dispatch, setCookie]);
const loginHandler = useCallback((userData) => {
setCookie("neo4jDash.sess", JSON.stringify(userData));
dispatch(actions.user.setUser(userData));
asyncDispatch(actions.db.setProperties, getDBSchema(userData.sessionId));
}, [asyncDispatch, dispatch, setCookie]);

useEffect(() => {
if (cookies["neo4jDash.sess"] && cookies["neo4jDash.sess"].sessionId && loading) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/card/Card.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useCallback, useRef, useEffect } from 'react';
import Summary from './Summary';

import { getChart } from '../../service/neo.service';
import { getQuery } from '../../service/neo.service';

import { ColumnLayout, RowLayout } from '../../global/layouts';
import Chart from '../../global/components/chart/Chart';
Expand Down Expand Up @@ -39,7 +39,7 @@ function Card(props) {

const fecthData = useCallback(async () => {
try {
const results = await getChart(user.sessionId, props.query);
const results = await getQuery(user.sessionId, props.query);
setResults(results);
setError(null);
} catch (err) {
Expand Down
11 changes: 10 additions & 1 deletion src/components/comander/Comander.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import Timeline from '../timeline/Timeline';
import CypherCodeMirror from './CypherCodeMirror';

import { codeMirrorSettings, neo4jSchema } from './cypher/common';
import { codeMirrorSettings, neo4jSchema, toSchema } from './cypher/common';

import { cls, concatUniqueStrings } from '../../global/utils';
import { RowLayout, ColumnLayout } from '../../global/layouts';
Expand All @@ -19,9 +19,18 @@ function Comander(props) {
const [highlightedSuggestion, setHighlightedSuggestion] = useState(-1);
const [fullscreen, setFullscreen] = useState(false);
const [editor, setEditor] = useState(null);
const schema = useRef(neo4jSchema);
const cm = useRef(null);
const storedQueries = useRef([]);
const theme = useSelector(state => state.currentTheme);
const dbSchema = useSelector(state => state.dbSchema);

useEffect(() => {
Object.keys(dbSchema)
.forEach(key =>
schema.current[key] = [...schema.current[key], ...toSchema(key, dbSchema[key].records)]
);
}, [dbSchema])

useEffect(() => {
if (editor) {
Expand Down
134 changes: 49 additions & 85 deletions src/components/comander/cypher/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,50 @@ export const codeMirrorSettings = {
},
};

export const toProcedure = (row) => {
const name = row[0];
const signature = row[1].replace(row[0], "");

let returnItems = [];
const matches = signature.match(/\([^)]*\) :: \((.*)\)/i);

if (matches) {
returnItems = matches[1].split(", ").map((returnItem) => {
const returnItemMatches = returnItem.match(/(.*) :: (.*)/);
return {
name: returnItemMatches[1],
signature: returnItemMatches[2],
};
});
}

return {
name,
signature,
returnItems,
};
};

export const toSchema = (type, records) => {
switch (type) {
case "procedures":
return records.map(record => {
const proc = record.toObject();
return toProcedure([proc.name, proc.signature])
});
case "functions":
return records.map(record => {
const func = record.toObject();
return {
name: func.name,
signature: func.signature.replace(func.name, ""),
};
})
default:
return records.map((record) => record.get(0));
}
};

export const neo4jSchema = {
consoleCommands: [
{ name: ":clear" },
Expand All @@ -64,95 +108,15 @@ export const neo4jSchema = {
{ name: ":history" },
{ name: ":queries" },
],
labels: [
":Spacey mc spaceface",
":Legislator",
":State",
":Party",
":Body",
":Bill",
":Subject",
":Committee",
":Congress",
],
relationshipTypes: [
":REPRESENTS",
":IS_MEMBER_OF",
":ELECTED_TO",
":PROPOSED_DURING",
":SPONSORED_BY",
":VOTED ON",
":REFERRED_TO",
":SERVES_ON",
":DEALS_WITH",
],
parameters: ["age", "name", "surname"],
propertyKeys: [
"bioguideID",
"code",
"name",
"type",
"billID",
"title",
"thomasID",
"birthday",
"wikipediaID",
"currentParty",
"state",
"votesmartID",
"fecIDs",
"republicanCount",
"otherCount",
"cspanID",
"democratCount",
"lastName",
"firstName",
"party",
"opensecretsID",
"icpsrID",
"religion",
"lisID",
"govtrackID",
"gender",
"district",
"number",
"enacted",
"officialTitle",
"vetoed",
"active",
"popularTitle",
"cosponsor",
"vote",
"jurisdiction",
"url",
"rank",
"washpostID",
],
labels: [],
relationshipTypes: [],
parameters: [],
propertyKeys: [],
functions: functions.data.map((data) => ({
name: data.row[0],
signature: data.row[1].replace(data.row[0], ""),
})),
procedures: procedures.data.map((data) => {
const name = data.row[0];
const signature = data.row[1].replace(data.row[0], "");

let returnItems = [];
const matches = signature.match(/\([^)]*\) :: \((.*)\)/i);

if (matches) {
returnItems = matches[1].split(", ").map((returnItem) => {
const returnItemMatches = returnItem.match(/(.*) :: (.*)/);
return {
name: returnItemMatches[1],
signature: returnItemMatches[2],
};
});
}

return {
name,
signature,
returnItems,
};
return toProcedure(data.row)
}),
};
6 changes: 3 additions & 3 deletions src/components/header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react';
import { useCookies } from 'react-cookie';
import { useSelector, useDispatch } from 'react-redux';

import allActions from '../../global/utils/store/actions';
import { RowLayout } from '../../global/layouts';
import { cls } from '../../global/utils';

import styles from './Header.module.css';
import actions from '../../global/utils/store/actions';

function Header(props) {
// eslint-disable-next-line no-unused-vars
Expand All @@ -16,12 +16,12 @@ function Header(props) {

const doLogout = () => {
removeCookie('neo4jDash.sess');
dispatch(allActions.userActions.logOut());
dispatch(actions.user.logOut());
};

const handleClick = () => {
const newTheme = theme.id === 'dark' ? 'light' : 'dark';
dispatch(allActions.themeActions.setCustomTheme(newTheme));
dispatch(actions.theme.setCustomTheme(newTheme));
}

return (
Expand Down
6 changes: 3 additions & 3 deletions src/global/components/chart/Chart.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect, useCallback } from 'react';
import GraphComponent from './../../../assets/visualization/Graph';
import { getChart } from './../../../service/neo.service';
import { getQuery } from './../../../service/neo.service';

import { extractNodesAndRelationshipsFromRecordsForOldVis } from './utils/graph-utils';
import deepmerge from 'deepmerge';
Expand Down Expand Up @@ -103,7 +103,7 @@ function Chart (props) {
ORDER BY id(o)
LIMIT ${props.maxNeighbours -
currentNeighbourIds.length}`
const results = await getChart(user.sessionId, query);
const results = await getQuery(user.sessionId, query);
const count = results.records.length > 0 ? parseInt(results.records[0].get("c").toString()) : 0;
const resultGraph = extractNodesAndRelationshipsFromRecordsForOldVis(results.records, false);
await autoCompleteRelationships(_graph._nodes, resultGraph.nodes);
Expand All @@ -116,7 +116,7 @@ function Chart (props) {
existingNodeIds = existingNodeIds.concat(newNodeIds)
const query =
'MATCH (a)-[r]->(b) WHERE id(a) IN $existingNodeIds AND id(b) IN $newNodeIds RETURN r;'
const results = await getChart(user.sessionId, query);
const results = await getQuery(user.sessionId, query);
return {
...extractNodesAndRelationshipsFromRecordsForOldVis(results.records, false),
};
Expand Down
10 changes: 10 additions & 0 deletions src/global/utils/hooks/dispatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useDispatch } from "react-redux"

export const useAsyncDispatch = () => {
const dispatch = useDispatch();

return async (action, method) => {
const result = await method;
dispatch(action(result));
}
}
12 changes: 12 additions & 0 deletions src/global/utils/store/actions/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DBPROPERTIES } from "../reducers/db"

const setProperties = (properties) => {
return {
type: DBPROPERTIES,
properties
}
}

export default {
setProperties
}
14 changes: 8 additions & 6 deletions src/global/utils/store/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import userActions from './user';
import themeActions from './theme';
import user from './user';
import theme from './theme';
import db from './db';

const allActions = {
userActions,
themeActions
const actions = {
user,
theme,
db
}

export default allActions;
export default actions;
11 changes: 6 additions & 5 deletions src/global/utils/store/actions/theme.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const setAutoTheme = theme => {
import { AUTOTHEME, THEME } from "../reducers/theme";

const setAutoTheme = () => {
return {
type: 'SET_AUTO_THEME',
payload: theme
type: AUTOTHEME
}
};

const setCustomTheme = theme => {
return {
type: 'SET_THEME',
payload: theme
type: THEME,
theme
}
};

Expand Down
9 changes: 6 additions & 3 deletions src/global/utils/store/actions/user.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { SETUSER, LOGOUT } from "../reducers/user"


const setUser = userObj => {
return {
type: 'SET_USER',
payload: userObj
type: SETUSER,
userData: userObj
}
}

const logOut = () => {
return {
type: 'LOG_OUT'
type: LOGOUT
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/global/utils/store/reducers/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const DBPROPERTIES = 'SET_DB_PROPERTIES';

const dbSchema = (state = {}, action) => {
switch (action.type) {
case DBPROPERTIES:
return {
...state,
...action.properties
}
default:
return state;
}
};

export default dbSchema;
4 changes: 3 additions & 1 deletion src/global/utils/store/reducers/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import currentUser from "./user";
import currentTheme from './theme';
import dbSchema from './db';
import { combineReducers } from "redux";

const rootReducer = combineReducers({
currentUser,
currentTheme
currentTheme,
dbSchema
});

export default rootReducer;
Loading

0 comments on commit 8a28f03

Please sign in to comment.