Skip to content
Open

HW2 #16

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
7 changes: 7 additions & 0 deletions admin/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Route, NavLink } from 'react-router-dom'
import ProtectedRoute from './components/common/protected-route'
import AuthPage from './routes/auth'
import AdminPage from './routes/admin'
import EventListPage from './routes/event-list'

class App extends Component {
render() {
Expand All @@ -18,7 +19,13 @@ class App extends Component {
auth
</NavLink>
</div>
<div>
<NavLink to="/events" activeStyle={{ color: 'red' }}>
events
</NavLink>
</div>
<Route path="/auth" component={AuthPage} />
<Route path="/events" component={EventListPage} />
<ProtectedRoute path="/admin" component={AdminPage} />
</div>
)
Expand Down
47 changes: 47 additions & 0 deletions admin/src/components/event/event-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { eventSelector, getListEvent } from '../../ducks/event'
import Event from './event'

class EventList extends Component {
static propTypes = {}

componentDidMount() {
this.props.getListEvent()
}

render() {
const { loaded, error, loading } = this.props.event
if (loading) {
return (
<div>
<p>Загрузка...</p>
</div>
)
} else if (error) {
return (
<div>
<p>Произошла ошибка</p>
</div>
)
} else if (loaded) {
return (
<div>
{this.props.eventList.map((event) => (
<Event key={event.id} event={event} />
))}
</div>
)
}

return null
}
}

export default connect(
(state) => ({
eventList: eventSelector(state),
event: state.event
}),
{ getListEvent }
)(EventList)
31 changes: 31 additions & 0 deletions admin/src/components/event/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { Component } from 'react'

export default class Event extends Component {
render() {
const {
title,
url,
where,
when,
month,
submissionDeadline
} = this.props.event
return (
<div>
<p>{title}</p>
<p>
<a href={url} target="_blank" rel="noopener">
{url}
</a>
</p>
<p>{where}</p>
<p>{when}</p>
<p>{month}</p>
<p>{submissionDeadline}</p>
<br />
<br />
<br />
</div>
)
}
}
8 changes: 4 additions & 4 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 = 'react-advanced-nikolay'

export const config = {
apiKey: 'AIzaSyCbMQM0eQUSQ0SuLVAu9ZNPUcm4rdbiB8U',
apiKey: 'AIzaSyAAwv7Zb7tJbu5VjbyI6O7kQ06nm4BAiIs',
authDomain: `${appName}.firebaseapp.com`,
databaseURL: `https://${appName}.firebaseio.com`,
projectId: appName,
storageBucket: '',
messagingSenderId: '1094825197832'
storageBucket: `${appName}.appspot.com`,
messagingSenderId: '806752161129'
}

firebase.initializeApp(config)
4 changes: 2 additions & 2 deletions admin/src/ducks/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function signIn(email, password) {
*/

export function* signUpSaga({ payload: { email, password } }) {
const auth = firebase.auth()
const auth = yield call(firebase.auth)
try {
const user = yield call(
[auth, auth.createUserWithEmailAndPassword],
Expand All @@ -97,7 +97,7 @@ export function* signInSaga() {
payload: { email, password }
} = yield take(SIGN_IN_REQUEST)

const auth = firebase.auth()
const auth = yield call(firebase.auth)

try {
const user = yield apply(auth, auth.signInWithEmailAndPassword, [
Expand Down
122 changes: 122 additions & 0 deletions admin/src/ducks/auth.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { put, apply, call, take } from 'redux-saga/effects'
import firebase from 'firebase/app'
import {
signInSaga,
signUpSaga,
SIGN_IN_SUCCESS,
SIGN_IN_REQUEST,
SIGN_IN_ERROR,
SIGN_IN_REQUESTS_LIMIT,
SIGN_UP_REQUEST,
SIGN_UP_SUCCESS,
SIGN_UP_ERROR
} from './auth'

describe('people auth', () => {
// Удачный логин
it('should sign-in', () => {
const data = { email: 'test@mail.ru', password: '12345678' }

const sagaProcess = signInSaga({
type: SIGN_IN_REQUEST,
payload: data
})

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

// НЕ понятно зачем передавать {payload: data}. И как это вообще работает
Copy link
Owner

Choose a reason for hiding this comment

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

ну эти данные должны как-то внутри генератора оказаться. Почитай как работают генераторы

expect(sagaProcess.next({ payload: data }).value).toEqual(
call(firebase.auth)
)

const auth = firebase.auth()

// НЕ понятно зачем передавать auth. И как это вообще работает.
expect(sagaProcess.next(auth).value).toEqual(
apply(auth, auth.signInWithEmailAndPassword, [data.email, data.password])
)

const user = apply(auth, auth.signInWithEmailAndPassword, [
data.email,
data.password
])

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

// Limit по авторизации
it('should sign-in limit', () => {
const data = { email: 'test@mail.ru', password: '123456' }

const sagaProcess = signInSaga({
type: SIGN_IN_REQUEST,
payload: data
})

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

// НЕ понятно зачем передавать {payload: data}. И как это вообще работает
expect(sagaProcess.next({ payload: data }).value).toEqual(
call(firebase.auth)
)

const auth = firebase.auth()

// НЕ понятно зачем передавать auth. И как это вообще работает.
expect(sagaProcess.next(auth).value).toEqual(
apply(auth, auth.signInWithEmailAndPassword, [
data.email,
data.password
])
)

const user = apply(auth, auth.signInWithEmailAndPassword, [
data.email,
data.password
])

sagaProcess.next()
}

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

// Удачное добавление нового пользователя
it('should sign-up', () => {
const data = { email: 'test1@mail.ru', password: '12345678' }

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

// НЕ понятно зачем передавать {payload: data}. И как это вообще работает
expect(sagaProcess.next({ payload: data }).value).toEqual(
call(firebase.auth)
)

const auth = firebase.auth()

// НЕ понятно зачем передавать auth. И как это вообще работает.
expect(sagaProcess.next(auth).value).toEqual(
apply(auth, auth.createUserWithEmailAndPassword, [
data.email,
data.password
])
)

const user = apply(auth, auth.createUserWithEmailAndPassword, [
data.email,
data.password
])

expect(sagaProcess.next(user).value).toEqual(
put({ type: SIGN_UP_SUCCESS, payload: { user } })
)
})
Copy link
Owner

Choose a reason for hiding this comment

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

Ок, но можно бы и reducer потестить

})
99 changes: 99 additions & 0 deletions admin/src/ducks/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { appName } from '../config'
import { Record, List } from 'immutable'
import { createSelector } from 'reselect'
import { takeEvery, all, put } from 'redux-saga/effects'
import firebase from 'firebase/app'

/**
* Constants
* */
export const moduleName = 'event'
const prefix = `${appName}/${moduleName}`
export const GET_LIST_REQUEST = `${prefix}/GET_LIST_REQUEST`
export const GET_LIST_FAIL = `${prefix}/GET_LIST_FAIL`
export const GET_LIST_SUCCESS = `${prefix}/GET_LIST_SUCCESS`

/**
* Reducer
* */
const ReducerState = Record({
entities: new List([]),
loading: false,
loaded: false,
error: null
})

const EventRecord = Record({
id: null,
month: '',
submissionDeadline: '',
title: '',
url: '',
when: '',
where: ''
})

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

switch (type) {
case GET_LIST_REQUEST:
return state.set('loading', true)
case GET_LIST_FAIL:
return state.set('loading', false).set('error', error)
case GET_LIST_SUCCESS:
const eventList = Object.keys(payload.list).map((key) => ({
id: key,
...payload.list[key]
}))
return state
.set(
'entities',
new List(eventList.map((item) => new EventRecord(item)))
)
.set('loading', false)
.set('loaded', true)
.set('error', null)
default:
return state
}
}
/**
* Selectors
* */

export const stateSelector = (state) => state[moduleName]
export const eventSelector = createSelector(stateSelector, (state) => {
return state.entities.valueSeq().toArray()
})

/**
* Action Creators
* */

export function getListEvent() {
return {
type: GET_LIST_REQUEST,
payload: {}
}
}

/**
* Sagas
* */

export function* getEventListSaga() {
try {
const eventsRef = yield firebase.database().ref('/events')

const events = yield eventsRef.once('value')

yield put({ type: GET_LIST_SUCCESS, payload: { list: events.val() } })
} catch (error) {
yield put({ type: GET_LIST_FAIL, error })
}
}

export function* saga() {
yield all([takeEvery(GET_LIST_REQUEST, getEventListSaga)])
}
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 eventReducer, { moduleName as eventModule } from '../ducks/event'

export default combineReducers({
router,
form,
[authModule]: authReducer,
[peopleModule]: peopleReducer
[peopleModule]: peopleReducer,
[eventModule]: eventReducer
})
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 eventSaga } from '../ducks/event'

export default function*() {
yield all([authSaga(), peopleSaga()])
yield all([authSaga(), peopleSaga(), eventSaga()])
}
Loading