diff --git a/src/components/people/PeopleList.js b/src/components/people/PeopleList.js new file mode 100644 index 0000000..1919109 --- /dev/null +++ b/src/components/people/PeopleList.js @@ -0,0 +1,50 @@ +import React, {Component} from 'react' +import {connect} from 'react-redux' +import {moduleName, peopleListSelector, fetchPeople} from '../../ducks/people' +import {List} from 'react-virtualized' +import 'react-virtualized/styles.css' + +class PeopleList extends Component { + + constructor(props) { + super(props) + } + + componentDidMount(){ + this.props.fetchPeople() + } + + render() { + + const {people} = this.props + console.log(people) + + return
+ } + + rowRenderer = people => ({key, index, isScrolling, isVisible, style}) => { + return ( +
+ {people[index].firstName } +   + {people[index].lastName } +   + {people[index].email } +
+ ) + } +} + +export default connect(state => ({ + people: peopleListSelector(state) +}), {fetchPeople})(PeopleList) \ No newline at end of file diff --git a/src/components/people/PeopleList.test.js b/src/components/people/PeopleList.test.js new file mode 100644 index 0000000..91e2310 --- /dev/null +++ b/src/components/people/PeopleList.test.js @@ -0,0 +1,23 @@ +import React from 'react' +import {shallow, mount} from 'enzyme' +import {PeopleList} from './PeopleList' +import {PersonRecord} from '../../ducks/people' + +const testPeople = [{ + firstName: 'Alex', + lastName : 'Ivanov', + email: 'iva@gmail.com' +},{ + firstName: 'Masha', + lastName : 'Popova', + email: 'mash@gmail.com' +}].map(event => new PersonRecord({...event, uid: Math.random().toString()})) + +it('should render people list', () => { + const container = shallow() + + const rows = container.find('.test--people-list__row') + + expect(rows.length).toEqual(testPeople.length) +}) + diff --git a/src/components/routes/PersonPage.js b/src/components/routes/PersonPage.js index fd69263..9bf8df9 100644 --- a/src/components/routes/PersonPage.js +++ b/src/components/routes/PersonPage.js @@ -2,6 +2,7 @@ import React, { Component } from 'react' import {connect} from 'react-redux' import {addPerson} from '../../ducks/people' import NewPersonForm from '../people/NewPersonForm' +import PeopleList from '../people/PeopleList' class PersonPage extends Component { static propTypes = { @@ -13,6 +14,7 @@ class PersonPage extends Component {

Add new person

+
) } diff --git a/src/config.js b/src/config.js index e8d8d78..3077535 100644 --- a/src/config.js +++ b/src/config.js @@ -1,13 +1,13 @@ import firebase from 'firebase' -export const appName = "advreact-21-08" +export const appName = "advanced-react-varenik163" export const firebaseConfig = { - apiKey: "AIzaSyDjA6CeIHuni5lNm4ML1b-TSxJltsYUO8g", - authDomain: `${appName}.firebaseapp.com`, - databaseURL: `https://${appName}.firebaseio.com`, - projectId: appName, - storageBucket: `${appName}.appspot.com`, - messagingSenderId: "789814589283" -} + apiKey: "AIzaSyDVBpwgGnjIYZu7iKWsPUiUPVvVc92XC2w", + authDomain: "advanced-react-varenik163.firebaseapp.com", + databaseURL: "https://advanced-react-varenik163.firebaseio.com", + projectId: "advanced-react-varenik163", + storageBucket: "advanced-react-varenik163.appspot.com", + messagingSenderId: "860869576887" +}; firebase.initializeApp(firebaseConfig) \ No newline at end of file diff --git a/src/ducks/people.js b/src/ducks/people.js index 6a2a848..da40c4c 100644 --- a/src/ducks/people.js +++ b/src/ducks/people.js @@ -1,14 +1,21 @@ import {appName} from '../config' import {Record, List} from 'immutable' -import {put, call, takeEvery} from 'redux-saga/effects' -import {generateId} from './utils' +import {put, call, all, take, takeEvery} from 'redux-saga/effects' +import {generateId, fbPeopleDatatoEntities} from './utils' import {reset} from 'redux-form' +import {addPersonToFB} from '../mocks/index' +import {createSelector} from 'reselect' +import {entitiesSelector} from "../redux/entitiesSelector" +import firebase from 'firebase' + const ReducerState = Record({ - entities: new List([]) + entities: new List([]), + loading: false, + loaded: false }) -const PersonRecord = Record({ +export const PersonRecord = Record({ id: null, firstName: null, lastName: null, @@ -19,20 +26,37 @@ export const moduleName = 'people' const prefix = `${appName}/${moduleName}` export const ADD_PERSON_REQUEST = `${prefix}/ADD_PERSON_REQUEST` export const ADD_PERSON = `${prefix}/ADD_PERSON` - +export const FETCH_PEOPLE_REQUEST = `${prefix}/FETCH_PEOPLE_REQUEST` +export const FETCH_PEOPLE_SUCCESS = `${prefix}/FETCH_PEOPLE_SUCCESS` export default function reducer(state = new ReducerState(), action) { const {type, payload} = action switch (type) { + case FETCH_PEOPLE_REQUEST: return state + .set('loading', true) + case ADD_PERSON: return state.update('entities', entities => entities.push(new PersonRecord(payload))) + case FETCH_PEOPLE_SUCCESS: + console.log(payload) + return state + .set('loading', false) + .set('loaded', true) + .set('entities', fbPeopleDatatoEntities(payload, PersonRecord)) + default: return state } } + + +export const peopleListSelector = createSelector(entitiesSelector(moduleName), entities => ( + entities.valueSeq().toArray() +)) + export function addPerson(person) { return { type: ADD_PERSON_REQUEST, @@ -40,15 +64,40 @@ export function addPerson(person) { } } +export function fetchPeople() { + return { + type: FETCH_PEOPLE_REQUEST + } +} + export const addPersonSaga = function * (action) { + const id = yield call(generateId) + addPersonToFB(action.payload) + yield put({ type: ADD_PERSON, payload: {...action.payload, id} }) yield put(reset('person')) + +} + +export const fetchPeopleSaga = function * () { + while (true) { + yield take(FETCH_PEOPLE_REQUEST) + + const ref = firebase.database().ref('people') + + const data = yield call([ref, ref.once], 'value') + + yield put({ + type: FETCH_PEOPLE_SUCCESS, + payload: data.val() + }) + } } /* @@ -65,5 +114,8 @@ export function addPerson(person) { */ export const saga = function * () { - yield takeEvery(ADD_PERSON_REQUEST, addPersonSaga) + yield takeEvery(ADD_PERSON_REQUEST, addPersonSaga)//не понял, как их объединить? + yield all([ + fetchPeopleSaga() + ]) } diff --git a/src/ducks/utils.js b/src/ducks/utils.js index be9b34c..ab0d4ea 100644 --- a/src/ducks/utils.js +++ b/src/ducks/utils.js @@ -8,4 +8,10 @@ export function fbDatatoEntities(data, RecordModel = Map) { return (new OrderedMap(data)).mapEntries(([uid, value]) => ( [uid, (new RecordModel(value)).set('uid', uid)] )) +} + +export function fbPeopleDatatoEntities(data, RecordModel = Map) { + return Map(data).mapEntries(([uid, value]) => ( + [uid, (new RecordModel(value)).set('id', uid)] + )).toList() } \ No newline at end of file diff --git a/src/mocks/index.js b/src/mocks/index.js index f6189bf..4b428fc 100644 --- a/src/mocks/index.js +++ b/src/mocks/index.js @@ -10,4 +10,9 @@ window.runMigration = function() { firebase.database().ref('/events').once('value', data => { if (!data.val()) saveEventsToFB() }) +} + +export function addPersonToFB(person) { + const peopleRef = firebase.database().ref('/people') + peopleRef.push(person) } \ No newline at end of file diff --git a/src/redux/entitiesSelector.js b/src/redux/entitiesSelector.js new file mode 100644 index 0000000..06f3713 --- /dev/null +++ b/src/redux/entitiesSelector.js @@ -0,0 +1,6 @@ +import {createSelector} from 'reselect' + +export function entitiesSelector(moduleName) { + const stateSelector = state => state[moduleName] + return createSelector(stateSelector, state => state.entities) +} \ No newline at end of file