Skip to content
Open
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
14,012 changes: 14,012 additions & 0 deletions admin/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"firebase": "^5.0.2",
"history": "^4.7.2",
"immutable": "^4.0.0-rc.9",
"lodash": "^4.17.10",
"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-redux": "^5.0.7",
Expand Down
5 changes: 5 additions & 0 deletions admin/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class App extends Component {
auth
</NavLink>
</div>
<div>
<NavLink to="/admin/events" activeStyle={{ color: 'red' }}>
events
</NavLink>
</div>
<Route path="/auth" component={AuthPage} />
<ProtectedRoute path="/admin" component={AdminPage} />
</div>
Expand Down
54 changes: 54 additions & 0 deletions admin/src/components/events/events-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { Component } from 'react'
import _ from 'lodash'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'
import { eventsListSelector } from '../../ducks/events'

class EventsList extends Component {
static propTypes = {}

render() {
const { events } = this.props
console.log(events)
return !!Object.keys(events).length ? (
<table cellPadding={20} border="1" cellSpacing={0}>
<thead>
<tr>
<th>Month</th>
<th>Submission Deadline</th>
<th>Title</th>
<th>url</th>
<th>When</th>
<th>Where</th>
</tr>
</thead>
<tbody>
{_.map(events, (event, key) => (
<tr key={key}>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я б для Event сразу отдельный компонент заводил

<td>{event.month}</td>
<td>
{!!event.submissionDeadline ? event.submissionDeadline : 'None'}
</td>
<td>{event.title}</td>
<td>
<a href={event.url} target="_blank">
{event.url}
</a>
</td>
<td>{event.when}</td>
<td>{event.where}</td>
</tr>
))}
</tbody>
</table>
) : (
<h2>No events now</h2>
)
}
}

const mapStateToProps = createStructuredSelector({
events: eventsListSelector
})

export default connect(mapStateToProps)(EventsList)
6 changes: 3 additions & 3 deletions admin/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/database'

export const appName = 'advreact-10-05'
export const appName = 'advancedreact-f31cd'

export const config = {
apiKey: 'AIzaSyCbMQM0eQUSQ0SuLVAu9ZNPUcm4rdbiB8U',
apiKey: 'AIzaSyC4HchzzCItq1dPJRY_B-InXmnkIasqMVw',
authDomain: `${appName}.firebaseapp.com`,
databaseURL: `https://${appName}.firebaseio.com`,
projectId: appName,
storageBucket: '',
messagingSenderId: '1094825197832'
messagingSenderId: '71475877514'
}

firebase.initializeApp(config)
94 changes: 94 additions & 0 deletions admin/src/ducks/auth.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import firebase from 'firebase/app'
import { signInSaga, signUpSaga } from './auth'
import {
SIGN_IN_REQUESTS_LIMIT,
SIGN_IN_REQUEST,
SIGN_IN_SUCCESS,
SIGN_UP_REQUEST,
SIGN_UP_SUCCESS
} from 'admin/src/ducks/auth'
import { all, call, apply, put, takeEvery, take } from 'redux-saga/effects'

describe('auth duck', () => {
it('should sign in', () => {
const userData = {
email: 'asd@asd.asd',
password: 'asdasdasd'
}
const sagaProcess = signInSaga({
type: SIGN_IN_REQUEST,
payload: userData
})

expect(sagaProcess.next().value).toEqual(take(SIGN_IN_REQUEST))

const auth = firebase.auth()

expect(sagaProcess.next({ payload: userData }).value).toEqual(
apply(auth, auth.signInWithEmailAndPassword, [
userData.email,
userData.password
])
)

expect(sagaProcess.next({ email: userData.email }).value).toEqual(
put({
type: SIGN_IN_SUCCESS,
payload: { user: { email: userData.email } }
})
)
})

it('should not allow to sign in more then 3 times', () => {
const userData = {
email: 'asd@asd.asd',
password: 'asdasd'
}
const sagaProcess = signInSaga({
type: SIGN_IN_REQUEST,
payload: userData
})

for (let i = 0; i < 3; i++) {
expect(sagaProcess.next().value).toEqual(take(SIGN_IN_REQUEST))

sagaProcess.next({ payload: userData })
sagaProcess.throw(new Error('invalid password'))
}

expect(sagaProcess.next().value).toEqual(
put({ type: SIGN_IN_REQUESTS_LIMIT })
)
expect(sagaProcess.next().done).toEqual(true)
})

it('should sign up', () => {
const auth = firebase.auth()

const userData = {
email: 'asd@asd.asd',
password: 'asdasd'
}

const sagaProcess = signUpSaga({
type: SIGN_UP_REQUEST,
payload: userData
})

expect(sagaProcess.next({ payload: userData }).value).toEqual(
call(
[auth, auth.createUserWithEmailAndPassword],
userData.email,
userData.password
)
)

expect(sagaProcess.next({ email: userData.email }).value).toEqual(
put({
type: SIGN_UP_SUCCESS,
payload: { user: { email: userData.email } }
})
)
expect(sagaProcess.next().done).toEqual(true)
})
})
77 changes: 77 additions & 0 deletions admin/src/ducks/events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { appName } from '../config'
import { Record, Map } from 'immutable'
import { createSelector } from 'reselect'
import { takeEvery, all, put, apply } from 'redux-saga/effects'
import firebase from 'firebase/app'

/**
* Constants
* */
export const moduleName = 'events'
const prefix = `${appName}/${moduleName}`
export const FETCH_EVENTS_REQUEST = `${prefix}/FETCH_EVENTS_REQUEST`
export const FETCH_EVENTS = `${prefix}/FETCH_EVENTS`

/**
* Reducer
* */
const ReducerState = Record({
isFetched: false,
isFetching: false,
entities: new Map({})
})

export default function reducer(state = new ReducerState(), action) {
const { type, payload } = action

switch (type) {
case FETCH_EVENTS_REQUEST:
return state.set('isFetched', false).set('isFetching', true)

case FETCH_EVENTS:
return state
.update('entities', (entities) => new Map(payload))
.set('isFetched', true)
.set('isFetching', false)

default:
return state
}
}
/**
* Selectors
* */

export const stateSelector = (state) => state[moduleName]
export const eventsSelector = createSelector(stateSelector, (state) =>
state.toJS()
)
export const eventsListSelector = createSelector(stateSelector, (state) =>
state.entities.toJS()
)

/**
* Action Creators
* */

export function fetchEvents() {
return {
type: FETCH_EVENTS_REQUEST
}
}

/**
* Sagas
* */

export function* fetchEventsSaga() {
const database = firebase.database().ref('/events')

const snapshot = yield apply(database, database.once, ['value'])

yield put({ type: FETCH_EVENTS, payload: snapshot.val() })
}

export function* saga() {
yield all([takeEvery(FETCH_EVENTS_REQUEST, fetchEventsSaga)])
}
4 changes: 3 additions & 1 deletion admin/src/redux/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { routerReducer as router } from 'react-router-redux'
import { reducer as form } from 'redux-form'
import authReducer, { moduleName as authModule } from '../ducks/auth'
import peopleReducer, { moduleName as peopleModule } from '../ducks/people'
import eventsReducer, { moduleName as eventsModule } from '../ducks/events'

export default combineReducers({
router,
form,
[authModule]: authReducer,
[peopleModule]: peopleReducer
[peopleModule]: peopleReducer,
[eventsModule]: eventsReducer
})
3 changes: 2 additions & 1 deletion admin/src/redux/saga.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { all } from 'redux-saga/effects'
import { saga as authSaga } from '../ducks/auth'
import { saga as peopleSaga } from '../ducks/people'
import { saga as eventsSaga } from '../ducks/events'

export default function*() {
yield all([authSaga(), peopleSaga()])
yield all([authSaga(), peopleSaga(), eventsSaga()])
}
2 changes: 2 additions & 0 deletions admin/src/routes/admin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from 'react'
import { Route } from 'react-router-dom'
import PersonPage from './person-page'
import EventsPage from './events-page'

class AdminPage extends Component {
static propTypes = {}
Expand All @@ -10,6 +11,7 @@ class AdminPage extends Component {
<div>
<h1>Admin Page</h1>
<Route path="/admin/people" component={PersonPage} />
<Route path="/admin/events" component={EventsPage} />
</div>
)
}
Expand Down
25 changes: 25 additions & 0 deletions admin/src/routes/events-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { fetchEvents, eventsSelector } from '../ducks/events'
import EventsList from '../components/events/events-list'

class PersonPage extends Component {
componentWillMount() {
this.props.fetchEvents()
}

render() {
const { events } = this.props

return (
<div>
<h2>Events</h2>
{events.isFetched ? <EventsList /> : <h2>Loading...</h2>}
</div>
)
}
}

export default connect((state) => ({ events: eventsSelector(state) }), {
fetchEvents
})(PersonPage)