Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
davidballester committed Nov 15, 2019
2 parents 28c9aa2 + 01eff77 commit e697048
Show file tree
Hide file tree
Showing 15 changed files with 175 additions and 16 deletions.
26 changes: 25 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"react-color": "2.17.3",
"react-dom": "16.8.3",
"react-force-graph-2d": "1.9.1",
"react-helmet": "^5.2.1",
"react-markdown": "4.1.0",
"react-redux": "6.0.1",
"react-router-dom": "5.0.0",
Expand Down
2 changes: 2 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
User-Agent: *
Disallow:
7 changes: 7 additions & 0 deletions src/app.component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Helmet } from 'react-helmet';

import Canvas from './components/canvas';
import Graph from './scenes/graph';
Expand All @@ -11,6 +12,12 @@ export class App extends Component {
render() {
return (
<React.Fragment>
<Helmet>
<meta charSet="utf-8" />
<title>Grapher</title>
<link rel="canonical" href="https://wizardly-minsky-4657d5.netlify.com" />
<meta name="Description" content="Grapher is a graph editor. It's that simple!" />
</Helmet>
<Route path={[ROUTES.BASE, ROUTES.GRAPHS]} exact render={() => <Welcome />} />
<Route path={ROUTES.IMPORT_GRAPH} exact render={() => [<Import key="Import" />, <Canvas key="Canvas" />]} />
<Route path={ROUTES.GRAPH} exact render={() => <Graph key="Graph" />} />
Expand Down
7 changes: 7 additions & 0 deletions src/ducks/graph/graph.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const GRAPH_SET_NAME = 'grapher/Graph/SET_NAME';
export const GRAPH_CREATE = 'grapher/Graph/CREATE';
export const GRAPH_LOAD = 'grapher/Graph/LOAD';
export const GRAPH_LOAD_SUCCESS = 'grapher/Graph/LOAD_SUCCESS';
export const GRAPH_LOAD_ERROR = 'grapher/Graph/LOAD_ERROR';
export const GRAPH_DELETE = 'grapher/Graph/DELETE';
export const GRAPH_SET_CONTENTS = 'grapher/Graph/SET_CONTENTS';
export const GRAPH_SET_TEXT = 'grapher/Graph/SET_TEXT';
Expand Down Expand Up @@ -44,6 +45,12 @@ export function loadGraphSuccess(graph) {
};
}

export function loadGraphError() {
return {
type: GRAPH_LOAD_ERROR,
};
}

export function deleteGraph(id) {
return {
type: GRAPH_DELETE,
Expand Down
19 changes: 18 additions & 1 deletion src/ducks/graph/graph.reducer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { GRAPH_SET_NAME, GRAPH_CREATE, GRAPH_LOAD_SUCCESS, GRAPH_SET_CONTENTS, GRAPH_SET_TEXT, GRAPH_SET_TEXT_ERROR } from './graph.actions';
import {
GRAPH_SET_NAME,
GRAPH_CREATE,
GRAPH_LOAD_SUCCESS,
GRAPH_LOAD_ERROR,
GRAPH_SET_CONTENTS,
GRAPH_SET_TEXT,
GRAPH_SET_TEXT_ERROR,
} from './graph.actions';

const initialState = {
id: '',
Expand Down Expand Up @@ -66,6 +74,7 @@ const initialState = {
groups: {},
text: '',
textError: undefined,
loadError: false,
};

export default function reducer(state = initialState, action) {
Expand All @@ -87,11 +96,19 @@ export default function reducer(state = initialState, action) {
groups: {},
text: '',
...graph,
loadError: false,
};
}
case GRAPH_LOAD_SUCCESS: {
return {
...action.payload,
loadError: false,
};
}
case GRAPH_LOAD_ERROR: {
return {
...state,
loadError: true,
};
}
case GRAPH_SET_CONTENTS: {
Expand Down
34 changes: 29 additions & 5 deletions src/ducks/graph/graph.reducer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jest.mock('uuid/v4', () => ({
default: () => 'uuid',
}));

import { setGraphName, createGraph, loadGraphSuccess, setContents, setText, setTextError } from './graph.actions';
import { setGraphName, createGraph, loadGraphSuccess, loadGraphError, setContents, setText, setTextError } from './graph.actions';
import reducer from './graph.reducer';

describe('reducer', () => {
Expand Down Expand Up @@ -67,7 +67,14 @@ describe('reducer', () => {
};
const action = createGraph({});
const state = reducer(initialState, action);
expect(state).toEqual(expectedState);
expect(state).toEqual(expect.objectContaining(expectedState));
});

it('sets the loadError flag to false', () => {
const initialState = { loadError: true };
const action = createGraph({});
const state = reducer(initialState, action);
expect(state.loadError).toBeFalsy();
});
});

Expand All @@ -83,9 +90,26 @@ describe('reducer', () => {
};
const action = loadGraphSuccess(graph);
const state = reducer(initialState, action);
expect(state).toEqual({
...graph,
});
expect(state).toEqual(
expect.objectContaining({
...graph,
})
);
});

it('sets the loadError flag to false', () => {
const initialState = { loadError: true };
const action = loadGraphSuccess({});
const state = reducer(initialState, action);
expect(state.loadError).toBeFalsy();
});
});

describe('GRAPH_LOAD_ERROR', () => {
it('sets the loadError flag to true', () => {
const action = loadGraphError();
const state = reducer({}, action);
expect(state.loadError).toBeTruthy();
});
});

Expand Down
7 changes: 6 additions & 1 deletion src/ducks/graph/graph.sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GRAPH_LOAD,
GRAPH_DELETE,
loadGraphSuccess,
loadGraphError,
GRAPH_SET_CONTENTS,
GRAPH_SET_TEXT,
setTextError,
Expand All @@ -30,7 +31,11 @@ export function* saveGraphSaga() {
export function* doLoadGraph(action) {
const graphId = action.payload;
const graph = yield call([graphService, 'readGraph'], graphId);
yield put(loadGraphSuccess(graph));
if (graph) {
yield put(loadGraphSuccess(graph));
} else {
yield put(loadGraphError());
}
}

export function* loadGraphSaga() {
Expand Down
9 changes: 8 additions & 1 deletion src/ducks/graph/graph.sagas.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
GRAPH_LOAD,
loadGraph,
loadGraphSuccess,
loadGraphError,
GRAPH_DELETE,
deleteGraph,
GRAPH_SET_CONTENTS,
Expand Down Expand Up @@ -96,12 +97,18 @@ describe('graph', () => {
expect(gen.next().value).toEqual(call([graphService, 'readGraph'], action.payload));
});

it('puts a `loadGraphSuccess` action with the graph returned by `readGraph`', () => {
it('puts a `loadGraphSuccess` action with the graph returned by `readGraph` if there is such a graph', () => {
const graph = { foo: 'bar' };
const gen = cloneableGenerator(doLoadGraph)(action);
gen.next();
expect(gen.next(graph).value).toEqual(put(loadGraphSuccess(graph)));
});

it('puts a loadGraphError action if there is no graph read', () => {
const gen = cloneableGenerator(doLoadGraph)(action);
gen.next();
expect(gen.next(undefined).value).toEqual(put(loadGraphError()));
});
});

describe(deleteGraphSaga.name, () => {
Expand Down
10 changes: 7 additions & 3 deletions src/ducks/graph/graph.selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ export function getName(state) {
}

function getNodes(state) {
return graphSelector(state).nodes;
return graphSelector(state).nodes || {};
}

export function getLinks(state) {
return graphSelector(state).links;
return graphSelector(state).links || {};
}

export function getLinkById(state, linkId) {
Expand Down Expand Up @@ -64,7 +64,7 @@ export const getSerializedGraph = createSelector(

const getGroups = createSelector(
graphSelector,
(graph) => graph.groups
(graph) => graph.groups || []
);

export const getGroupsAsArray = createSelector(
Expand All @@ -83,3 +83,7 @@ export function getText(state) {
export function getTextError(state) {
return graphSelector(state).textError;
}

export function getLoadError(state) {
return graphSelector(state).loadError;
}
10 changes: 10 additions & 0 deletions src/ducks/graph/graph.selectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ describe('selectors', () => {
const nodes = getNodesAsArray(appState);
expect(nodes).toEqual([node1, node2, node3]);
});

it('returns an empty array if the state contains no nodes', () => {
const nodes = getNodesAsArray({ graph: {} });
expect(nodes).toEqual([]);
});
});

describe('getLinksAsArray', () => {
Expand Down Expand Up @@ -105,6 +110,11 @@ describe('selectors', () => {
const links = getLinksAsArray(appState);
expect(links).toEqual([link1, link2, link3]);
});

it('returns an empty array if the state contains no links', () => {
const links = getLinksAsArray({ graph: {} });
expect(links).toEqual([]);
});
});

describe(getNodesIds.name, () => {
Expand Down
37 changes: 37 additions & 0 deletions src/scenes/graph/components/not-found.component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

import Container from '@material-ui/core/Container';
import Typography from '@material-ui/core/Typography';
import Link from '@material-ui/core/Link';
import { withStyles } from '@material-ui/core/styles';

const styles = (theme) => ({
title: {
marginTop: theme.spacing(1),
marginBottom: theme.spacing(4),
},
text: {
marginBottom: theme.spacing(2),
},
});

function NotFound({ classes }) {
return (
<Container>
<Typography component="h1" variant="h1" className={classes.title}>
Graph not found!
</Typography>
<Typography component="p" variant="body1" className={classes.text}>
That's unfortunate. If you are looking for a graph that was there before, remember that they are stored in your browser. Are you using a
different browser?
</Typography>
<Typography component="p" variant="body1" className={classes.text}>
To avoid accidental losses, remember that you can export your graphs from the top right corner and save them as JSON files into your computer
that you can then import into Grapher whenever you want.
</Typography>
<Link href="/">Go to your graphs</Link>
</Container>
);
}

export default withStyles(styles, { withTheme: true })(NotFound);
13 changes: 10 additions & 3 deletions src/scenes/graph/graph.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ import Export from './components/export';
import Onboarding from './components/onboarding';
import GraphLarge from './components/graph-large.component';
import GraphSmall from './components/graph-small.component';
import NotFound from './components/not-found.component';

export default function Graph({ graphId, graphName, loadedGraphId, loadGraph, openGraphList, loadError }) {
const theme = useTheme();
const bigScreen = useMediaQuery(theme.breakpoints.up('md'));

if (loadError) {
return <NotFound />;
}

export default function Graph({ graphId, graphName, loadedGraphId, loadGraph, openGraphList, classes }) {
if (!!graphId && graphId !== loadedGraphId) {
loadGraph(graphId);
}
const theme = useTheme();
const bigScreen = useMediaQuery(theme.breakpoints.up('md'));

return (
<>
<ConfirmDeletes />
Expand Down
6 changes: 6 additions & 0 deletions src/scenes/graph/graph.component.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { createShallow } from '@material-ui/core/test-utils';

import Graph from './graph.component';
import NotFound from './components/not-found.component';

describe(Graph.name, () => {
let shallow;
Expand Down Expand Up @@ -35,4 +36,9 @@ describe(Graph.name, () => {
shallow(<Graph loadGraph={loadGraph} graphId={'foo'} loadedGraphId={'bar'} />);
expect(loadGraph).toHaveBeenCalledWith('foo');
});

it('returns the NotFound component if the loadError prop is true', () => {
const component = shallow(<Graph loadGraph={loadGraph} graphId={'foo'} loadedGraphId={'bar'} loadError={true} />);
expect(component.find(NotFound).getElement()).toBeDefined();
});
});
Loading

0 comments on commit e697048

Please sign in to comment.