Collapsible admin toolbar

This commit is contained in:
Alex Hunt 2018-12-02 15:05:04 -08:00
parent c9f197675f
commit 125cef05bb
12 changed files with 124 additions and 51 deletions

View File

@ -16,7 +16,6 @@
"draft-js": "^0.10.4",
"draft-js-export-html": "^1.2.0",
"draft-js-import-html": "^1.2.1",
"font-awesome": "^4.7.0",
"history": "^4.7.2",
"popper.js": "^1.14.5",
"prop-types": "^15.6.1",
@ -29,6 +28,7 @@
"redux": "^3.7.2"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.5.0",
"babel-core": "^6.26.0",
"babel-jest": "^22.4.3",
"babel-loader": "^7.1.2",

View File

@ -115,6 +115,10 @@ const userActions = {
({
type: 'CLEAR_ANNOTATION_TAG'
}),
showAdmin: () =>
({
type: 'SHOW_ADMIN_HEADER'
}),
hideAdmin: () =>
({
type: 'HIDE_ADMIN_HEADER'

View File

@ -1,28 +0,0 @@
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

@ -10,7 +10,7 @@ export const ReaderEditButton = ({onClick}) =>
<div className='edit_note_button'>
<button onClick={onClick} className='btn btn-outline-primary btn-sm'>
Edit
<i className='fa fa_inline fa-edit'></i>
<i className='fas fa_inline fa-edit'></i>
</button>
</div>
@ -18,7 +18,7 @@ export const ReaderAnnotateButton = ({onClick}) =>
<div className='annotate_note_button'>
<button onClick={onClick} className='btn btn-outline-primary btn-sm'>
Annotate
<i className='fa fa_inline fa-link'></i>
<i className='fas fa_inline fa-link'></i>
</button>
</div>
@ -57,7 +57,7 @@ export const SearchButton = ({input, onClick}) =>
<div>
<div id='search_button' className='text-center'>
<button className='btn btn-primary btn-sm' onClick={()=>onClick(input)}>
Search <i className='fa fa_inline fa-search'></i>
Search <i className='fas fa_inline fa-search'></i>
</button>
</div>
</div>
@ -66,7 +66,7 @@ export const NewChapterButton = ({onClick}) =>
<div>
<div id='new_chapter_button' className='text-center'>
<button onClick={onClick} className='btn btn-outline-success btn-lg'>
New Chapter <i className='fa fa_inline fa-plus-square-o'></i>
New Chapter <i className='fas fa_inline fa-plus-square-o'></i>
</button>
</div>
</div>
@ -76,7 +76,7 @@ export const NewDocumentButton = ({onClick, docType}) =>
<div id='new_document_button' className='text-center'>
<button onClick={onClick} className='btn btn-outline-success btn-sm'>
New {helpers.docTypeName(docType)}
<i className='fa fa_inline fa-plus-square-o'></i>
<i className='fas fa_inline fa-plus-square-o'></i>
</button>
</div>
</div>
@ -86,43 +86,43 @@ export const NewDocumentButton = ({onClick, docType}) =>
export const AnnotatorNewButton = ({onClick, disabled}) =>
<button type='button' onClick={onClick} disabled={disabled} className='btn btn-info btn-sm' data-toggle='modal' data-target='#annotate_modal'>
New Annotation
<i className='fa fa_inline fa-link'></i>
<i className='fas fa_inline fa-link'></i>
</button>
export const AnnotatorRemoveButton = ({onClick, disabled}) =>
<button type='button' onClick={onClick} disabled={disabled} className='btn btn-secondary btn-sm'>
Remove Annotation
<i className='fa fa_inline fa-unlink'></i>
<i className='fas fa_inline fa-unlink'></i>
</button>
export const EditorToolButton = ({glyph, onClick}) =>
<button type='button' onClick={onClick} className='btn btn-info btn-sm'>
<i className={'fa fa-' + glyph}></i>
<i className={'fas fa-' + glyph}></i>
</button>
export const EditorDeleteToolButton = ({disabled}) =>
<button className='btn btn-info btn-sm' disabled={disabled} data-toggle='modal' data-target='#delete_confirm_modal' type='button'>
Delete
<i className='fa fa_inline fa-trash-o'></i>
<i className='fas fa_inline fa-trash-o'></i>
</button>
export const EditorCancelButton = ({onClick}) =>
<button type='button' onClick={onClick} className='btn btn-outline-secondary btn-sm' data-dismiss='modal'>
Cancel
<i className='fa fa_inline fa-times'></i>
<i className='fas fa_inline fa-times'></i>
</button>
export const EditorSubmitButton = ({onClick}) =>
<button id='editor_submit' onClick={onClick} type='button' className='btn btn-outline-success btn-sm'>
Submit
<i className='fa fa_inline fa-check-square-o'></i>
<i className='fas fa_inline fa-check-square-o'></i>
</button>
export const EditorDeleteButton = ({onClick}) =>
<button id='editor_delete' onClick={onClick} type='button' data-dismiss='modal' className='btn btn-outline-danger btn-sm'>
Delete
<i className='fa fa_inline fa-trash-o'></i>
<i className='fas fa_inline fa-trash-o'></i>
</button>
ReaderEditButton.propTypes = {

View File

@ -14,7 +14,7 @@ const ChooseAnnotationModal = ({notes, tags, annotationNote, annotationTag, moda
<div className='modal-header'>
<h5 className='modal-title' id='exampleModalLabel'>Select a note</h5>
<button id='select_annotation_modal_close' type="button" className="close" data-dismiss="modal">
<i className='fa fa-times'></i>
<i className='fas fa-times'></i>
</button>
</div>
<div className='modal-body'>
@ -28,7 +28,7 @@ const ChooseAnnotationModal = ({notes, tags, annotationNote, annotationTag, moda
</div>
<div className='row'>
<div id='annotation_tag_dropdown' className='col-md-2'>
<button className={annotationNote.id ? 'btn btn-primary dropdown-toggle caret-off' : 'btn btn-primary dropdown-toggle caret-off disabled'} data-toggle='dropdown' type='button'><i className='fa fa-chevron-down'></i>Tags</button>
<button className={annotationNote.id ? 'btn btn-primary dropdown-toggle caret-off' : 'btn btn-primary dropdown-toggle caret-off disabled'} data-toggle='dropdown' type='button'><i className='fas fa-chevron-down'></i>Tags</button>
<div className='dropdown-menu'>
{tags.map(tag =>
<div key={tag.id} className='dropdown-item' onClick={()=>selectAnnotationTag(tag)}>
@ -44,7 +44,7 @@ const ChooseAnnotationModal = ({notes, tags, annotationNote, annotationTag, moda
<TagColorPreview color={annotationTag.color}/>
{annotationTag.title}
<a id='clear_anntation_tag' onClick={clearAnnotationTag}>
<i className='fa fa-times'></i>
<i className='fas fa-times'></i>
</a>
</div>
}

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
const LoadingSpinner = ({size=2}) =>
<div className='loading_spinner'>
<i className={'fa fa-cog fa-spin fa-' + size + 'x fa-fw'}></i>
<i className={'fas fa-cog fa-spin fa-' + size + 'x fa-fw'}></i>
</div>
LoadingSpinner.propTypes = {

View File

@ -9,7 +9,7 @@ const TagColorPicker = ({input, onChange, onColorSwatchClick}) =>
</div>
<input type='text' className='form-control' placeholder='Color' value={input} onChange={onChange}/>
<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='fas fa-chevron-down'></i></button>
<div className='dropdown-menu'>
{defaultTagColors.map(color =>
<div key={color} className='dropdown-item'>

View File

@ -0,0 +1,61 @@
import React from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import actions from '../actions'
import api from '../modules/api'
const refreshElasticsearch = () => {
api.HTTPGetRefreshList().then(response =>
location.reload()
)
}
const AdminHeader = ({toggles, hideAdmin, showAdmin}) => {
if (toggles.admin === true) {
return (
<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='fas fa-times'/>
</button>
</div>
)
} else {
return (
<div id='open_admin_button'>
<button type='button' className='btn btn-sm btn-outline-danger' onClick={showAdmin}>
<i className='fas fa-screwdriver'/>
</button>
</div>
)
}
}
const mapStateToProps = state => {
return {
toggles: state.toggles,
}
}
const mapDispatchToProps = dispatch => {
return {
hideAdmin: () => {
dispatch(actions.hideAdmin())
},
showAdmin: () => {
dispatch(actions.showAdmin())
}
}
}
const AdminHeaderContainer = connect(mapStateToProps, mapDispatchToProps)(AdminHeader)
export default AdminHeaderContainer
AdminHeader.propTypes = {
refreshElasticsearch: PropTypes.func,
}

View File

@ -16,7 +16,7 @@ import { logger, joyceAPI, joyceInterface, joyceRouter } from './middleware/'
import ReaderPageContainer from './containers/readerPageContainer'
import EditorPageContainer from './containers/editorPageContainer'
import SearchPageContainer from './containers/searchPageContainer'
import AdminHeader from './components/adminHeader'
import AdminHeaderContainer from './containers/adminHeaderContainer'
const history = createHistory()
const router = routerMiddleware(history)
@ -32,7 +32,7 @@ ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<AdminHeader toggles={state.toggles} hideAdmin={()=>store.dispatch(actions.hideAdmin())}/>
<AdminHeaderContainer />
<Navbar />
<Switch>
<Route exact path='/' render={() =>

View File

@ -33,6 +33,11 @@ const toggles = (state=initialState, action) => {
highlights: !state.highlights
}
// Admin
case 'SHOW_ADMIN_HEADER':
return {
...state,
admin: true
}
case 'HIDE_ADMIN_HEADER':
return {
...state,

View File

@ -1,4 +1,5 @@
@import "variables";
@import "mixin";
#admin_header {
padding: .3rem;
@ -6,4 +7,30 @@
.admin_hide {
display: none;
}
}
#open_admin_button {
position: absolute;
z-index: 1;
width: 6%;
margin: 0 auto;
padding: 0.4rem 0;
left: 0;
right: 0px;
background-color: rgba(245,245,245,0.1);
border: 1px solid rgba(245,245,245,0.6);
border-radius: 0 0 15px 15px;
}
@include respond-below(xs) {
#open_admin_button {
width: 14%;
}
}
#open_admin_button > button {
display: block;
margin: 0 auto;
}

View File

@ -10,8 +10,12 @@
@import "dev";
@import "node_modules/bootstrap/scss/bootstrap";
$fa-font-path: "../../node_modules/font-awesome/fonts";
@import "node_modules/font-awesome/scss/font-awesome";
// $fa-font-path: "../../node_modules/font-awesome/fonts";
// @import "node_modules/font-awesome/scss/font-awesome";
$fa-font-path: "../../node_modules/@fortawesome/fontawesome-free/webfonts";
@import "node_modules/@fortawesome/fontawesome-free/scss/fontawesome";
@import "node_modules/@fortawesome/fontawesome-free/scss/solid";
#joyce_reader {
overflow: hidden;