Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions client/src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,31 @@ export class App extends Component {
render() {
const { user } = this.props;
return (
<div className="wrapper">
<div>
<Navbar color="faded" light toggleable>
<Container>
<NavbarToggler right onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav navbar>
<NavItem>
<NavLink href="/#/posts">Posts</NavLink>
</NavItem>
<NavItem>
<NavLink href="/#/categories">Categories</NavLink>
</NavItem>
<NavItem>
<NavLink href="/#/users">Users</NavLink>
</NavItem>
</Nav>
<Nav navbar className="ml-auto">
<NavItem>
<NavLink href onClick={this.logout}><small>{user.email}</small> Logout</NavLink>
</NavItem>
</Nav>
</Collapse>
<NavbarToggler right onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav navbar>
<NavItem>
<NavLink href="/#/posts">Posts</NavLink>
</NavItem>
<NavItem>
<NavLink href="/#/categories">Categories</NavLink>
</NavItem>
<NavItem>
<NavLink href="/#/users">Users</NavLink>
</NavItem>
</Nav>
<Nav navbar className="ml-auto">
<NavItem>
<NavLink href onClick={this.logout}><small>{user.email}</small> Logout</NavLink>
</NavItem>
</Nav>
</Collapse>
</Container>
</Navbar>
<Container>
<Container className="container-main">
{this.props.children}
</Container>
</div>
Expand Down
6 changes: 5 additions & 1 deletion client/src/components/Auth/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { connect } from 'react-redux';
import { replace } from 'react-router-redux';
import { SubmissionError } from 'redux-form';

import { CardSingle } from '../UI';
import LoginForm from './LoginForm';
import { login } from '../../store/api';

Expand All @@ -15,7 +16,10 @@ export class Login extends Component {

render() {
return (
<LoginForm onSubmit={this.onSubmit}/>
<CardSingle>
<h1>Login</h1>
<LoginForm onSubmit={this.onSubmit}/>
</CardSingle>
);
}
}
Expand Down
36 changes: 16 additions & 20 deletions client/src/components/Auth/LoginForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,28 @@ import { isEmpty } from 'lodash';
import { Field, reduxForm } from 'redux-form';
import { Alert, Button, Form } from 'reactstrap';

import { CardSingle } from '../UI';
import { InputField, required } from '../../forms';

class LoginForm extends Component {
render() {
const { handleSubmit, pristine, reset, submitting, error } = this.props;
const { handleSubmit, submitting, error } = this.props;

return (
<CardSingle>
<h1>Login</h1>
<Form onSubmit={handleSubmit}>
{error && <Alert color="danger">{error}</Alert>}
<Field
name="email"
label="Email"
component={InputField}
/>
<Field
name="password"
label="Password"
component={InputField}
type='password'
/>
<Button disabled={submitting}>Login</Button>
</Form>
</CardSingle>
<Form onSubmit={handleSubmit}>
{error && <Alert color="danger">{error}</Alert>}
<Field
name="email"
label="Email"
component={InputField}
/>
<Field
name="password"
label="Password"
component={InputField}
type='password'
/>
<Button disabled={submitting}>Login</Button>
</Form>
);
}
}
Expand Down
34 changes: 23 additions & 11 deletions client/src/components/Categories/CategoryForm.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import React, { Component, PropTypes } from 'react';
import { isEmpty } from 'lodash';
import { Field, reduxForm } from 'redux-form';
import { Button, Form, Col, Row } from 'reactstrap';

import { InputField, required } from '../../forms';

class CategoryForm extends Component {
render() {
const { handleSubmit, pristine, reset, submitting } = this.props;
const { handleSubmit, onDelete, reset, isNew, submitSucceeded } = this.props;

if (isNew && submitSucceeded) {
setTimeout(() => reset());
}

return (
<form onSubmit={handleSubmit}>
<div>
<Field name="name" component={InputField} />
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>Undo Changes</button>
</div>
</form>
<Form onSubmit={handleSubmit}>
<Row>
<Col xs="10" sm="8" md="6">
<Field
name="name"
component={InputField}
/>
</Col>
<Col xs="2">
{
isNew
? <Button color="success">+</Button>
: <Button color="danger" onClick={onDelete}>X</Button>
}
</Col>
</Row>
</Form>
);
}
}
Expand All @@ -29,6 +42,5 @@ const validate = (values) => {

export default reduxForm({
enableReinitialize: true,
form: 'category',
validate,
})(CategoryForm);
16 changes: 13 additions & 3 deletions client/src/components/Categories/CategoryList.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { find, keyBy } from 'lodash';

import { withResourceList } from '../../hocs';
import CategoryForm from './CategoryForm';

export class CategoryList extends Component {
componentWillMount() {
this.props.fetchResourceList({ page: { size: 999 } });
}

render() {
const { resourceList } = this.props;
const { resourceList, onSubmit, onDelete } = this.props;

return (
<div>
{resourceList.data.map(category =>
<div key={category.id}>
<Link to={`/categories/${category.id}`}>{category.name}</Link>
<CategoryForm
form={`category-${category.id}`}
initialValues={category}
onSubmit={onSubmit}
onDelete={onDelete(category)}
/>
</div>,
)}
<CategoryForm
isNew={true}
form="category-new"
onSubmit={onSubmit}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React, { Component } from 'react';

import { Card, CardBlock } from 'reactstrap';

export default () => (
export default (props) => (
<Card className="mx-auto" style={{maxWidth: '400px', marginTop: '50px'}}>
<CardBlock>{this.props.children}</CardBlock>
<CardBlock>{props.children}</CardBlock>
</Card>
);
2 changes: 1 addition & 1 deletion client/src/components/UI/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export CardSingle from './CardSingle';
export EditHeader from './EditHeader';
export Pagination from './Pagination';
export SingleCard from './SingleCard';
8 changes: 1 addition & 7 deletions client/src/hocs/withResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,11 @@ const withResource = resourceKey => (WrappedComponent) => {
withHandlers({
onSubmit: props => (values) => {
const { params, createResource, updateResource, redirectToIndex } = props;

const payload = {
id: params.id,
...values,
};

const payload = { id: params.id, ...values };
return (params.id ? updateResource : createResource)(payload)
.then(redirectToIndex)
.catch((errors) => { throw new SubmissionError(errors); });
},

onDelete: props => (e) => {
const { deleteResource, resource, redirectToIndex } = props;
e.preventDefault();
Expand Down
17 changes: 17 additions & 0 deletions client/src/hocs/withResourceList.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { SubmissionError } from 'redux-form';
import { get, find, isEmpty, omitBy } from 'lodash';
import compose from 'recompose/compose';
import withHandlers from 'recompose/withHandlers';

import {
fetchList,
createResource,
updateResource,
deleteResource,
getList,
} from '../store/api';

Expand Down Expand Up @@ -34,6 +38,16 @@ const withResourceList = resourceKey => (WrappedComponent) => {
const { page = {} } = params;
fetchResourceList({ ...params, page: { ...page, number } });
},
onSubmit: props => (values) => {
const { createResource, updateResource } = props;
return (values.id ? updateResource : createResource)(values)
.catch((errors) => { throw new SubmissionError(errors); });
},
onDelete: props => (resource) => (e) => {
const { deleteResource } = props;
e.preventDefault();
deleteResource(resource);
},
}),
);

Expand All @@ -43,6 +57,9 @@ const withResourceList = resourceKey => (WrappedComponent) => {

const mapDispatchToProps = dispatch => ({
fetchResourceList: (params = {}) => dispatch(fetchList(resourceKey, params)),
createResource: payload => dispatch(createResource(resourceKey, payload, {list: true})),
updateResource: payload => dispatch(updateResource(resourceKey, payload)),
deleteResource: payload => dispatch(deleteResource(resourceKey, payload)),
});

return connect(mapStateToProps, mapDispatchToProps)(enhance(WrappedComponent));
Expand Down
3 changes: 3 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.container-main {
padding-top: 15px;
}
2 changes: 1 addition & 1 deletion client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Routes from './components/Routes';
import configureStore from './store/configureStore';

import 'bootstrap/dist/css/bootstrap.css';
import './index.scss';
import './index.css';

const store = configureStore(hashHistory);
const history = syncHistoryWithStore(hashHistory, store);
Expand Down
Empty file removed client/src/index.scss
Empty file.
6 changes: 5 additions & 1 deletion client/src/store/api/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ export default (state = initialState, action) => {
return addNormalized(newState, payload);
}
case actionType(CREATE, SUCCESS): {
return addNormalized(newState, payload);
newState = addNormalized(newState, payload);
if (meta.list) {
newState = imm.push(newState, [key, 'list', 'ids'], payload.data.id);
}
return newState;
}
case actionType(UPDATE, SUCCESS): {
return addNormalized(newState, payload);
Expand Down