Skip to content

Commit

Permalink
feat: add ActionEditor to visualize actions json, update tests
Browse files Browse the repository at this point in the history
closes #226
  • Loading branch information
pyphilia committed Mar 16, 2020
1 parent b2dd03d commit bada1b2
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import LoadSpace from './components/LoadSpace';
import SpaceScreen from './components/space/SpaceScreen';
import DeveloperScreen from './components/developer/DeveloperScreen';
import { OnlineTheme, OfflineTheme } from './themes';
import ActionDashboard from './components/actionDashboard/ActionDashboard';
import {
SETTINGS_PATH,
SPACE_PATH,
Expand All @@ -25,6 +26,7 @@ import {
VISIT_PATH,
LOAD_SPACE_PATH,
DEVELOPER_PATH,
ACTION_DASHBOARD_PATH,
} from './config/paths';
import {
getGeolocation,
Expand Down Expand Up @@ -159,6 +161,11 @@ export class App extends Component {
path={DEVELOPER_PATH}
component={DeveloperScreen}
/>
<Route
exact
path={ACTION_DASHBOARD_PATH}
component={ActionDashboard}
/>
</Switch>
</div>
</Router>
Expand Down
138 changes: 138 additions & 0 deletions src/components/actionDashboard/ActionDashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { Component } from 'react';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core';
import { withTranslation } from 'react-i18next';
import { withRouter } from 'react-router';
import Typography from '@material-ui/core/Typography';
import CssBaseline from '@material-ui/core/CssBaseline';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import Drawer from '@material-ui/core/Drawer';
import Divider from '@material-ui/core/Divider';
import PropTypes from 'prop-types';
import MainMenu from '../common/MainMenu';
import ActionEditor from './ActionEditor';
import Styles from '../../Styles';
import Banner from '../common/Banner';

export class ActionDashboard extends Component {
state = {
open: false,
};

static propTypes = {
t: PropTypes.func.isRequired,
classes: PropTypes.shape({
root: PropTypes.string.isRequired,
appBar: PropTypes.string.isRequired,
appBarShift: PropTypes.string.isRequired,
menuButton: PropTypes.string.isRequired,
hide: PropTypes.string.isRequired,
drawer: PropTypes.string.isRequired,
drawerPaper: PropTypes.string.isRequired,
drawerHeader: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
contentShift: PropTypes.string.isRequired,
developer: PropTypes.string.isRequired,
screenTitle: PropTypes.string.isRequired,
}).isRequired,
theme: PropTypes.shape({
direction: PropTypes.string.isRequired,
}).isRequired,
history: PropTypes.shape({
replace: PropTypes.func.isRequired,
}).isRequired,
i18n: PropTypes.shape({
changeLanguage: PropTypes.func.isRequired,
}).isRequired,
};

handleDrawerOpen = () => {
this.setState({ open: true });
};

handleDrawerClose = () => {
this.setState({ open: false });
};

render() {
const { classes, theme, t } = this.props;
const { open } = this.state;

return (
<div className={classes.root}>
<CssBaseline />
<AppBar
position="fixed"
className={classNames(classes.appBar, {
[classes.appBarShift]: open,
})}
>
<Toolbar disableGutters={!open}>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerOpen}
className={classNames(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
</Toolbar>
</AppBar>
<Drawer
className={classes.drawer}
variant="persistent"
anchor="left"
open={open}
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={this.handleDrawerClose}>
{theme.direction === 'ltr' ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<MainMenu />
</Drawer>
<main
className={classNames(classes.content, {
[classes.contentShift]: open,
})}
>
<div className={classes.drawerHeader} />
<div className={classes.developer}>
<Typography variant="h4" className={classes.screenTitle}>
{t('Action Dashboard')}
</Typography>
<br />
<Banner
text={t(
'Danger Zone! Proceed with caution as changes to this section might lead to data loss.'
)}
type="error"
/>
<ActionEditor />
</div>
</main>
</div>
);
}
}

const StyledComponent = withStyles(Styles, { withTheme: true })(
ActionDashboard
);

const TranslatedComponent = withTranslation()(StyledComponent);

export default withRouter(TranslatedComponent);
97 changes: 97 additions & 0 deletions src/components/actionDashboard/ActionEditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { Component } from 'react';
import _ from 'lodash';
import { connect } from 'react-redux';
import ReactJson from 'react-json-view';
import PropTypes from 'prop-types';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import { withTranslation } from 'react-i18next';
import { withStyles } from '@material-ui/core';
import { getDatabase, setDatabase } from '../../actions';
import Loader from '../common/Loader';
import Styles from '../../Styles';
import SampleDatabase from '../../data/sample.json';

export class ActionEditor extends Component {
static propTypes = {
t: PropTypes.func.isRequired,
classes: PropTypes.shape({
button: PropTypes.string.isRequired,
}).isRequired,
dispatchGetDatabase: PropTypes.func.isRequired,
dispatchSetDatabase: PropTypes.func.isRequired,
database: PropTypes.shape({
user: PropTypes.object,
spaces: PropTypes.array,
actions: PropTypes.array,
}),
};

static defaultProps = {
database: {},
};

componentDidMount() {
const { dispatchGetDatabase } = this.props;
dispatchGetDatabase();
}

handleEdit = ({ updated_src: updatedSrc }) => {
const { dispatchSetDatabase } = this.props;
dispatchSetDatabase(updatedSrc);
};

handleUseSampleDatabase = () => {
const { dispatchSetDatabase } = this.props;
dispatchSetDatabase(SampleDatabase);
};

render() {
const { database, t, classes } = this.props;

if (!database || _.isEmpty(database)) {
return <Loader />;
}

return (
<div>
<Typography variant="h6">{t('Manually Edit the Database')}</Typography>
<ReactJson
name="actions"
collapsed
src={database.actions}
onEdit={this.handleEdit}
onAdd={this.handleEdit}
onDelete={this.handleEdit}
/>
<br />
<Button
variant="contained"
className={classes.button}
onClick={this.handleUseSampleDatabase}
color="primary"
>
{t('Use Sample Database')}
</Button>
</div>
);
}
}

const mapStateToProps = ({ Developer }) => ({
database: Developer.get('database'),
});

const mapDispatchToProps = {
dispatchGetDatabase: getDatabase,
dispatchSetDatabase: setDatabase,
};

const StyledComponent = withStyles(Styles, { withTheme: true })(ActionEditor);
const TranslatedComponent = withTranslation()(StyledComponent);
const ConnectedComponent = connect(
mapStateToProps,
mapDispatchToProps
)(TranslatedComponent);

export default ConnectedComponent;
11 changes: 11 additions & 0 deletions src/components/common/MainMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
SPACES_NEARBY_PATH,
VISIT_PATH,
DEVELOPER_PATH,
ACTION_DASHBOARD_PATH,
} from '../../config/paths';

export class MainMenu extends Component {
Expand Down Expand Up @@ -147,6 +148,16 @@ export class MainMenu extends Component {
</ListItemIcon>
<ListItemText primary={t('Settings')} />
</MenuItem>
<MenuItem
onClick={() => this.handleClick(ACTION_DASHBOARD_PATH)}
button
selected={path === ACTION_DASHBOARD_PATH}
>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary={t('Action Dashboard')} />
</MenuItem>
{this.renderDeveloperMode()}
</List>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/MainMenu.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
LOAD_SPACE_PATH,
SETTINGS_PATH,
DEVELOPER_PATH,
ACTION_DASHBOARD_PATH,
} from '../../config/paths';

// offline: 2, online: 5
const MENUITEM_OFFLINE_NUMBER = 2;
const MENUITEM_OFFLINE_ONLINE_COUNT = 7;
const MENUITEM_OFFLINE_ONLINE_COUNT = 8;

const createMainMenuProps = (developerMode, path) => {
return {
Expand Down Expand Up @@ -105,6 +106,7 @@ describe('<MainMenu />', () => {
[true, LOAD_SPACE_PATH, 'Load'],
[true, SETTINGS_PATH, 'Settings'],
[true, DEVELOPER_PATH, 'Developer'],
[true, ACTION_DASHBOARD_PATH, 'Action Dashboard'],
])('<MainMenu /> selects one MenuItem', (developerMode, path, text) => {
it(`select path=${path} (developerMode = ${developerMode})`, () => {
const props = createMainMenuProps(developerMode, path);
Expand Down
24 changes: 24 additions & 0 deletions src/components/common/__snapshots__/MainMenu.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ exports[`<MainMenu /> <MainMenu /> with developerMode = false renders correctly
primary="Settings"
/>
</WithStyles(ForwardRef(MenuItem))>
<WithStyles(ForwardRef(MenuItem))
button={true}
onClick={[Function]}
selected={false}
>
<WithStyles(ForwardRef(ListItemIcon))>
<SettingsIcon />
</WithStyles(ForwardRef(ListItemIcon))>
<WithStyles(ForwardRef(ListItemText))
primary="Action Dashboard"
/>
</WithStyles(ForwardRef(MenuItem))>
</WithStyles(ForwardRef(List))>
`;

Expand Down Expand Up @@ -247,6 +259,18 @@ exports[`<MainMenu /> <MainMenu /> with developerMode = true renders correctly 1
primary="Settings"
/>
</WithStyles(ForwardRef(MenuItem))>
<WithStyles(ForwardRef(MenuItem))
button={true}
onClick={[Function]}
selected={false}
>
<WithStyles(ForwardRef(ListItemIcon))>
<SettingsIcon />
</WithStyles(ForwardRef(ListItemIcon))>
<WithStyles(ForwardRef(ListItemText))
primary="Action Dashboard"
/>
</WithStyles(ForwardRef(MenuItem))>
<WithStyles(ForwardRef(MenuItem))
button={true}
onClick={[Function]}
Expand Down
1 change: 1 addition & 0 deletions src/config/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export const LOAD_SPACE_PATH = '/load-space';
export const SETTINGS_PATH = '/settings';
export const SPACE_PATH = '/space/:id';
export const DEVELOPER_PATH = '/developer';
export const ACTION_DASHBOARD_PATH = '/action-dashboard';

0 comments on commit bada1b2

Please sign in to comment.