Skip to content
Binary file added public/assets/trash-can.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<style>
nav.submenu {
background: #eee;
padding: .5rem;
}
nav.submenu a {
margin-right: 1rem;
color: #333;
text-decoration: none;
}
nav.submenu a.active {
font-weight: bold;
}
.error-field {
margin-bottom: 1rem;
}
</style>
</head>
<body>
<noscript>
Expand Down
50 changes: 43 additions & 7 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React, { Component } from 'react'
import {Route, NavLink} from 'react-router-dom'
import {Route} from 'react-router-dom'
import {connect} from 'react-redux'
import ProtectedRoute from './common/ProtectedRoute'
import AdminPage from './routes/Admin'
import AuthPage from './routes/Auth'
import PersonPage from './routes/PersonPage'
import EventsPage from './routes/EventsPage'
import CustomDragLayer from './CustomDragLayer'
import Submenu from './common/Submenu'
import {userAuthorizedSelector} from '../ducks/auth'

class App extends Component {
static propTypes = {
Expand All @@ -16,11 +19,7 @@ class App extends Component {
return (
<div>
<h1>Hello world</h1>
<ul>
<li><NavLink to='/admin' activeStyle = {{color: 'red'}}>admin</NavLink></li>
<li><NavLink to='/people' activeStyle = {{color: 'red'}}>people</NavLink></li>
<li><NavLink to='/events' activeStyle = {{color: 'red'}}>events</NavLink></li>
</ul>
{this.renderSubmenu()}
<ProtectedRoute path = '/admin' component = {AdminPage}/>
<ProtectedRoute path = '/people' component={PersonPage}/>
<ProtectedRoute path = '/events' component={EventsPage}/>
Expand All @@ -29,6 +28,43 @@ class App extends Component {
</div>
)
}

renderSubmenu() {
const links = []

if (this.props.authorized) {
links.push({
to: '/admin',
title: 'Admin',
}, {
to: '/people',
title: 'People',
}, {
to: '/events',
title: 'Events',
}, {
to: '/logout',
title: 'Logout',
})
}
else {
links.push({
to: '/auth/signin',
title: 'Sign in',
}, {
to: '/auth/signup',
title: 'Sign up',
})
}

const props = {
links,
}

return <Submenu {...props} />
}
}

export default App
export default connect(state => ({
authorized: userAuthorizedSelector(state)
}), null, null, { pure: false })(App)
3 changes: 2 additions & 1 deletion src/components/CustomDragLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class CustomDragLayer extends Component {
const DragPreview = item.DragPreview

if (!DragPreview) return null
if (!offset) return null

const style = {
transform: `translate(${offset.x}px, ${offset.y}px)`
Expand Down Expand Up @@ -46,7 +47,7 @@ class CustomDragLayer extends Component {

const collect = (monitor) => ({
isDragging: monitor.isDragging(),
offset: monitor.getSourceClientOffset(),
offset: monitor.getClientOffset(),
item: monitor.getItem()
})

Expand Down
4 changes: 2 additions & 2 deletions src/components/common/ErrorField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ function ErrorField(props) {
const {input, type, meta: {error, touched}} = props
const errorText = touched && error && <div style={{color: 'red'}}>{error}</div>
return (
<div>
<label>{input.name}</label>
<div className="error-field">
<label>{input.name}<br/></label>
<input {...input} type={type}/>
{errorText}
</div>
Expand Down
46 changes: 46 additions & 0 deletions src/components/common/Garbage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import {DropTarget} from 'react-dnd'
import { deleteEvent } from '../../ducks/events'

const baseStyle = {
margin: '20px 0',
padding: 10,
display: 'inline-block',
borderRadius: 10,
opacity: .5,
}

class Garbage extends Component {
render() {
const { connectDropTarget, canDrop, hovered } = this.props

const style = {
...baseStyle,
border: `5px dashed ${hovered ? '#666' : 'transparent'}`,
}

return connectDropTarget(
<div style={style}>
<img src="/assets/trash-can.png" width={100} height={100} />
</div>
)
}
}

const spec = {
drop(props, monitor) {
const { id } = monitor.getItem()
props.deleteEvent(id)
}
}

const collect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
canDrop: monitor.canDrop(),
hovered: monitor.isOver()
})

export default connect(null, {deleteEvent})(
DropTarget('event', spec, collect)(Garbage)
)
6 changes: 3 additions & 3 deletions src/components/common/ProtectedRoute.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from 'react'
import {Route} from 'react-router-dom'
import {connect} from 'react-redux'
import {userSelector} from '../../ducks/auth'
import {userAuthorizedSelector} from '../../ducks/auth'

class ProtectedRoute extends Component {
static propTypes = {
Expand All @@ -21,5 +21,5 @@ class ProtectedRoute extends Component {
}

export default connect(state => ({
authorized: !!userSelector(state)
}), null, null, { pure: false })(ProtectedRoute)
authorized: userAuthorizedSelector(state)
}), null, null, { pure: false })(ProtectedRoute)
30 changes: 30 additions & 0 deletions src/components/common/Submenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'

class Submenu extends Component {
render() {
return (
<nav className="submenu">
{this.props.links.map(this.renderSubmenuItem.bind(this))}
</nav>
)
}

renderSubmenuItem(item, index) {
const { to, title } = item

const props = {
key: index,
activeClassName: 'active',
to,
}

return (
<NavLink {...props}>
{title}
</NavLink>
)
}
}

export default Submenu
30 changes: 30 additions & 0 deletions src/components/events/EventDragPreview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { eventSelector } from '../../ducks/events'

class EventDragPreview extends Component {
render() {
const style = {
display: 'inline-block',
border: '1px solid #ccc',
borderRadius: 5,
background: '#eee',
transform: 'translate(-30px, -40px)',
padding: 10,
}

const { event } = this.props

return (
<div style={style}>
<h4 style={{margin:0}}>{event.title}</h4>
<div>{event.where}</div>
<div>{event.when}</div>
</div>
)
}
}

export default connect((state, props) => ({
event: eventSelector(state, props)
}))(EventDragPreview)
43 changes: 43 additions & 0 deletions src/components/events/EventRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { Component } from 'react'
import {DragSource} from 'react-dnd'
import { defaultTableRowRenderer as DefaultTableRowRenderer } from 'react-virtualized'
import {getEmptyImage} from 'react-dnd-html5-backend'
import DragPreview from './EventDragPreview'

class EventRow extends Component {
componentDidMount() {
this.props.connectPreview(getEmptyImage())
}

render() {
const { key, connectDragSource } = this.props

return connectDragSource(
<div key={key}>
<DefaultTableRowRenderer {...this.props} />
</div>
)
}
}

const spec = {
beginDrag(props) {
return {
id: props.rowData.uid,
DragPreview
}
},

/*endDrag() {
console.log('---', 'endDrag')
}*/
}

const collect = (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectPreview: connect.dragPreview(),
// isDragging: monitor.isDragging(),
// canDrag: monitor.canDrag(),
})

export default DragSource('event', spec, collect)(EventRow)
8 changes: 2 additions & 6 deletions src/components/events/EventTableVirtualized.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import React, { Component } from 'react'
import {Table, Column} from 'react-virtualized'
import {connect} from 'react-redux'
import {fetchAllEvents, selectEvent, selectedEventsSelector, eventListSelector, loadedSelector, loadingSelector} from '../../ducks/events'
import {selectEvent, selectedEventsSelector, eventListSelector, loadedSelector, loadingSelector} from '../../ducks/events'
import Loader from '../common/Loader'
import 'react-virtualized/styles.css'

class EventTableVirtualized extends Component {
static propTypes = {

};
componentDidMount() {
this.props.fetchAllEvents()
console.log('---', 'load events')
}

render() {
if (this.props.loading) return <Loader />
Expand Down Expand Up @@ -54,4 +50,4 @@ export default connect((state, props) => ({
loading: loadingSelector(state),
loaded: loadedSelector(state),
selected: selectedEventsSelector(state)
}), { fetchAllEvents, selectEvent })(EventTableVirtualized)
}), { selectEvent })(EventTableVirtualized)
15 changes: 12 additions & 3 deletions src/components/events/VirtualizedLazyTable.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {moduleName, fetchLazy, selectEvent, eventListSelector} from '../../ducks/events'
import {Table, Column, InfiniteLoader} from 'react-virtualized'
import EventRow from './EventRow'
import 'react-virtualized/styles.css'

export class EventList extends Component {
static propTypes = {

allowSelectEvents: PropTypes.bool
};

componentDidMount() {
Expand All @@ -33,6 +35,7 @@ export class EventList extends Component {
height={300}
onRowClick={this.handleRowClick}
onRowsRendered={onRowsRendered}
rowRenderer={this.rowRenderer}
>
<Column
label="title"
Expand Down Expand Up @@ -66,8 +69,14 @@ export class EventList extends Component {
}

handleRowClick = (rowData) => {
const {selectEvent} = this.props
selectEvent && selectEvent(rowData.uid)
if (this.allowSelectEvents === true) {
const {selectEvent} = this.props
selectEvent && selectEvent(rowData.uid)
}
}

rowRenderer = props => {
return <EventRow {...props} />
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/routes/Admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Admin extends Component {
<h2>Admin Page</h2>
<SelectedEvents/>
<PeopleList/>
<EventList/>
<EventList allowSelectEvents={true} />
</div>
)
}
Expand Down
6 changes: 2 additions & 4 deletions src/components/routes/Auth.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { Component } from 'react'
import {Route, NavLink} from 'react-router-dom'
import {Route} from 'react-router-dom'
import {connect} from 'react-redux'
import {signUp, signIn} from '../../ducks/auth'
import SignIn from '../auth/SignIn'
Expand All @@ -14,8 +14,6 @@ class AuthPage extends Component {
return (
<div>
<h2>Auth page</h2>
<NavLink to = '/auth/signin' activeStyle = {{color: 'red'}}>sign in</NavLink>
<NavLink to = '/auth/signup' activeStyle = {{color: 'red'}}>sign up</NavLink>
<Route path = '/auth/signin' render = {() => <SignIn onSubmit = {this.handleSignIn}/>}/>
<Route path = '/auth/signup' render = {() => <SignUp onSubmit = {this.handleSignUp}/>}/>
</div>
Expand All @@ -26,4 +24,4 @@ class AuthPage extends Component {
handleSignUp = ({email, password}) => this.props.signUp(email, password)
}

export default connect(null, { signUp, signIn })(AuthPage)
export default connect(null, { signUp, signIn })(AuthPage)
Loading