Refactoring input & toggle state

This commit is contained in:
Alex Hunt 2018-11-29 23:37:36 -08:00
parent 0860d6f0d1
commit c9f197675f
25 changed files with 254 additions and 117 deletions

View File

@ -5,21 +5,21 @@
const inputActions = { const inputActions = {
// Handle changes to the document title input box // Handle changes to the document title input box
updateDocumentTitleInput: documentTitleInput => updateDocumentTitleInput: input =>
({ ({
type: 'UPDATE_DOCUMENT_TITLE', type: 'UPDATE_DOCUMENT_TITLE',
data: documentTitleInput.target.value data: input.target.value
}), }),
updateColorPickerInput: colorPickerInput => updateColorPickerInput: input =>
({ ({
type: 'UPDATE_COLOR_PICKER', type: 'UPDATE_COLOR_PICKER',
data: colorPickerInput.target.value data: input.target.value
}), }),
// Handle changes to the search input box // Handle changes to the search input box
updateSearchInput: searchInput => updateSearchInput: input =>
({ ({
type: 'UPDATE_SEARCH_INPUT', type: 'UPDATE_SEARCH_INPUT',
data: searchInput.target.value data: input.target.value
}) })
} }

View File

@ -18,13 +18,12 @@ const userActions = {
docType: docType docType: docType
}), }),
// Click 'Submit' to save a document edit // Click 'Submit' to save a document edit
submitDocumentEdit: (currentDocument, editorState, documentTitleInput, colorPickerInput, docType) => submitDocumentEdit: (currentDocument, editorState, inputs, docType) =>
({ ({
type: 'SUBMIT_DOCUMENT_EDIT', type: 'SUBMIT_DOCUMENT_EDIT',
currentDocument: currentDocument, currentDocument: currentDocument,
editorState: editorState, editorState: editorState,
documentTitleInput: documentTitleInput, inputs: inputs,
colorPickerInput: colorPickerInput,
docType: docType docType: docType
}), }),
// Click 'Cancel' to discard document changes // Click 'Cancel' to discard document changes
@ -62,10 +61,10 @@ const userActions = {
mode: mode mode: mode
}), }),
// Click 'Search' to request search results // Click 'Search' to request search results
clickSearch: searchInput => clickSearch: inputs =>
({ ({
type: 'CLICK_SEARCH', type: 'CLICK_SEARCH',
data: searchInput data: inputs.search
}), }),
// Set the DocType to choose from in the Editor // Set the DocType to choose from in the Editor
setDocType: docType => setDocType: docType =>
@ -116,6 +115,10 @@ const userActions = {
({ ({
type: 'CLEAR_ANNOTATION_TAG' type: 'CLEAR_ANNOTATION_TAG'
}), }),
hideAdmin: () =>
({
type: 'HIDE_ADMIN_HEADER'
})
} }
export default userActions export default userActions

View File

@ -0,0 +1,28 @@
import React from 'react'
import PropTypes from 'prop-types'
import api from '../modules/api'
import { ReaderAnnotateButton, ReaderEditButton, EditorToolButton, EditorDeleteToolButton, AnnotatorNewButton, AnnotatorRemoveButton } from './button'
const refreshElasticsearch = () => {
api.HTTPGetRefreshList().then(response =>
location.reload()
)
}
const AdminHeader = ({toggles, hideAdmin}) =>
<div id='admin_header' className={toggles.admin ? 'admin_show' : 'admin_hide'}>
<button type='button' className='btn btn-sm btn-outline-primary' onClick={refreshElasticsearch}>
Refresh Seed Data
</button>
<button className='btn btn-sm btn-outline-primary' onClick={hideAdmin}>
<i className='fa fa-times'></i>
</button>
</div>
export default AdminHeader
AdminHeader.propTypes = {
refreshElasticsearch: PropTypes.func,
}

View File

@ -44,19 +44,19 @@ export const TagButton = ({tag, currentTag, onClick}) =>
</button> </button>
</div> </div>
export const HighlightButton = ({highlightToggle, onClick, size='lg'}) => export const HighlightButton = ({toggle, onClick, size='lg'}) =>
<div> <div>
<div id='highlight_button' className='text-center'> <div id='highlight_button' className='text-center'>
<button onClick={onClick} className={highlightToggle ? 'btn btn-primary btn-' + size : 'btn btn-outline-primary btn-' + size}> <button onClick={onClick} className={toggle ? 'btn btn-primary btn-' + size : 'btn btn-outline-primary btn-' + size}>
{highlightToggle ? 'Hide Notes' : 'Highlight Notes'} {toggle ? 'Hide Notes' : 'Highlight Notes'}
</button> </button>
</div> </div>
</div> </div>
export const SearchButton = ({searchInput, onClick}) => export const SearchButton = ({input, onClick}) =>
<div> <div>
<div id='search_button' className='text-center'> <div id='search_button' className='text-center'>
<button className='btn btn-primary btn-sm' onClick={()=>onClick(searchInput)}> <button className='btn btn-primary btn-sm' onClick={()=>onClick(input)}>
Search <i className='fa fa_inline fa-search'></i> Search <i className='fa fa_inline fa-search'></i>
</button> </button>
</div> </div>
@ -146,7 +146,7 @@ NoteButton.propTypes = {
} }
HighlightButton.propTypes = { HighlightButton.propTypes = {
highlightToggle: PropTypes.bool, toggle: PropTypes.bool,
onClick: PropTypes.func, onClick: PropTypes.func,
} }

View File

@ -5,10 +5,10 @@ import { EditorCancelButton, EditorSubmitButton } from '../components/button'
export const EditModeBottomBar = ({cancelEdit, onSubmitClick}) => export const EditModeBottomBar = ({cancelEdit, onSubmitClick}) =>
<div className='row'> <div className='row'>
<div className='col-md-5'> <div className='col-5'>
<EditorCancelButton onClick={()=>cancelEdit()}/> <EditorCancelButton onClick={()=>cancelEdit()}/>
</div> </div>
<div className='col-md-5 offset-md-2'> <div className='col-5 offset-2'>
<EditorSubmitButton onClick={onSubmitClick} /> <EditorSubmitButton onClick={onSubmitClick} />
</div> </div>
</div> </div>

View File

@ -12,7 +12,7 @@ const EditorAnnotateMode = ({
currentDocument, currentDocument,
editorState, editorState,
docType, docType,
loadingToggle, toggles,
onChangeEditorState, onChangeEditorState,
onNewAnnotationClick, onNewAnnotationClick,
annotateKeyBindings, annotateKeyBindings,
@ -22,7 +22,7 @@ const EditorAnnotateMode = ({
}) => }) =>
<div> <div>
<div id='editor_metadata'> <div id='editor_metadata'>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner /> <LoadingSpinner />
} }
<DocumentTitle docType={docType} currentDocument={currentDocument} /> <DocumentTitle docType={docType} currentDocument={currentDocument} />

View File

@ -13,15 +13,14 @@ const EditorEditMode = ({
currentDocument, currentDocument,
editorState, editorState,
docType, docType,
loadingToggle, toggles,
handleKeyCommand, handleKeyCommand,
onChangeEditorState, onChangeEditorState,
onToolButtonClick, onToolButtonClick,
setMode, setMode,
cancelEdit, cancelEdit,
onSubmitClick, onSubmitClick,
colorPickerInput, inputs,
documentTitleInput,
onDocumentTitleChange, onDocumentTitleChange,
onColorPickerInputChange, onColorPickerInputChange,
onColorSwatchClick, onColorSwatchClick,
@ -29,10 +28,10 @@ const EditorEditMode = ({
}) => }) =>
<div> <div>
<div id='editor_metadata'> <div id='editor_metadata'>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner /> <LoadingSpinner />
} }
<input type='text' value={documentTitleInput} onChange={onDocumentTitleChange}/> <input type='text' value={inputs.documentTitle} onChange={onDocumentTitleChange}/>
</div> </div>
<div id='editor_topbar'> <div id='editor_topbar'>
<EditModeTopBar <EditModeTopBar
@ -50,7 +49,7 @@ const EditorEditMode = ({
</div> </div>
<div id='editor_attributes'> <div id='editor_attributes'>
{docType === 'tags' && {docType === 'tags' &&
<TagColorPicker colorPickerInput={colorPickerInput} onChange={onColorPickerInputChange} onColorSwatchClick={onColorSwatchClick}/> <TagColorPicker input={inputs.colorPicker} onChange={onColorPickerInputChange} onColorSwatchClick={onColorSwatchClick}/>
} }
</div> </div>
<div id='editor_bottombar'> <div id='editor_bottombar'>

View File

@ -11,12 +11,12 @@ const EditorReadMode = ({
currentDocument, currentDocument,
editorState, editorState,
docType, docType,
loadingToggle, toggles,
setMode setMode
}) => }) =>
<div id='editor_read_mode'> <div id='editor_read_mode'>
<div id='editor_metadata'> <div id='editor_metadata'>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner /> <LoadingSpinner />
} }
<DocumentTitle docType={docType} currentDocument={currentDocument} /> <DocumentTitle docType={docType} currentDocument={currentDocument} />

View File

@ -7,7 +7,7 @@ import { ReaderDocDropdown } from './dropdown'
export const ReaderSidebarOptions = ({docs, currentDocument, highlightToggle, docType, onHighlightClick, onDocumentClick}) => export const ReaderSidebarOptions = ({docs, currentDocument, highlightToggle, docType, onHighlightClick, onDocumentClick}) =>
<div id='mobile_reader_sidebar' className='row'> <div id='mobile_reader_sidebar' className='row'>
<div className='col-6 d-block d-md-none'> <div className='col-6 d-block d-md-none'>
<HighlightButton highlightToggle={highlightToggle} onClick={onHighlightClick} size='md'/> <HighlightButton toggle={highlightToggle} onClick={onHighlightClick} size='md'/>
</div> </div>
<div className='col-6 d-block d-md-none'> <div className='col-6 d-block d-md-none'>
<ReaderDocDropdown currentDocument={currentDocument} docs={docs} docType={docType} onDocumentClick={onDocumentClick}/> <ReaderDocDropdown currentDocument={currentDocument} docs={docs} docType={docType} onDocumentClick={onDocumentClick}/>

View File

@ -2,12 +2,12 @@ import React from 'react'
import defaultTagColors from '../modules/editorSettings' import defaultTagColors from '../modules/editorSettings'
const TagColorPicker = ({colorPickerInput, onChange, onColorSwatchClick}) => const TagColorPicker = ({input, onChange, onColorSwatchClick}) =>
<div className='input-group'> <div className='input-group'>
<div className='input-group-prepend'> <div className='input-group-prepend'>
<span className='input-group-text' id='basic-addon1'>#</span> <span className='input-group-text' id='basic-addon1'>#</span>
</div> </div>
<input type='text' className='form-control' placeholder='Color' value={colorPickerInput} onChange={onChange}/> <input type='text' className='form-control' placeholder='Color' value={input} onChange={onChange}/>
<div className='input-group-append'> <div className='input-group-append'>
<button className='btn btn-primary dropdown-toggle caret-off' data-toggle='dropdown' type='button'><i className='fa fa-chevron-down'></i></button> <button className='btn btn-primary dropdown-toggle caret-off' data-toggle='dropdown' type='button'><i className='fa fa-chevron-down'></i></button>
<div className='dropdown-menu'> <div className='dropdown-menu'>

View File

@ -8,11 +8,15 @@ import EditorAnnotateMode from '../components/editorAnnotateMode'
import EditorEditMode from '../components/editorEditMode' import EditorEditMode from '../components/editorEditMode'
const EditorContent = ({ const EditorContent = ({
// State
currentDocument, currentDocument,
editorState, editorState,
docType, docType,
mode, mode,
loadingToggle, toggles,
inputs,
userErrors,
//Dispatch
handleKeyCommand, handleKeyCommand,
onChangeEditorState, onChangeEditorState,
onToolButtonClick, onToolButtonClick,
@ -20,14 +24,11 @@ const EditorContent = ({
cancelEdit, cancelEdit,
onSubmitClick, onSubmitClick,
onColorSwatchClick, onColorSwatchClick,
documentTitleInput,
colorPickerInput,
onDocumentTitleChange, onDocumentTitleChange,
onColorPickerInputChange, onColorPickerInputChange,
onNewAnnotationClick, onNewAnnotationClick,
annotateKeyBindings, annotateKeyBindings,
onRemoveAnnotationClick, onRemoveAnnotationClick,
userErrors,
}) => }) =>
<div id='editor_container'> <div id='editor_container'>
{mode === 'READ_MODE' && {mode === 'READ_MODE' &&
@ -35,7 +36,7 @@ const EditorContent = ({
currentDocument={currentDocument} currentDocument={currentDocument}
editorState={editorState} editorState={editorState}
docType={docType} docType={docType}
loadingToggle={loadingToggle} toggles={toggles}
setMode={setMode} setMode={setMode}
/> />
} }
@ -44,7 +45,7 @@ const EditorContent = ({
currentDocument={currentDocument} currentDocument={currentDocument}
editorState={editorState} editorState={editorState}
docType={docType} docType={docType}
loadingToggle={loadingToggle} toggles={toggles}
handleKeyCommand={handleKeyCommand} handleKeyCommand={handleKeyCommand}
onNewAnnotationClick={()=>onNewAnnotationClick(editorState.getSelection())} onNewAnnotationClick={()=>onNewAnnotationClick(editorState.getSelection())}
onRemoveAnnotationClick={()=>onRemoveAnnotationClick(editorState)} onRemoveAnnotationClick={()=>onRemoveAnnotationClick(editorState)}
@ -53,7 +54,7 @@ const EditorContent = ({
onToolButtonClick={onToolButtonClick} onToolButtonClick={onToolButtonClick}
setMode={setMode} setMode={setMode}
cancelEdit={cancelEdit} cancelEdit={cancelEdit}
onSubmitClick={()=>onSubmitClick(currentDocument, editorState, documentTitleInput, colorPickerInput, docType)} onSubmitClick={()=>onSubmitClick(currentDocument, editorState, inputs, docType)}
/> />
} }
{mode === 'EDIT_MODE' && {mode === 'EDIT_MODE' &&
@ -61,12 +62,11 @@ const EditorContent = ({
currentDocument={currentDocument} currentDocument={currentDocument}
editorState={editorState} editorState={editorState}
docType={docType} docType={docType}
loadingToggle={loadingToggle} toggles={toggles}
onChangeEditorState={onChangeEditorState} onChangeEditorState={onChangeEditorState}
cancelEdit={cancelEdit} cancelEdit={cancelEdit}
onSubmitClick={()=>onSubmitClick(currentDocument, editorState, documentTitleInput, colorPickerInput, docType)} onSubmitClick={()=>onSubmitClick(currentDocument, editorState, inputs, docType)}
documentTitleInput={documentTitleInput} inputs={inputs}
colorPickerInput={colorPickerInput}
onColorSwatchClick={onColorSwatchClick} onColorSwatchClick={onColorSwatchClick}
onDocumentTitleChange={onDocumentTitleChange} onDocumentTitleChange={onDocumentTitleChange}
onColorPickerInputChange={onColorPickerInputChange} onColorPickerInputChange={onColorPickerInputChange}
@ -81,9 +81,8 @@ const mapStateToProps = (state, props) => {
mode: state.mode, mode: state.mode,
docType: state.docType, docType: state.docType,
editorState: state.editorState, editorState: state.editorState,
documentTitleInput: state.documentTitleInput, inputs: state.inputs,
colorPickerInput: state.colorPickerInput, toggles: state.toggles,
loadingToggle: state.loadingToggle,
userErrors: state.userErrors, userErrors: state.userErrors,
} }
} }
@ -93,11 +92,11 @@ const mapDispatchToProps = dispatch => {
onChangeEditorState: editorState => { onChangeEditorState: editorState => {
dispatch(actions.updateEditorState(editorState)) dispatch(actions.updateEditorState(editorState))
}, },
onDocumentTitleChange: documentTitleInput => { onDocumentTitleChange: input => {
dispatch(actions.updateDocumentTitleInput(documentTitleInput)) dispatch(actions.updateDocumentTitleInput(input))
}, },
onColorPickerInputChange: colorPickerInput => { onColorPickerInputChange: input => {
dispatch(actions.updateColorPickerInput(colorPickerInput)) dispatch(actions.updateColorPickerInput(input))
}, },
handleKeyCommand: (command, editorState) => { handleKeyCommand: (command, editorState) => {
dispatch(actions.handleEditorKeyCommand(editorState, command)) dispatch(actions.handleEditorKeyCommand(editorState, command))
@ -124,8 +123,8 @@ const mapDispatchToProps = dispatch => {
onToolButtonClick: (editorState, style) => { onToolButtonClick: (editorState, style) => {
dispatch(actions.applyInlineStyles(editorState, style)) dispatch(actions.applyInlineStyles(editorState, style))
}, },
onSubmitClick: (currentDocument, editorState, documentTitleInput, colorPickerInput, docType) => { onSubmitClick: (currentDocument, editorState, inputs, docType) => {
dispatch(actions.submitDocumentEdit(currentDocument, editorState, documentTitleInput, colorPickerInput, docType)) dispatch(actions.submitDocumentEdit(currentDocument, editorState, inputs, docType))
} }
} }
} }
@ -133,10 +132,10 @@ const mapDispatchToProps = dispatch => {
EditorContent.propTypes = { EditorContent.propTypes = {
currentDocument: PropTypes.object, currentDocument: PropTypes.object,
editorState: PropTypes.object, editorState: PropTypes.object,
documentTitleInput: PropTypes.string, inputs: PropTypes.object,
docType: PropTypes.string, docType: PropTypes.string,
mode: PropTypes.string, mode: PropTypes.string,
loadingToggle: PropTypes.bool, toggles: PropTypes.object,
handleKeyCommand: PropTypes.func, handleKeyCommand: PropTypes.func,
onChangeEditorState: PropTypes.func, onChangeEditorState: PropTypes.func,
onToolButtonClick: PropTypes.func, onToolButtonClick: PropTypes.func,

View File

@ -21,7 +21,7 @@ const EditorPage = ({
modalEditorState, modalEditorState,
docType, docType,
tags, tags,
loadingToggle, toggles,
onDeleteConfirm, onDeleteConfirm,
onSubmitAnnotationClick, onSubmitAnnotationClick,
selectAnnotationNote, selectAnnotationNote,
@ -34,13 +34,13 @@ const EditorPage = ({
<div className="row"> <div className="row">
<EditorSidebarContainer /> <EditorSidebarContainer />
<Content> <Content>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner size={4} /> <LoadingSpinner size={4} />
} }
{(Object.keys(currentDocument).length > 0 && loadingToggle === false) && {(Object.keys(currentDocument).length > 0 && toggles.loading === false) &&
<EditorContentContainer /> <EditorContentContainer />
} }
{(Object.keys(currentDocument).length === 0 && loadingToggle === false) && {(Object.keys(currentDocument).length === 0 && toggles.loading === false) &&
<EditorWelcome /> <EditorWelcome />
} }
</Content> </Content>
@ -72,7 +72,7 @@ const mapStateToProps = state => {
modalEditorState: state.modalEditorState, modalEditorState: state.modalEditorState,
selectionState: state.selectionState, selectionState: state.selectionState,
docType: state.docType, docType: state.docType,
loadingToggle: state.loadingToggle, toggles: state.toggles,
userErrors: state.userErrors, userErrors: state.userErrors,
} }
} }
@ -107,7 +107,7 @@ EditorPage.propTypes = {
modalEditorState: PropTypes.object, modalEditorState: PropTypes.object,
selectionState: PropTypes.object, selectionState: PropTypes.object,
docType: PropTypes.string, docType: PropTypes.string,
loadingToggle: PropTypes.bool, toggles: PropTypes.object,
onDeleteConfirm: PropTypes.func, onDeleteConfirm: PropTypes.func,
onSubmitAnnotationClick: PropTypes.func, onSubmitAnnotationClick: PropTypes.func,
selectAnnotationNote: PropTypes.func, selectAnnotationNote: PropTypes.func,

View File

@ -9,11 +9,10 @@ import LoadingSpinner from '../components/loadingSpinner'
const ReaderContent = ({ const ReaderContent = ({
currentDocument, currentDocument,
editorState, editorState,
loadingToggle, toggles,
highlightToggle,
}) => }) =>
<div id="page" className={highlightToggle ? 'annotations' : 'hidden_annotations'}> <div id="page" className={toggles.highlights ? 'annotations' : 'hidden_annotations'}>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner /> <LoadingSpinner />
} }
<br /> <br />
@ -28,16 +27,14 @@ const mapStateToProps = state => {
return { return {
currentDocument: state.currentDocument, currentDocument: state.currentDocument,
editorState: state.editorState, editorState: state.editorState,
highlightToggle: state.highlightToggle, toggles: state.toggles,
loadingToggle: state.loadingToggle
} }
} }
ReaderContent.propTypes = { ReaderContent.propTypes = {
currentDocument: PropTypes.object, currentDocument: PropTypes.object,
editorState: PropTypes.object, editorState: PropTypes.object,
loadingToggle: PropTypes.bool, toggles: PropTypes.object,
highlightToggle: PropTypes.bool,
} }
const ReaderContentContainer = connect(mapStateToProps)(ReaderContent) const ReaderContentContainer = connect(mapStateToProps)(ReaderContent)

View File

@ -21,8 +21,7 @@ const ReaderPage = ({
docType, docType,
annotationNote, annotationNote,
modalEditorState, modalEditorState,
loadingToggle, toggles,
highlightToggle,
onDocumentClick, onDocumentClick,
onHighlightClick, onHighlightClick,
}) => }) =>
@ -30,7 +29,7 @@ const ReaderPage = ({
<ReaderSidebarOptions <ReaderSidebarOptions
docs={helpers.documentsOfDocType(docType, chapters, notes, tags)} docs={helpers.documentsOfDocType(docType, chapters, notes, tags)}
currentDocument={currentDocument} currentDocument={currentDocument}
highlightToggle={highlightToggle} highlightToggle={toggles.highlights}
docType={docType} docType={docType}
onHighlightClick={onHighlightClick} onHighlightClick={onHighlightClick}
onDocumentClick={onDocumentClick} onDocumentClick={onDocumentClick}
@ -38,13 +37,13 @@ const ReaderPage = ({
<div id='content_container' className='row'> <div id='content_container' className='row'>
<ReaderSidebarContainer /> <ReaderSidebarContainer />
<Content> <Content>
{loadingToggle === true && {toggles.loading === true &&
<LoadingSpinner size={4} /> <LoadingSpinner size={4} />
} }
{(Object.keys(currentDocument).length > 0 && loadingToggle === false) && {(Object.keys(currentDocument).length > 0 && toggles.loading === false) &&
<ReaderContentContainer /> <ReaderContentContainer />
} }
{(Object.keys(currentDocument).length === 0 && loadingToggle === false) && {(Object.keys(currentDocument).length === 0 && toggles.loading === false) &&
<ReaderWelcome /> <ReaderWelcome />
} }
</Content> </Content>
@ -61,8 +60,7 @@ const mapStateToProps = state => {
docType: state.docType, docType: state.docType,
annotationNote: state.annotationNote, annotationNote: state.annotationNote,
modalEditorState: state.modalEditorState, modalEditorState: state.modalEditorState,
loadingToggle: state.loadingToggle, toggles: state.toggles,
highlightToggle: state.highlightToggle,
} }
} }
@ -73,15 +71,19 @@ const mapDispatchToProps = dispatch => {
}, },
onHighlightClick: () => { onHighlightClick: () => {
dispatch(actions.toggleHighlight()) dispatch(actions.toggleHighlight())
} }
} }
} }
ReaderPage.propTypes = { ReaderPage.propTypes = {
chapters: PropTypes.arrayOf(PropTypes.object),
notes: PropTypes.arrayOf(PropTypes.object),
tags: PropTypes.arrayOf(PropTypes.object),
currentDocument: PropTypes.object, currentDocument: PropTypes.object,
modalEditorState: PropTypes.object, docType: PropTypes.string,
annotationNote: PropTypes.object, annotationNote: PropTypes.object,
loadingToggle: PropTypes.bool, modalEditorState: PropTypes.object,
toggles: PropTypes.object,
} }
const ReaderPageContainer = connect(mapStateToProps, mapDispatchToProps)(ReaderPage) const ReaderPageContainer = connect(mapStateToProps, mapDispatchToProps)(ReaderPage)

View File

@ -13,13 +13,13 @@ const ReaderSidebar = ({
notes, notes,
currentDocument, currentDocument,
docType, docType,
highlightToggle, toggles,
onDocumentClick, onDocumentClick,
onHighlightClick, onHighlightClick,
}) => }) =>
<div className='col-md-3 d-none d-md-block' id='sidebar'> <div className='col-md-3 d-none d-md-block' id='sidebar'>
<div> <div>
<HighlightButton highlightToggle={highlightToggle} onClick={onHighlightClick}/> <HighlightButton toggle={toggles.highlights} onClick={onHighlightClick}/>
<SidebarSpacer /> <SidebarSpacer />
<DocumentList docs={helpers.documentsOfDocType(docType, chapters, notes)} currentDocument={currentDocument} onDocumentClick={onDocumentClick} docType={docType}/> <DocumentList docs={helpers.documentsOfDocType(docType, chapters, notes)} currentDocument={currentDocument} onDocumentClick={onDocumentClick} docType={docType}/>
</div> </div>
@ -31,7 +31,7 @@ const mapStateToProps = state => {
notes: state.notes, notes: state.notes,
docType: state.docType, docType: state.docType,
currentDocument: state.currentDocument, currentDocument: state.currentDocument,
highlightToggle: state.highlightToggle toggles: state.toggles,
} }
} }
@ -51,7 +51,7 @@ ReaderSidebar.propTypes = {
notes: PropTypes.arrayOf(PropTypes.object), notes: PropTypes.arrayOf(PropTypes.object),
currentDocument: PropTypes.object, currentDocument: PropTypes.object,
docType: PropTypes.string, docType: PropTypes.string,
highlightToggle: PropTypes.bool, toggles: PropTypes.object,
onDocumentClick: PropTypes.func, onDocumentClick: PropTypes.func,
onHighlightClick: PropTypes.func, onHighlightClick: PropTypes.func,
} }

View File

@ -9,17 +9,17 @@ import SearchResultsBox from '../components/searchResultsBox'
const SearchContent = ({ const SearchContent = ({
searchResults, searchResults,
searchInput, inputs,
onSearchInputChange, onSearchInputChange,
onSearchClick, onSearchClick,
}) => }) =>
<div className='container'> <div className='container'>
<div className='row'> <div className='row'>
<div className='col-sm-2'> <div className='col-sm-2'>
<SearchButton onClick={onSearchClick} searchInput={searchInput}/> <SearchButton onClick={onSearchClick} input={inputs.search}/>
</div> </div>
<div className='col-sm-10'> <div className='col-sm-10'>
<input id='search_input' type='text' value={searchInput} onChange={onSearchInputChange} /> <input id='search_input' type='text' value={inputs.search} onChange={onSearchInputChange} />
</div> </div>
</div> </div>
<div className='row'> <div className='row'>
@ -30,14 +30,14 @@ const SearchContent = ({
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
searchResults: state.searchResults, searchResults: state.searchResults,
searchInput: state.searchInput inputs: state.inputs
} }
} }
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
onSearchInputChange: searchInput => { onSearchInputChange: input => {
dispatch(actions.updateSearchInput(searchInput)) dispatch(actions.updateSearchInput(inputs))
}, },
onSearchClick: searchInput => { onSearchClick: searchInput => {
dispatch(actions.clickSearch(searchInput)) dispatch(actions.clickSearch(searchInput))
@ -47,7 +47,7 @@ const mapDispatchToProps = dispatch => {
SearchContent.propTypes = { SearchContent.propTypes = {
searchResults: PropTypes.object, searchResults: PropTypes.object,
searchInput: PropTypes.string, inputs: PropTypes.object,
onSearchInputChange: PropTypes.func, onSearchInputChange: PropTypes.func,
onSearchClick: PropTypes.func, onSearchClick: PropTypes.func,
} }

View File

@ -12,11 +12,11 @@ import 'bootstrap'
import Navbar from './components/navbar' import Navbar from './components/navbar'
import reduceJoyce from './reducers/reduceJoyce' import reduceJoyce from './reducers/reduceJoyce'
import actions from './actions' import actions from './actions'
import api from './modules/api'
import { logger, joyceAPI, joyceInterface, joyceRouter } from './middleware/' import { logger, joyceAPI, joyceInterface, joyceRouter } from './middleware/'
import ReaderPageContainer from './containers/readerPageContainer' import ReaderPageContainer from './containers/readerPageContainer'
import EditorPageContainer from './containers/editorPageContainer' import EditorPageContainer from './containers/editorPageContainer'
import SearchPageContainer from './containers/searchPageContainer' import SearchPageContainer from './containers/searchPageContainer'
import AdminHeader from './components/adminHeader'
const history = createHistory() const history = createHistory()
const router = routerMiddleware(history) const router = routerMiddleware(history)
@ -24,12 +24,6 @@ const store = createStore(reduceJoyce,
applyMiddleware(logger, router, joyceAPI, joyceInterface, joyceRouter)) applyMiddleware(logger, router, joyceAPI, joyceInterface, joyceRouter))
const state = store.getState() const state = store.getState()
const refreshElasticsearch = () => {
api.HTTPGetRefreshList().then(response =>
location.reload()
)
}
store.dispatch(actions.getDocumentList({docType: 'chapters'})) store.dispatch(actions.getDocumentList({docType: 'chapters'}))
store.dispatch(actions.getDocumentList({docType: 'notes'})) store.dispatch(actions.getDocumentList({docType: 'notes'}))
store.dispatch(actions.getDocumentList({docType: 'tags'})) store.dispatch(actions.getDocumentList({docType: 'tags'}))
@ -38,7 +32,7 @@ ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<div> <div>
<div id='admin_toolbar'><button type='button' className='btn btn-sm btn-outline-primary' onClick={refreshElasticsearch}>Refresh</button></div> <AdminHeader toggles={state.toggles} hideAdmin={()=>store.dispatch(actions.hideAdmin())}/>
<Navbar /> <Navbar />
<Switch> <Switch>
<Route exact path='/' render={() => <Route exact path='/' render={() =>

View File

@ -14,7 +14,7 @@ const joyceInterface = store => next => action => {
store.dispatch(actions.getDocumentText({id: action.id, docType: action.docType, state: 'currentDocument'})) store.dispatch(actions.getDocumentText({id: action.id, docType: action.docType, state: 'currentDocument'}))
break break
case 'SUBMIT_DOCUMENT_EDIT': case 'SUBMIT_DOCUMENT_EDIT':
const docErrors = validateSubmittedDocument(action.docType, action.documentTitleInput, action.colorPickerInput) const docErrors = validateSubmittedDocument(action.docType, action.inputs)
if (docErrors.length < 1) { if (docErrors.length < 1) {
const textContent = action.editorState.getCurrentContent() const textContent = action.editorState.getCurrentContent()
const data = { const data = {

View File

@ -1,15 +1,15 @@
import regex from './regex' import regex from './regex'
export const validateSubmittedDocument = (docType, documentTitleInput, colorPickerInput) => { export const validateSubmittedDocument = (docType, inputs) => {
const errors = [] const errors = []
if (docType === 'tags') { if (docType === 'tags') {
if (colorPickerInput.length < 1) { if (inputs.colorPicker.length < 1) {
errors.push('Please select a tag color.') errors.push('Please select a tag color.')
} else if (!regex.checkColorPickerHexValue(colorPickerInput)) { } else if (!regex.checkColorPickerHexValue(inputs.colorPicker)) {
errors.push('Please select a valid hex code color.') errors.push('Please select a valid hex code color.')
} }
} }
if (documentTitleInput.length < 1) { if (inputs.documentTitle.length < 1) {
errors.push('Please enter a title.') errors.push('Please enter a title.')
} }
return errors return errors

61
src/reducers/inputs.js Normal file
View File

@ -0,0 +1,61 @@
const initialState = {
documentTitle: '',
search: '',
colorPicker: '',
}
const inputs = (state=initialState, action) => {
switch(action.type) {
// Document Title
case 'GET_DOCUMENT_TEXT':
if (action.status === 'success' && action.state === 'currentDocument') {
return {
...state,
documentTitle: action.data.title
}
} else { return state }
case 'CREATE_DOCUMENT':
return {
...state,
documentTitle: ''
}
case 'UPDATE_DOCUMENT_TITLE':
return {
...state,
documentTitle: action.data
}
// Search
case 'UPDATE_SEARCH_INPUT':
return {
...state,
search: action.data
}
// Color Picker
case 'GET_DOCUMENT_TEXT':
if (action.status === 'success' && action.state === 'currentDocument' && action.docType === 'tags') {
return {
...state,
colorPicker: action.data.color
}
} else { return state }
case 'CREATE_DOCUMENT':
return {
...state,
colorPicker: ''
}
case 'SELECT_COLOR_SWATCH':
return {
...state,
colorPicker: action.data
}
case 'UPDATE_COLOR_PICKER':
return {
...state,
colorPicker: action.data.toUpperCase()
}
default:
return state
}
}
export default inputs

View File

@ -15,15 +15,17 @@ import searchResults from './searchResults'
import editorState from './editorState' import editorState from './editorState'
import modalEditorState from './modalEditorState' import modalEditorState from './modalEditorState'
import selectionState from './selectionState' import selectionState from './selectionState'
import documentTitleInput from './documentTitleInput' import inputs from './inputs'
import colorPickerInput from './colorPickerInput' // import documentTitleInput from './documentTitleInput'
import searchInput from './searchInput' // import colorPickerInput from './colorPickerInput'
// import searchInput from './searchInput'
// Toggles
import docType from './docType' import docType from './docType'
import mode from './mode' import mode from './mode'
import highlightToggle from './highlightToggle' // Toggles
import loadingToggle from './loadingToggle' import toggles from './toggles'
// import highlightToggle from './highlightToggle'
// import loadingToggle from './loadingToggle'
// Validation // Validation
import userErrors from './userErrors' import userErrors from './userErrors'
@ -42,14 +44,16 @@ const reduceJoyce = combineReducers({
editorState, editorState,
modalEditorState, modalEditorState,
selectionState, selectionState,
colorPickerInput, inputs,
documentTitleInput, // colorPickerInput,
searchInput, // documentTitleInput,
// searchInput,
// Toggles // Toggles
docType, docType,
mode, mode,
highlightToggle, toggles,
loadingToggle, // highlightToggle,
// loadingToggle,
// Validation // Validation
userErrors, userErrors,
}) })

46
src/reducers/toggles.js Normal file
View File

@ -0,0 +1,46 @@
const initialState = {
loading: true,
highlights: true,
admin: true,
}
const toggles = (state=initialState, action) => {
switch(action.type) {
// Loading
case 'GET_DOCUMENT_TEXT':
if (action.status === 'request' && action.state === 'currentDocument') {
return {
...state,
loading: true
}
} else if (action.status === 'success' && action.state === 'currentDocument') {
return {
...state,
loading: false
}
}
case 'GET_DOCUMENT_LIST':
if (action.status === 'success' && !action.data[0] && action.state === 'currentDocType') {
return {
...state,
loading: false
}
}
// Highlights
case 'TOGGLE_HIGHLIGHT':
return {
...state,
highlights: !state.highlights
}
// Admin
case 'HIDE_ADMIN_HEADER':
return {
...state,
admin: false
}
default:
return state
}
}
export default toggles

View File

@ -3,7 +3,7 @@ import { validateSubmittedDocument, validateSubmittedAnnotation } from '../modul
const userErrors = (state=[], action) => { const userErrors = (state=[], action) => {
switch(action.type) { switch(action.type) {
case 'SUBMIT_DOCUMENT_EDIT': case 'SUBMIT_DOCUMENT_EDIT':
return validateSubmittedDocument(action.docType, action.documentTitleInput, action.colorPickerInput) return validateSubmittedDocument(action.docType, action.inputs)
case 'SUBMIT_ANNOTATION': case 'SUBMIT_ANNOTATION':
return validateSubmittedAnnotation(action.annotationNote, action.annotationTag) return validateSubmittedAnnotation(action.annotationNote, action.annotationTag)
case 'GET_DOCUMENT_TEXT': case 'GET_DOCUMENT_TEXT':

View File

@ -1,5 +1,9 @@
@import "variables"; @import "variables";
#admin_toolbar { #admin_header {
padding: .3rem; padding: .3rem;
}
.admin_hide {
display: none;
} }

View File

@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<head> <head>
<title>Joyce - Reader</title> <title>Joyce</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/static/icon.png"> <link rel="icon" type="image/png" href="/static/icon.png">
<script>const assets = {{ assets|tojson }}</script> <script>const assets = {{ assets|tojson }}</script>