Finally refactored actions so they can be import as a single object

This commit is contained in:
Alex Hunt 2018-05-08 20:36:04 -04:00
parent e1b4797c52
commit b90e6a49b1
20 changed files with 155 additions and 206 deletions

View File

@ -1,3 +1,3 @@
{
"presets": ["env", "react"]
"presets": ["env", "react", "stage-3"]
}

View File

@ -31,6 +31,7 @@
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-3": "^6.24.1",
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.2",

View File

@ -1,21 +1,20 @@
//
// -------------------
// API Request Actions
//
// These actions are handled by middleware and initiate
// an API request.
// -------------------
// These actions are handled by middleware and initiate an API request.
const apiActions = {
// Requesting the list of documents without complete text
export const getDocumentList = (response = {}) =>
getDocumentList: (response = {}) =>
({
type: 'GET_DOCUMENT_LIST',
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data,
state: response.state
})
}),
// Requesting the full text of a given document
export const getDocumentText = (response = {}) =>
getDocumentText: (response = {}) =>
({
type: 'GET_DOCUMENT_TEXT',
id: response.id,
@ -23,33 +22,32 @@
status: response.status ? response.status : 'request',
data: response.data,
state: response.state,
})
}),
// Deleting a given document
export const deleteDocument = (response = {}) =>
deleteDocument: (response = {}) =>
({
type: 'DELETE_DOCUMENT',
id: response.id,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
}),
// Saving a document, create or update depending on if it receives an id
export const saveDocument = (response = {}) =>
saveDocument: (response = {}) =>
({
type: 'SAVE_DOCUMENT',
id: response.id ? response.id : null,
docType: response.docType,
status: response.status ? response.status : 'request',
data: response.data
})
}),
// Requesting search results with a search input
export const getSearchResults = (response={}) => {
return ({
getSearchResults: (response={}) =>
({
type: 'GET_SEARCH_RESULTS',
data: response.data,
status: response.status ? response.status : 'request'
})
}
}
export default apiActions

View File

@ -1,27 +1,29 @@
//
// -------------------
// EditorState Actions
//
// These actions handle state changes for the DraftJS editor
// -------------------
// These actions handle state changes for the DraftJS editor
const editorStateActions = {
// Update EditorState on change
export const updateEditorState = editorState =>
updateEditorState: editorState =>
({
type: 'UPDATE_EDITOR_STATE',
data: editorState
})
}),
// Handle Editor inline style buttons
export const applyInlineStyles = (editorState, style) =>
applyInlineStyles: (editorState, style) =>
({
type: 'APPLY_INLINE_STYLE',
editorState: editorState,
style: style
})
}),
// Handle key commands to apply inline styles
export const handleEditorKeyCommand = (editorState, command) =>
handleEditorKeyCommand: (editorState, command) =>
({
type: 'HANDLE_EDITOR_KEY_COMMAND',
editorState: editorState,
command: command
})
}),
}
export default editorStateActions

13
src/actions/index.js Normal file
View File

@ -0,0 +1,13 @@
import apiActions from './apiActions'
import userActions from './userActions'
import inputActions from './inputActions'
import editorStateActions from './editorStateActions'
const actions = {
...apiActions,
...userActions,
...inputActions,
...editorStateActions
}
export default actions

View File

@ -1,20 +1,21 @@
//
// -------------
// Input Actions
//
// These actions handle states for the non-DraftJS input elements
// -------------
// These actions handle states for the non-DraftJS input elements
const inputActions = {
// Handle changes to the document title input box
export const updateDocumentTitleChange = documentTitleInput => {
return ({
updateDocumentTitleChange: documentTitleInput =>
({
type: 'UPDATE_DOCUMENT_TITLE',
data: documentTitleInput.target.value
})
}
}),
// Handle changes to the search input box
export const updateSearchInput = searchInput => {
return ({
updateSearchInput: searchInput =>
({
type: 'UPDATE_SEARCH_INPUT',
data: searchInput.target.value
})
}
})
}
export default inputActions

View File

@ -1,109 +1,98 @@
//
// ------------
// User Actions
//
// These actions are initiated by user action
// ------------
// These actions are initiated by user action
const userActions = {
// Select a document to read or edit
export const setCurrentDocument = (id, docType) =>
setCurrentDocument: (id, docType) =>
({
type: 'SET_CURRENT_DOCUMENT',
id: id,
docType: docType
})
}),
// Click the 'New' button in the Editor
export const createNewDocument = docType =>
createNewDocument: docType =>
({
type: 'CREATE_DOCUMENT',
docType: docType
})
}),
// Click 'Submit' to save a document edit
export const submitDocumentEdit = (currentDocument, editorState, documentTitleInput, docType) =>
submitDocumentEdit: (currentDocument, editorState, documentTitleInput, docType) =>
({
type: 'SUBMIT_DOCUMENT_EDIT',
currentDocument: currentDocument,
editorState: editorState,
documentTitleInput: documentTitleInput,
docType: docType
})
}),
// Click 'Cancel' to discard document changes
export const cancelEdit = () =>
cancelEdit: () =>
({
type: 'CANCEL_EDIT'
})
export const clearCurrentDocument = () =>
}),
clearCurrentDocument: () =>
({
type: 'CLEAR_CURRENT_DOCUMENT'
})
}),
// Click 'Delete' and confirm to delete a document
export const deleteCurrentDocument = (id, docType) =>
deleteCurrentDocument: (id, docType) =>
({
type: 'DELETE_CURRENT_DOCUMENT',
id: id,
docType: docType
})
}),
// Toggle the button to hide or display note highlights
export const toggleHighlight = () => {
return ({
toggleHighlight: () =>
({
type: 'TOGGLE_HIGHLIGHT'
})
}
}),
// Select 'Read', 'Edit' or 'Annotate' modes in the Editor
export const setMode = mode =>
setMode: mode =>
({
type: 'SET_MODE',
mode: mode
})
}),
// Click 'Search' to request search results
export const clickSearch = searchInput => {
return ({
clickSearch: searchInput =>
({
type: 'CLICK_SEARCH',
data: searchInput
})
}
}),
// Set the DocType to choose from in the Editor
export const setDocType = docType =>
setDocType: docType =>
({
type: 'SET_DOC_TYPE',
docType: docType
})
}),
// Click 'Add Annotation' to enter 'Annotate' mode
export const addAnnotation = data =>
addAnnotation: data =>
({
type: 'ADD_ANNOTATION',
data: data
})
}),
// Click 'Submit' to save annotation
export const submitAnnotation = (annotationNote, selectionState, editorState) =>
submitAnnotation: (annotationNote, selectionState, editorState) =>
({
type: 'SUBMIT_ANNOTATION',
annotationNote: annotationNote,
selectionState: selectionState,
editorState: editorState
})
}),
// Click to remove selected Annotation
export const removeAnnotation = (editorState) =>
removeAnnotation: (editorState) =>
({
type: 'REMOVE_ANNOTATION',
editorState: editorState,
selectionState: editorState.getSelection()
})
}),
// Click a link to choose the note that will be displayed in the modal
export const selectAnnotationNote = id =>
selectAnnotationNote: id =>
({
type: 'SELECT_ANNOTATION_NOTE',
id: id
})
}),
}
export default userActions

View File

@ -4,19 +4,9 @@ import { Editor } from 'draft-js'
import { ReadModeTopBar, EditModeTopBar, AnnotateModeTopBar } from '../components/contentTopBar'
import { EditModeBottomBar } from '../components/contentBottomBar'
import actions from '../actions'
import DocumentTitle from '../components/documentTitle'
import LoadingSpinner from '../components/loadingSpinner'
import {
setMode,
cancelEdit,
submitDocumentEdit,
addAnnotation,
removeAnnotation } from '../actions/userActions'
import {
updateEditorState,
handleEditorKeyCommand,
applyInlineStyles } from '../actions/editorStateActions'
import { updateDocumentTitleChange } from '../actions/inputActions'
const JoyceEditorContent = ({currentDocument, editorState, mode, handleKeyCommand, onChangeEditorState, onToolButtonClick, setMode, cancelEdit, onSubmitClick, documentTitleInput, onDocumentTitleChange, onNewAnnotationClick, annotateKeyBindings, onRemoveAnnotationClick, docType, loadingToggle}) =>
<div>
@ -74,34 +64,34 @@ const mapStateToProps = (state, props) => {
const mapDispatchToProps = dispatch => {
return {
onChangeEditorState: editorState => {
dispatch(updateEditorState(editorState))
dispatch(actions.updateEditorState(editorState))
},
onDocumentTitleChange: documentTitleInput => {
dispatch(updateDocumentTitleChange(documentTitleInput))
dispatch(actions.updateDocumentTitleChange(documentTitleInput))
},
handleKeyCommand: (command, editorState) => {
dispatch(handleEditorKeyCommand(editorState, command))
dispatch(actions.handleEditorKeyCommand(editorState, command))
},
annotateKeyBindings: () => {
return 'handled'
},
setMode: (mode) => {
dispatch(setMode(mode))
dispatch(actions.setMode(mode))
},
cancelEdit: () => {
dispatch(cancelEdit())
dispatch(actions.cancelEdit())
},
onNewAnnotationClick: (selectionState) => {
dispatch(addAnnotation(selectionState))
dispatch(actions.addAnnotation(selectionState))
},
onRemoveAnnotationClick: (editorState) => {
dispatch(removeAnnotation(editorState))
dispatch(actions.removeAnnotation(editorState))
},
onToolButtonClick: (editorState, style) => {
dispatch(applyInlineStyles(editorState, style))
dispatch(actions.applyInlineStyles(editorState, style))
},
onSubmitClick: (currentDocument, editorState, documentTitleInput, docType) => {
dispatch(submitDocumentEdit(currentDocument, editorState, documentTitleInput, docType))
dispatch(actions.submitDocumentEdit(currentDocument, editorState, documentTitleInput, docType))
}
}
}

View File

@ -2,7 +2,7 @@ import React from 'react'
import { connect } from 'react-redux'
import { EditorState } from 'draft-js'
import { deleteCurrentDocument, submitAnnotation, selectAnnotationNote } from '../actions/userActions'
import actions from '../actions'
import Content from '../components/content'
import { EditorWelcome } from '../components/welcome'
import LoadingSpinner from '../components/loadingSpinner'
@ -42,13 +42,13 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
onDeleteClick: (id, docType) => {
dispatch(deleteCurrentDocument(id, docType))
dispatch(actions.deleteCurrentDocument(id, docType))
},
selectAnnotationNote: id => {
dispatch(selectAnnotationNote(id))
dispatch(actions.selectAnnotationNote(id))
},
onSubmitAnnotationClick: (annotationNote, selectionState, editorState) => {
dispatch(submitAnnotation(annotationNote, selectionState, editorState))
dispatch(actions.submitAnnotation(annotationNote, selectionState, editorState))
}
}
}

View File

@ -1,6 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { setCurrentDocument, createNewDocument, setDocType } from '../actions/userActions'
import actions from '../actions'
import { DocumentList } from '../components/list'
import { NewDocumentButton } from '../components/button'
import { DocTypeDropdown } from '../components/dropdown'
@ -30,13 +30,13 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
setDocType: docType => {
dispatch(setDocType(docType))
dispatch(actions.setDocType(docType))
},
onNewDocumentClick: docType => {
dispatch(createNewDocument(docType))
dispatch(actions.createNewDocument(docType))
},
onDocumentClick: (id, docType) => {
dispatch(setCurrentDocument(id, docType))
dispatch(actions.setCurrentDocument(id, docType))
},
}
}

View File

@ -1,8 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { Editor } from 'draft-js'
import { setCurrentChapter, setAnnotationNote, toggleLoading } from '../actions/userActions'
import DocumentTitle from '../components/documentTitle'
import LoadingSpinner from '../components/loadingSpinner'

View File

@ -1,6 +1,6 @@
import React from 'react'
import { connect } from 'react-redux'
import { setCurrentDocument, toggleHighlight } from '../actions/userActions'
import actions from '../actions'
import { DocumentList } from '../components/list'
import { HighlightButton } from '../components/button'
import SidebarSpacer from '../components/sidebarSpacer'
@ -28,10 +28,10 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
onDocumentClick: (id, docType) => {
dispatch(setCurrentDocument(id, docType))
dispatch(actions.setCurrentDocument(id, docType))
},
onHighlightClick: () => {
dispatch(toggleHighlight())
dispatch(actions.toggleHighlight())
}
}
}

View File

@ -2,10 +2,9 @@ import React from 'react'
import { connect } from 'react-redux'
import { Editor } from 'draft-js'
import actions from '../actions'
import { SearchButton } from '../components/button'
import SearchResultsBox from '../components/searchResultsBox'
import { clickSearch } from '../actions/userActions'
import { updateSearchInput } from '../actions/inputActions'
const JoyceSearchContent = ({searchResults, searchInput, onSearchInputChange, onSearchClick}) =>
<div className='container'>
@ -32,10 +31,10 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
onSearchInputChange: searchInput => {
dispatch(updateSearchInput(searchInput))
dispatch(actions.updateSearchInput(searchInput))
},
onSearchClick: searchInput => {
dispatch(clickSearch(searchInput))
dispatch(actions.clickSearch(searchInput))
}
}
}

View File

@ -1,5 +1,5 @@
import React from 'react'
import { selectAnnotationNote } from '../actions/userActions'
import actions from '../actions'
import { connect } from 'react-redux'
const Link = (props) => {

View File

@ -11,25 +11,24 @@ import 'bootstrap'
// src packages
import Navbar from './components/navbar'
import reduceReader from './reducers/reduceReader'
import { selectAnnotationNote } from './actions/userActions'
import { getDocumentList } from './actions/apiActions'
import DeleteConfirmModal from './components/deleteConfirmModal'
import AnnotateModal from './components/annotateModal'
import AnnotationModal from './components/annotationModal'
import { setDocType } from './actions/userActions'
import actions from './actions'
import { logger, joyceAPI, joyceInterface, joyceRouter } from './middleware/'
import JoyceReaderPageContainer from './containers/joyceReaderPageContainer'
import JoyceEditorPageContainer from './containers/joyceEditorPageContainer'
import JoyceSearchPageContainer from './containers/joyceSearchPageContainer'
// TODO: Pass routing from Flask?
const history = createHistory()
const router = routerMiddleware(history)
const store = createStore(reduceReader, applyMiddleware(logger, router, joyceAPI, joyceInterface, joyceRouter))
store.dispatch(getDocumentList({docType: 'chapters'}))
store.dispatch(getDocumentList({docType: 'notes'}))
console.log(actions)
store.dispatch(actions.getDocumentList({docType: 'chapters'}))
store.dispatch(actions.getDocumentList({docType: 'notes'}))
// TODO: Modal container should probably get state and dispatch as props, not access store
ReactDOM.render(
<Provider store={store}>
@ -56,7 +55,7 @@ ReactDOM.render(
<Route exact path='/:id' component={JoyceReaderPageContainer} />
</Switch>
<DeleteConfirmModal onDeleteClick={()=>onDeleteClick(currentDocument.id, docType)}/>
<AnnotateModal notes={store.getState().notes} annotationNote={store.getState().annotationNote} onSubmitClick={()=>onSubmitAnnotationClick(store.getState().annotationNote, store.getState().selectionState, store.getState().editorState)} selectAnnotationNote={selectAnnotationNote} />
<AnnotateModal notes={store.getState().notes} annotationNote={store.getState().annotationNote} onSubmitClick={()=>onSubmitAnnotationClick(store.getState().annotationNote, store.getState().selectionState, store.getState().editorState)} selectAnnotationNote={actions.selectAnnotationNote} />
<AnnotationModal annotationNote={store.getState().annotationNote} />
</div>
</ConnectedRouter>

View File

@ -1,14 +1,4 @@
import { push } from 'react-router-redux'
import {
getDocumentList,
getDocumentText,
deleteDocument,
saveDocument,
createNewChapter,
getSearchResults
} from '../actions/apiActions'
import actions from '../actions'
import api from '../modules/api'
import regex from '../modules/regex'
@ -19,14 +9,14 @@ const joyceAPI = store => next => action => {
case 'GET_DOCUMENT_LIST':
if (action.status === 'request') {
api.HTTPGetDocumentList(action.docType, action.state).then(response =>
store.dispatch(getDocumentList(response))
store.dispatch(actions.getDocumentList(response))
)
}
break
case 'GET_DOCUMENT_TEXT':
if (action.status === 'request') {
api.HTTPGetDocumentText(action.id, action.docType, action.state).then(response =>
store.dispatch(getDocumentText(response))
store.dispatch(actions.getDocumentText(response))
)
}
break
@ -34,11 +24,11 @@ const joyceAPI = store => next => action => {
if (action.status === 'request') {
if (action.id) {
api.HTTPPostWriteDocument(action.id, action.docType, action.data).then(response =>
store.dispatch(saveDocument(response)
store.dispatch(actions.saveDocument(response)
)
)} else {
api.HTTPPutCreateDocument(action.docType, action.data).then(response =>
store.dispatch(saveDocument(response))
store.dispatch(actions.saveDocument(response))
)
}
}
@ -46,14 +36,14 @@ const joyceAPI = store => next => action => {
case 'DELETE_DOCUMENT':
if (action.status === 'request') {
api.HTTPDeleteDocument(action.id, action.docType).then(response =>
store.dispatch(deleteDocument(response))
store.dispatch(actions.deleteDocument(response))
)
}
break
case 'GET_SEARCH_RESULTS':
if (action.status === 'request') {
api.HTTPPostSearchResults(action.data).then(response =>
store.dispatch(getSearchResults(response))
store.dispatch(actions.getSearchResults(response))
)
}
break

View File

@ -3,17 +3,7 @@ import { stateToHTML } from 'draft-js-export-html'
import { stateToMarkdown } from 'draft-js-export-markdown'
import { convertToRaw } from 'draft-js'
import {
getDocumentList,
getDocumentText,
deleteDocument,
saveDocument,
createNewChapter,
getSearchResults
} from '../actions/apiActions'
import { clearCurrentDocument } from '../actions/userActions'
import actions from '../actions'
import helpers from '../modules/helpers'
const html_export_options = {
@ -37,7 +27,7 @@ const joyceInterface = store => next => action => {
next(action)
switch(action.type) {
case 'SET_CURRENT_DOCUMENT':
store.dispatch(getDocumentText({id: action.id, docType: action.docType, state: 'currentDocument'}))
store.dispatch(actions.getDocumentText({id: action.id, docType: action.docType, state: 'currentDocument'}))
break
case 'SUBMIT_DOCUMENT_EDIT':
const textContent = action.editorState.getCurrentContent()
@ -53,32 +43,32 @@ const joyceInterface = store => next => action => {
data.number = action.currentDocument.number
}
}
store.dispatch(saveDocument({id: data.id ? data.id : null, docType: action.docType, data: data}))
store.dispatch(actions.saveDocument({id: data.id ? data.id : null, docType: action.docType, data: data}))
break
case 'DELETE_CURRENT_DOCUMENT':
store.dispatch(deleteDocument({id: action.id, docType: action.docType}))
store.dispatch(actions.deleteDocument({id: action.id, docType: action.docType}))
break
case 'CANCEL_EDIT':
const docType = store.getState().docType
const currentDocument = store.getState().currentDocument
if (currentDocument.id) {
store.dispatch(getDocumentText({id: currentDocument.id, docType: docType, state: 'currentDocument'}))
store.dispatch(actions.getDocumentText({id: currentDocument.id, docType: docType, state: 'currentDocument'}))
} else {
store.dispatch(getDocumentText({id: notes[0].id, docType: docType, state: 'currentDocument'}))
store.dispatch(actions.getDocumentText({id: notes[0].id, docType: docType, state: 'currentDocument'}))
}
break
case 'SET_DOC_TYPE':
if (action.docType !== store.getState().docType) {
store.dispatch(clearCurrentDocument())
store.dispatch(actions.clearCurrentDocument())
}
break
// Annotation Action Middleware
case 'SELECT_ANNOTATION_NOTE':
store.dispatch(getDocumentText({id: action.id, docType: 'notes', state: 'annotationNote'}))
store.dispatch(actions.getDocumentText({id: action.id, docType: 'notes', state: 'annotationNote'}))
break
// Search Action Middleware
case 'CLICK_SEARCH':
store.dispatch(getSearchResults({data: action.data}))
store.dispatch(actions.getSearchResults({data: action.data}))
break
default:
break

View File

@ -1,6 +1,6 @@
import { push } from 'react-router-redux'
import { setCurrentDocument, setDocType } from '../actions/userActions'
import actions from '../actions'
import helpers from '../modules/helpers'
import regex from '../modules/regex'
@ -16,19 +16,19 @@ const joyceRouter = store => next => action => {
switch(action.type) {
case '@@router/LOCATION_CHANGE':
if (regex.checkIfRedirectPath(path) && currentDocument.hasOwnProperty('id')) {
store.dispatch(push(docType === 'chapters' ? String(currentDocument.number) : currentDocument.id))
store.dispatch(actions.push(docType === 'chapters' ? String(currentDocument.number) : currentDocument.id))
}
if (regex.checkNoteReaderRoute(path) && regex.checkIfRedirectPath(path) && notes.length > 0) {
store.dispatch(setCurrentDocument(notes[0].id, 'notes'))
store.dispatch(actions.setCurrentDocument(notes[0].id, 'notes'))
}
if (regex.checkNoteReaderRoute(path) || regex.checkNoteEditorRoute(path)) {
store.dispatch(setDocType('notes'))
store.dispatch(actions.setDocType('notes'))
}
if (regex.checkRootRedirectRoute(path) && chapters.length > 0) {
store.dispatch(setCurrentDocument(chapters[0].id, 'chapters'))
store.dispatch(actions.setCurrentDocument(chapters[0].id, 'chapters'))
}
if (regex.checkNoteBaseRoute(path)) {
store.dispatch(setDocType('notes'))
store.dispatch(actions.setDocType('notes'))
}
if (regex.checkEditBaseRoute(path)){
if (docType === 'notes') {
@ -38,16 +38,16 @@ const joyceRouter = store => next => action => {
case 'GET_DOCUMENT_LIST':
if (action.status === 'success' && action.docType === docType && !currentDocument.id) {
if (regex.checkIfRedirectPath(path)) {
store.dispatch(setCurrentDocument(action.data[0].id, action.docType))
store.dispatch(actions.setCurrentDocument(action.data[0].id, action.docType))
}
if (action.docType === 'chapters' && pathNumber !== undefined) {
for (const chapter of action.data) {
if (chapter.number === pathNumber) {
store.dispatch(setCurrentDocument(chapter.id, action.docType))
store.dispatch(actions.setCurrentDocument(chapter.id, action.docType))
}
}
} else if (pathID !== undefined) {
store.dispatch(setCurrentDocument(pathID, action.docType))
store.dispatch(actions.setCurrentDocument(pathID, action.docType))
}
}
break
@ -58,17 +58,17 @@ const joyceRouter = store => next => action => {
break
case 'SAVE_DOCUMENT':
if (action.status === 'success' && !action.id) {
store.dispatch(setCurrentDocument(action.data.slice(-1)[0].id, action.docType))
store.dispatch(actions.setCurrentDocument(action.data.slice(-1)[0].id, action.docType))
}
break
case 'DELETE_DOCUMENT':
if (action.status === 'request') {
api.HTTPDeleteDocument(action.id, action.docType).then(response =>
store.dispatch(deleteDocument(response))
store.dispatch(actions.deleteDocument(response))
)
} else if (action.status === 'success') {
if (action.data[0]) {
store.dispatch(setCurrentDocument(action.data[0].id, action.docType, 'currentDocument'))
store.dispatch(actions.setCurrentDocument(action.data[0].id, action.docType, 'currentDocument'))
}
}
break

View File

@ -7,7 +7,6 @@ const loadingToggle = (state=true, action) => {
return false
}
case 'GET_DOCUMENT_LIST':
// TODO: How should this handle multiple docTypes?
if (action.status === 'success' && !action.data[0] && action.state === 'currentDocType') {
return false
}

View File

@ -1,20 +0,0 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import { Provider } from 'react-redux'
import 'bootstrap'
import reduceSearch from './reducers/reduceSearch'
import { logger, joyceAPI } from './middleware/'
import JoyceSearchPageContainer from './containers/joyceSearchPageContainer'
// TODO: Pass routing from Flask?
let store = createStore(reduceSearch, applyMiddleware(logger, joyceAPI))
ReactDOM.render(
<Provider store={store}>
<JoyceSearchPageContainer />
</Provider>,
document.getElementById('wrapper')
)