Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task 3 #15

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
15 changes: 11 additions & 4 deletions admin/src/components/events/events-table-virtualized.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Table, Column } from 'react-virtualized'
import {
fetchAllEvents,
fetchLazyEvents,
selectEvent,
eventListSelector,
loadedSelector,
Expand All @@ -15,12 +15,12 @@ export class EventsTableVirtualized extends Component {
static propTypes = {}

componentDidMount() {
this.props.fetchAllEvents()
this.props.fetchLazyEvents()
}

render() {
const { events, loading } = this.props
if (loading) return <Loader />
if (loading && !events.length) return <Loader />

return (
<Table
Expand All @@ -32,6 +32,7 @@ export class EventsTableVirtualized extends Component {
headerHeight={50}
onRowClick={this.handleSelect}
overscanRowCount={1}
onRowsRendered={this.handleScroll}
>
<Column dataKey="title" width={200} label="name" />
<Column dataKey="where" width={300} label="place" />
Expand All @@ -43,6 +44,12 @@ export class EventsTableVirtualized extends Component {
rowGetter = ({ index }) => this.props.events[index]

handleSelect = ({ rowData }) => this.props.selectEvent(rowData.uid)

handleScroll = ({ stopIndex }) => {
if (stopIndex > this.props.events.length - 3) {
this.props.fetchLazyEvents()
}
}
}

export default connect(
Expand All @@ -51,5 +58,5 @@ export default connect(
loading: loadingSelector(state),
loaded: loadedSelector(state)
}),
{ fetchAllEvents, selectEvent }
{ fetchLazyEvents, selectEvent }
)(EventsTableVirtualized)
21 changes: 21 additions & 0 deletions admin/src/components/events/events-table-virtualized.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'
import Enzyme, { shallow } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import { EventsTableVirtualized } from './events-table-virtualized'
import Loader from '../common/loader'

Enzyme.configure({ adapter: new Adapter() })

describe('EventsTableVirtualized', () => {
it('should render a loader', () => {
const container = shallow(
<EventsTableVirtualized loading events={[]} fetchLazyEvents={() => {}} />
)

expect(container.contains(<Loader />)).toBe(true)
})

it('should fetch lazy events', (done) => {
shallow(<EventsTableVirtualized fetchLazyEvents={done} events={[]} />)
})
})
50 changes: 50 additions & 0 deletions admin/src/ducks/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import { fbToEntities } from './utils'
* */
export const moduleName = 'events'
const prefix = `${appName}/${moduleName}`
const fetchLimit = 10

export const FETCH_ALL_REQUEST = `${prefix}/FETCH_ALL_REQUEST`
export const FETCH_ALL_START = `${prefix}/FETCH_ALL_START`
export const FETCH_ALL_SUCCESS = `${prefix}/FETCH_ALL_SUCCESS`
export const FETCH_LAZY_REQUEST = `${prefix}/FETCH_LAZY_REQUEST`
export const FETCH_LAZY_START = `${prefix}/FETCH_LAZY_START`
export const FETCH_LAZY_SUCCESS = `${prefix}/FETCH_LAZY_SUCCESS`
export const TOGGLE_SELECT = `${prefix}/TOGGLE_SELECT`

/**
Expand Down Expand Up @@ -49,6 +53,17 @@ export default function reducer(state = new ReducerRecord(), action) {
.set('loaded', true)
.set('entities', fbToEntities(payload, EventRecord))

case FETCH_LAZY_START:
return state.set('loading', true)

case FETCH_LAZY_SUCCESS: {
const loadedEntities = state.entities.size ? state.entities : null

return state
.set('loading', false)
.set('entities', fbToEntities(payload, EventRecord, loadedEntities))
}

case TOGGLE_SELECT:
return state.update(
'selected',
Expand Down Expand Up @@ -84,6 +99,11 @@ export const eventListSelector = createSelector(entitiesSelector, (entities) =>
entities.toArray()
)

export const lastEventKeySelector = createSelector(
eventListSelector,
(events) => (events.length ? events[events.length - 1].uid : '')
)

export const selectionSelector = createSelector(
stateSelector,
(state) => state.selected
Expand All @@ -106,6 +126,12 @@ export function fetchAllEvents() {
}
}

export function fetchLazyEvents() {
return {
type: FETCH_LAZY_REQUEST
}
}

export const selectEvent = (uid) => ({
type: TOGGLE_SELECT,
payload: { uid }
Expand All @@ -132,6 +158,30 @@ export function* fetchAllSaga() {
})
}

export function* fetchLazySaga() {
const eventsState = yield select(stateSelector)
if (eventsState.loading) return

yield put({
type: FETCH_LAZY_START
})

const fetchStartAt = yield select(lastEventKeySelector)
const ref = firebase
.database()
.ref('events')
.orderByKey()
.limitToFirst(fetchLimit)
.startAt(fetchStartAt)
const snapshot = yield call([ref, ref.once], 'value')

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

export function* saga() {
yield all([takeEvery(FETCH_ALL_REQUEST, fetchAllSaga)])
yield all([takeEvery(FETCH_LAZY_REQUEST, fetchLazySaga)])
}
11 changes: 9 additions & 2 deletions admin/src/ducks/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ export function generateId() {
return Date.now() + Math.random()
}

export function fbToEntities(values, DataRecord) {
return new List(
export function fbToEntities(values, DataRecord, initailValues) {
const newList = new List(
Object.entries(values).map(
([uid, value]) => new DataRecord({ uid, ...value })
)
)

// такой подход для этой утилиты ок? Или лучше выделить новую функцию?
if (initailValues) {
return new List(initailValues).concat(newList)
}

return newList
}