Working on the editor UI. Needs some refactoring components and wire up api middleware.
3
TODO.txt
|
@ -9,13 +9,14 @@
|
||||||
|
|
||||||
Short List:
|
Short List:
|
||||||
- Some Testing
|
- Some Testing
|
||||||
|
- Font Awesome / Better Glyphicons
|
||||||
- Env Configs
|
- Env Configs
|
||||||
- Collapsable Button Lists
|
- Collapsable Button Lists
|
||||||
- Draft.JS
|
- Draft.JS
|
||||||
- DRY up Sass Modules
|
- DRY up Sass Modules
|
||||||
- Async API Middleware
|
- Async API Middleware
|
||||||
- CombineReducers in App.js
|
- CombineReducers in App.js
|
||||||
- Import Actions into Reducers
|
- Import Action consts into Reducers
|
||||||
- PropTypes
|
- PropTypes
|
||||||
|
|
||||||
- Loading Indicators
|
- Loading Indicators
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"clean-webpack-plugin": "^0.1.17",
|
"clean-webpack-plugin": "^0.1.17",
|
||||||
"css-loader": "^0.28.7",
|
"css-loader": "^0.28.7",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
|
"file-loader": "^1.1.5",
|
||||||
"manifest-revision-webpack-plugin": "^0.4.1",
|
"manifest-revision-webpack-plugin": "^0.4.1",
|
||||||
"node-sass": "^4.6.0",
|
"node-sass": "^4.6.0",
|
||||||
"postcss-loader": "^2.0.8",
|
"postcss-loader": "^2.0.8",
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
const setCurrentChapter = id =>
|
|
||||||
({
|
|
||||||
type: 'GET_TEXT_DATA',
|
|
||||||
id: id
|
|
||||||
})
|
|
||||||
|
|
||||||
const toggleHighlight = () =>
|
|
||||||
({
|
|
||||||
type: 'TOGGLE_HIGHLIGHT'
|
|
||||||
})
|
|
||||||
|
|
||||||
const updateEditorState = editorState =>
|
|
||||||
({
|
|
||||||
type: 'UPDATE_EDITOR_STATE',
|
|
||||||
payload: editorState
|
|
||||||
})
|
|
||||||
|
|
||||||
export {
|
|
||||||
setCurrentChapter,
|
|
||||||
toggleHighlight,
|
|
||||||
updateEditorState
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
import axios from 'axios'
|
||||||
|
import EditorState from 'draft-js'
|
||||||
|
|
||||||
|
let apiRoute = '/api/chapters/'
|
||||||
|
|
||||||
|
const SELECT_CHAPTER = 'SELECT_CHAPTER'
|
||||||
|
const GET_CHAPTER_DATA = 'GET_CHAPTER_DATA'
|
||||||
|
const GET_CHAPTER_DATA_RECEIVED = 'GET_CHAPTER_DATA_RECEIVED'
|
||||||
|
const GET_CHAPTER_DATA_ERROR = 'GET_CHAPTER_DATA_ERROR'
|
||||||
|
const GET_TEXT_DATA = 'GET_TEXT_DATA'
|
||||||
|
const GET_TEXT_DATA_RECEIVED = 'GET_TEXT_DATA_RECEIVED'
|
||||||
|
const GET_TEXT_DATA_ERROR = 'GET_TEXT_DATA_ERROR'
|
||||||
|
const UPDATE_EDITOR_STATE = 'UPDATE_EDITOR_STATE'
|
||||||
|
const TOGGLE_HIGHLIGHT = 'TOGGLE_HIGHLIGHT'
|
||||||
|
const UPDATE_CHAPTER_TITLE = 'UPDATE_CHAPTER_TITLE'
|
||||||
|
|
||||||
|
export const setCurrentChapter = id =>
|
||||||
|
({
|
||||||
|
type: GET_TEXT_DATA,
|
||||||
|
id: id
|
||||||
|
})
|
||||||
|
|
||||||
|
export const toggleHighlight = () =>
|
||||||
|
({
|
||||||
|
type: TOGGLE_HIGHLIGHT
|
||||||
|
})
|
||||||
|
|
||||||
|
export const updateChapterTitleInput = chapterTitleInput => {
|
||||||
|
return ({
|
||||||
|
type: UPDATE_CHAPTER_TITLE,
|
||||||
|
data: chapterTitleInput.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateEditorState = editorState =>
|
||||||
|
({
|
||||||
|
type: UPDATE_EDITOR_STATE,
|
||||||
|
data: editorState
|
||||||
|
})
|
||||||
|
|
||||||
|
export const chapterDataReceived = data =>
|
||||||
|
({
|
||||||
|
type: GET_CHAPTER_DATA_RECEIVED,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
|
||||||
|
export const chapterDataError = error =>
|
||||||
|
({
|
||||||
|
type: GET_CHAPTER_DATA_ERROR,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
|
||||||
|
export const textDataReceived = data =>
|
||||||
|
({
|
||||||
|
type: GET_TEXT_DATA_RECEIVED,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
|
||||||
|
export const textDataError = error =>
|
||||||
|
({
|
||||||
|
type: GET_TEXT_DATA_ERROR,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
|
||||||
|
export const setChapterEditor = chapter =>
|
||||||
|
({
|
||||||
|
type: SET_EDITED_CHAPTER,
|
||||||
|
chapter
|
||||||
|
})
|
||||||
|
|
||||||
|
export const logger = store => next => action => {
|
||||||
|
console.group(action.type)
|
||||||
|
console.info('dispatching', action)
|
||||||
|
let result = next(action)
|
||||||
|
console.log('next state', store.getState())
|
||||||
|
console.log('chapter count', store.getState().chapters.length)
|
||||||
|
console.groupEnd(action.type)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export const joyceAPIService = store => next => action => {
|
||||||
|
next(action)
|
||||||
|
switch(action.type) {
|
||||||
|
case GET_CHAPTER_DATA:
|
||||||
|
axios.get(apiRoute).then(res => {
|
||||||
|
const data = res.data
|
||||||
|
return next(chapterDataReceived(data))
|
||||||
|
}).catch(error => {
|
||||||
|
return next(chapterDataError(error))
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case GET_TEXT_DATA:
|
||||||
|
axios.get(apiRoute + action.id).then(res=> {
|
||||||
|
const data = res.data
|
||||||
|
return next(textDataReceived(data))
|
||||||
|
}).catch(error => {
|
||||||
|
return next(textDataError(error))
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case CREATE_CHAPTER:
|
||||||
|
const nextNumber = store.getState().chapters.length + 1
|
||||||
|
const chapter = {
|
||||||
|
number: nextNumber,
|
||||||
|
title: '',
|
||||||
|
text: EditorState.createEmpty(),
|
||||||
|
}
|
||||||
|
store.dispatch(setChapterEditor(chapter))
|
||||||
|
break
|
||||||
|
defaut:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const foo = 'bar'
|
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,30 @@
|
||||||
|
const glyphiconItalic = require('./glyphicons-102-italic.png')
|
||||||
|
const glyphiconBold = require('./glyphicons-103-bold.png')
|
||||||
|
const glyphiconUnderline = require('./glyphicons-104-text-underline.png')
|
||||||
|
|
||||||
|
const glyphiconAlignLeft = require('./glyphicons-111-align-left.png')
|
||||||
|
const glyphiconAlignCenter = require('./glyphicons-112-align-center.png')
|
||||||
|
const glyphiconAlignRight = require('./glyphicons-113-align-right.png')
|
||||||
|
|
||||||
|
const glyphiconChevronLeft = require('./glyphicons-225-chevron-left.png')
|
||||||
|
const glyphiconChevronRight = require('./glyphicons-224-chevron-right.png')
|
||||||
|
|
||||||
|
const glyphiconPlusSign = require('./glyphicons-191-plus-sign.png')
|
||||||
|
const glyphiconMinusSign = require('./glyphicons-192-minus-sign.png')
|
||||||
|
const glyphiconRemoveSign = require('./glyphicons-193-remove-sign.png')
|
||||||
|
const glyphiconOKSign = require('./glyphicons-194-ok-sign.png')
|
||||||
|
|
||||||
|
export {
|
||||||
|
glyphiconItalic,
|
||||||
|
glyphiconBold,
|
||||||
|
glyphiconUnderline,
|
||||||
|
glyphiconAlignLeft,
|
||||||
|
glyphiconAlignCenter,
|
||||||
|
glyphiconAlignRight,
|
||||||
|
glyphiconChevronLeft,
|
||||||
|
glyphiconChevronRight,
|
||||||
|
glyphiconPlusSign,
|
||||||
|
glyphiconMinusSign,
|
||||||
|
glyphiconRemoveSign,
|
||||||
|
glyphiconOKSign
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
const EditorButtonGroup = () =>
|
|
||||||
<div className='editor_button_group'>
|
|
||||||
<div className='btn-group' role='group'>
|
|
||||||
<button type='button' className='btn btn-secondary'>Bold</span></button>
|
|
||||||
<button type='button' className='btn btn-secondary'>Italics</span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
export default EditorButtonGroup
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import React from 'react'
|
||||||
|
import ChapterListContainer from '../containers/chapterListContainer'
|
||||||
|
import NewChapterButtonContainer from '../containers/newChapterButtonContainer'
|
||||||
|
import SidebarSpacer from './sidebarSpacer'
|
||||||
|
|
||||||
|
const EditorSidebar = () =>
|
||||||
|
<div className="col-md-3" id="sidebar">
|
||||||
|
<SidebarSpacer />
|
||||||
|
<NewChapterButtonContainer />
|
||||||
|
<SidebarSpacer />
|
||||||
|
<ChapterListContainer />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
export default EditorSidebar
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { glyphiconPlusSign } from '../assets'
|
||||||
|
|
||||||
|
const NewChapterButton = () =>
|
||||||
|
<div>
|
||||||
|
<div id="highlight_button" className="text-center">
|
||||||
|
<button className='btn btn-outline-success btn-lg'>
|
||||||
|
New Chapter <img src={glyphiconPlusSign} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
export default NewChapterButton
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
import { setCurrentChapter } from '../actions/actions'
|
import { setCurrentChapter } from '../actions'
|
||||||
|
|
||||||
import ChapterList from '../components/chapterList'
|
import ChapterList from '../components/chapterList'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
|
|
||||||
import TextEditorContainer from '../containers/textEditorContainer'
|
import TextEditorContainer from '../containers/textEditorContainer'
|
||||||
import Navbar from '../components/navbar'
|
import Navbar from '../components/navbar'
|
||||||
import Sidebar from '../components/sidebar'
|
import EditorSidebar from '../components/editorSidebar'
|
||||||
import Content from '../components/content'
|
import Content from '../components/content'
|
||||||
|
|
||||||
const EditorContainer = () =>
|
const EditorContainer = () =>
|
||||||
|
@ -10,7 +10,7 @@ const EditorContainer = () =>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div id='joyce_editor' className='container-fluid'>
|
<div id='joyce_editor' className='container-fluid'>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<Sidebar />
|
<EditorSidebar />
|
||||||
<Content>
|
<Content>
|
||||||
<TextEditorContainer />
|
<TextEditorContainer />
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
import { toggleHighlight } from '../actions/actions'
|
import { toggleHighlight } from '../actions'
|
||||||
|
|
||||||
import HighlightButton from '../components/highlightButton'
|
import HighlightButton from '../components/highlightButton'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { createNewChapter } from '../actions'
|
||||||
|
|
||||||
|
import NewChapterButton from '../components/newChapterButton'
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onNewChapterClick: () => {
|
||||||
|
dispatch(createNewChapter())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NewChapterButtonContainer = connect(mapDispatchToProps)(NewChapterButton)
|
||||||
|
|
||||||
|
export default NewChapterButtonContainer
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { setCurrentChapter } from '../actions/actions'
|
import { setCurrentChapter } from '../actions'
|
||||||
|
|
||||||
class Page extends React.Component {
|
class Page extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
import { setCurrentChapter } from '../actions/actions'
|
import { setCurrentChapter } from '../actions'
|
||||||
|
|
||||||
import PageContainer from '../containers/pageContainer'
|
import PageContainer from '../containers/pageContainer'
|
||||||
import Content from '../components/content'
|
import Content from '../components/content'
|
||||||
|
|
|
@ -1,21 +1,57 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { updateEditorState } from '../actions/actions'
|
import { updateEditorState, updateChapterTitleInput } from '../actions'
|
||||||
|
|
||||||
import { Editor, convertToRaw } from 'draft-js';
|
import { Editor, convertToRaw } from 'draft-js';
|
||||||
|
|
||||||
import EditorButtonGroup from '../components/editorButtonGroup'
|
import { glyphiconBold, glyphiconItalic, glyphiconUnderline, glyphiconAlignLeft, glyphiconAlignCenter, glyphiconAlignRight } from '../assets'
|
||||||
|
|
||||||
const TextEditor = ({editorState, onSaveEditorState}) =>
|
const TextEditor = ({editorState, onSaveEditorState, chapterTitleInput, onChapterTitleChange}) =>
|
||||||
<div id="text_editor">
|
<div id='editor_container'>
|
||||||
<EditorButtonGroup />
|
<div id='editor_topbar'>
|
||||||
<Editor editorState={editorState} onChange={onSaveEditorState} />
|
<div className='row'>
|
||||||
{JSON.stringify(editorState.getSelection())}
|
<div className='col-md-4'>
|
||||||
|
<h4>Chapter 1:</h4>
|
||||||
|
</div>
|
||||||
|
<div className='col-md-8'>
|
||||||
|
<input type="text" value={chapterTitleInput} onChange={onChapterTitleChange}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className='row'>
|
||||||
|
<div className='btn-group col-md-3 offset-md-6' role='group'>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconBold} /></button>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconItalic} /></button>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconUnderline} /></button>
|
||||||
|
</div>
|
||||||
|
<div className='btn-group col-md-3' role='group'>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconAlignLeft} /></button>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconAlignCenter} /></button>
|
||||||
|
<button type='button' className='btn btn-info btn-sm'><img src={glyphiconAlignRight} /></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id='editor_content'>
|
||||||
|
<Editor editorState={editorState} onChange={onSaveEditorState} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id='editor_bottombar'>
|
||||||
|
<div className='row'>
|
||||||
|
<div className='col-md-5'>
|
||||||
|
<button id='editor_delete' type='button' className='btn btn-danger btn-sm'>Delete</button>
|
||||||
|
</div>
|
||||||
|
<div className='col-md-5 offset-md-2'>
|
||||||
|
<button id='editor_save' type='button' className='btn btn-success btn-sm'>Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
editorState: state.editorState
|
editorState: state.editorState,
|
||||||
|
chapterTitleInput: state.chapterTitleInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +59,9 @@ const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
onSaveEditorState: editorState => {
|
onSaveEditorState: editorState => {
|
||||||
dispatch(updateEditorState(editorState))
|
dispatch(updateEditorState(editorState))
|
||||||
|
},
|
||||||
|
onChapterTitleChange: chapterTitleInput => {
|
||||||
|
dispatch(updateChapterTitleInput(chapterTitleInput))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,26 @@ import { createStore, combineReducers, applyMiddleware } from 'redux'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import 'bootstrap'
|
import 'bootstrap'
|
||||||
|
|
||||||
import { chapters, highlightActive, currentChapter, editorState } from './reducers/editor'
|
import { chapters, highlightActive, currentChapter, chapterTitleInput, editorState } from './reducers/editor'
|
||||||
import joyceAPIService from './middleware'
|
import { joyceAPIService, logger } from './actions'
|
||||||
import EditorContainer from './containers/editorContainer'
|
import EditorContainer from './containers/editorContainer'
|
||||||
|
|
||||||
const reduceEditor = combineReducers({
|
const reduceEditor = combineReducers({
|
||||||
chapters,
|
chapters,
|
||||||
currentChapter,
|
currentChapter,
|
||||||
|
chapterTitleInput,
|
||||||
highlightActive,
|
highlightActive,
|
||||||
editorState
|
editorState
|
||||||
})
|
})
|
||||||
|
|
||||||
let store = createStore(reduceEditor, applyMiddleware(joyceAPIService))
|
let store = createStore(reduceEditor, applyMiddleware(joyceAPIService, logger))
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<EditorContainer />
|
<EditorContainer />
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.getElementById('wrapper')
|
document.getElementById('wrapper')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
store.dispatch({type: 'GET_CHAPTER_DATA'})
|
||||||
|
store.dispatch({type: 'GET_TEXT_DATA', id: 1})
|
|
@ -5,7 +5,7 @@ import { Provider } from 'react-redux'
|
||||||
import 'bootstrap'
|
import 'bootstrap'
|
||||||
|
|
||||||
import { chapters, currentChapter, highlightActive } from './reducers/reader'
|
import { chapters, currentChapter, highlightActive } from './reducers/reader'
|
||||||
import joyceAPIService from './middleware'
|
import { joyceAPIService } from './actions'
|
||||||
import { ReaderContainer } from './containers/readerContainer'
|
import { ReaderContainer } from './containers/readerContainer'
|
||||||
|
|
||||||
const reduceReader = combineReducers({
|
const reduceReader = combineReducers({
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { EditorState } from 'draft-js'
|
import { EditorState } from 'draft-js'
|
||||||
import objectAssign from 'object-assign' // Object.assign() polyfill for older browsers
|
import objectAssign from 'object-assign' // Object.assign() polyfill for older browsers
|
||||||
import actions from '../actions/actions'
|
import actions from '../actions'
|
||||||
|
|
||||||
const chapters = (state=[], action) => {
|
const chapters = (state=[], action) => {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
|
@ -32,8 +32,16 @@ const currentChapter = (state={}, action) => {
|
||||||
const editorState = (state=(EditorState.createEmpty()), action) => {
|
const editorState = (state=(EditorState.createEmpty()), action) => {
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case 'UPDATE_EDITOR_STATE':
|
case 'UPDATE_EDITOR_STATE':
|
||||||
console.log(action.payload.getSelection())
|
return action.data
|
||||||
return action.payload
|
default:
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const chapterTitleInput = (state='', action) => {
|
||||||
|
switch(action.type) {
|
||||||
|
case 'UPDATE_CHAPTER_TITLE':
|
||||||
|
return action.data
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@ -43,5 +51,6 @@ export {
|
||||||
chapters,
|
chapters,
|
||||||
highlightActive,
|
highlightActive,
|
||||||
currentChapter,
|
currentChapter,
|
||||||
|
chapterTitleInput,
|
||||||
editorState
|
editorState
|
||||||
}
|
}
|
|
@ -1,4 +1,7 @@
|
||||||
$theme-colors: (
|
$theme-colors: (
|
||||||
|
"info": #537577,
|
||||||
|
"danger": #72030a,
|
||||||
|
"success": #118734,
|
||||||
"dark": #07383a,
|
"dark": #07383a,
|
||||||
"primary": #824500
|
"primary": #824500
|
||||||
);
|
);
|
|
@ -108,13 +108,50 @@ nav a:hover {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#text_editor {
|
#editor_topbar {
|
||||||
|
margin: 0.8% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_topbar input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_topbar button img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_content {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(256,256,256,.8);
|
background-color: rgba(256,256,256,.8);
|
||||||
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
|
box-shadow: 2px 5px 10px 1px rgba(0, 0, 0, 0.3);
|
||||||
padding: 3% 8%;
|
margin: 0.8% 0;
|
||||||
border: 1px solid $border_color;
|
border: 1px solid $border_color;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
padding: 3% 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_content div {
|
||||||
|
height: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_topbar button img {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_bottombar {
|
||||||
|
margin: 0.8% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_delete {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_save {
|
||||||
|
float: right;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#page {
|
#page {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
const CleanWebpackPlugin = require('clean-webpack-plugin')
|
const CleanWebpackPlugin = require('clean-webpack-plugin')
|
||||||
const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin');
|
const ManifestRevisionPlugin = require('manifest-revision-webpack-plugin')
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack')
|
||||||
const path = require('path');
|
const path = require('path')
|
||||||
|
|
||||||
const rootAssetPath = './src/';
|
const rootAssetPath = './src/'
|
||||||
|
|
||||||
let pathsToClean = [
|
let pathsToClean = [
|
||||||
'static/'
|
'static/'
|
||||||
|
@ -25,7 +25,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
publicPath: "/static/js/",
|
publicPath: "/static/js/",
|
||||||
filename: '[name].[chunkhash].js',
|
filename: '[name].[hash].js',
|
||||||
path: path.resolve(__dirname, 'static/js/')
|
path: path.resolve(__dirname, 'static/js/')
|
||||||
},
|
},
|
||||||
watch: true,
|
watch: true,
|
||||||
|
@ -44,6 +44,12 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png)$/,
|
||||||
|
use: {
|
||||||
|
loader: 'file-loader'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.(scss)$/,
|
test: /\.(scss)$/,
|
||||||
use: [{
|
use: [{
|
||||||
|
@ -75,6 +81,6 @@ module.exports = {
|
||||||
'window.jQuery': 'jquery',
|
'window.jQuery': 'jquery',
|
||||||
Popper: ['popper.js', 'default']
|
Popper: ['popper.js', 'default']
|
||||||
}),
|
}),
|
||||||
new CleanWebpackPlugin(pathsToClean)
|
new CleanWebpackPlugin(pathsToClean),
|
||||||
],
|
],
|
||||||
};
|
};
|