diff --git a/admin/src/components/events/events-table-virtualized.js b/admin/src/components/events/events-table-virtualized.js
index eb5ba6c..92f5866 100644
--- a/admin/src/components/events/events-table-virtualized.js
+++ b/admin/src/components/events/events-table-virtualized.js
@@ -1,42 +1,57 @@
import React, { Component } from 'react'
import { connect } from 'react-redux'
import {
- fetchAllEvents,
+ fetchLazyEvents,
toggleSelection as handleSelect,
eventListSelector,
loadedSelector,
loadingSelector
} from '../../ducks/events'
-import Loader from '../common/loader'
-import { Table, Column } from 'react-virtualized'
+import { InfiniteLoader, Table, Column } from 'react-virtualized'
import 'react-virtualized/styles.css'
export class EventsTable extends Component {
static propTypes = {}
componentDidMount() {
- this.props.fetchAllEvents && this.props.fetchAllEvents()
+ this.fetchEvents()
}
render() {
- const { loading, events } = this.props
- if (loading) return
+ const { events, loaded } = this.props
return (
-
+ {({ onRowsRendered, registerChild }) => (
+
+ )}
+
)
}
+ fetchEvents = () => {
+ this.props.fetchLazyEvents && this.props.fetchLazyEvents()
+ }
+
+ isRowLoaded = () => this.props.loaded
+
rowGetter = ({ index }) => this.props.events[index]
}
@@ -46,5 +61,5 @@ export default connect(
loading: loadingSelector(state),
loaded: loadedSelector(state)
}),
- { fetchAllEvents, handleSelect }
+ { fetchLazyEvents, handleSelect }
)(EventsTable)
diff --git a/admin/src/components/events/events-table-virtualized.test.js b/admin/src/components/events/events-table-virtualized.test.js
new file mode 100644
index 0000000..7040ff5
--- /dev/null
+++ b/admin/src/components/events/events-table-virtualized.test.js
@@ -0,0 +1,21 @@
+import React from 'react'
+import { EventsTable } from './events-table-virtualized'
+import { shallow, mount } from 'enzyme'
+import eventsMocks from '../../mocks/conferences'
+
+const events = eventsMocks.map((event) => ({
+ ...event,
+ uid: Math.random().toString()
+}))
+
+describe('EventsTable', () => {
+ it('should render some events', () => {
+ const container = mount()
+
+ expect(container.find('.test--event-list_item').length).toBeGreaterThan(1)
+ })
+
+ it('should fetch events', (done) => {
+ shallow( done()} />)
+ })
+})
diff --git a/admin/src/ducks/events.js b/admin/src/ducks/events.js
index 74107b8..d0230c3 100644
--- a/admin/src/ducks/events.js
+++ b/admin/src/ducks/events.js
@@ -1,4 +1,4 @@
-import { all, takeEvery, put, call } from 'redux-saga/effects'
+import { all, takeEvery, put, call, take, select } from 'redux-saga/effects'
import { appName } from '../config'
import { Record, OrderedSet, OrderedMap } from 'immutable'
import firebase from 'firebase/app'
@@ -14,6 +14,9 @@ const prefix = `${appName}/${moduleName}`
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_SELECTION = `${prefix}/TOGGLE_SELECTION`
/**
@@ -41,6 +44,7 @@ export default function reducer(state = new ReducerRecord(), action) {
switch (type) {
case FETCH_ALL_START:
+ case FETCH_LAZY_START:
return state.set('loading', true)
case FETCH_ALL_SUCCESS:
@@ -49,6 +53,12 @@ export default function reducer(state = new ReducerRecord(), action) {
.set('loaded', true)
.set('entities', fbToEntities(payload, EventRecord))
+ case FETCH_LAZY_SUCCESS:
+ return state
+ .set('loading', false)
+ .set('loaded', Object.keys(payload).length < 10)
+ .mergeIn(['entities'], fbToEntities(payload, EventRecord))
+
case TOGGLE_SELECTION:
return state.update(
'selected',
@@ -83,6 +93,9 @@ export const loadedSelector = createSelector(
export const eventListSelector = createSelector(entitiesSelector, (entities) =>
entities.valueSeq().toArray()
)
+export const lastEventSelector = createSelector(entitiesSelector, (entities) =>
+ entities.last()
+)
export const selectedIdsSelector = createSelector(stateSelector, (state) =>
state.selected.toArray()
@@ -104,6 +117,12 @@ export function fetchAllEvents() {
}
}
+export function fetchLazyEvents() {
+ return {
+ type: FETCH_LAZY_REQUEST
+ }
+}
+
export function toggleSelection(uid) {
return {
type: TOGGLE_SELECTION,
@@ -130,6 +149,38 @@ export function* fetchAllSaga() {
})
}
+export function* fetchLazySaga() {
+ while (true) {
+ yield take(FETCH_LAZY_REQUEST)
+
+ const loaded = yield select(loadedSelector)
+ if (loaded) return
+
+ const loading = yield select(loadingSelector)
+ if (loading) continue
+
+ yield put({
+ type: FETCH_LAZY_START
+ })
+
+ const lastEvent = yield select(lastEventSelector)
+
+ const ref = firebase
+ .database()
+ .ref('events')
+ .orderByKey()
+ .limitToFirst(10)
+ .startAt(lastEvent ? lastEvent.uid : '')
+
+ 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_ALL_REQUEST, fetchAllSaga), fetchLazySaga()])
}