mirror of
https://github.com/BoostIo/Boostnote
synced 2026-01-30 09:07:21 +00:00
Detail
This commit is contained in:
17
browser/main/Detail/Detail.styl
Normal file
17
browser/main/Detail/Detail.styl
Normal file
@@ -0,0 +1,17 @@
|
||||
.root
|
||||
absolute top bottom right
|
||||
border-width 1px 0
|
||||
border-style solid
|
||||
border-color $ui-borderColor
|
||||
|
||||
.empty
|
||||
height 320px
|
||||
display flex
|
||||
align-items center
|
||||
|
||||
.empty-message
|
||||
width 100%
|
||||
font-size 42px
|
||||
line-height 72px
|
||||
text-align center
|
||||
color $ui-inactive-text-color
|
||||
155
browser/main/Detail/NoteDetail.js
Normal file
155
browser/main/Detail/NoteDetail.js
Normal file
@@ -0,0 +1,155 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './NoteDetail.styl'
|
||||
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
||||
import queue from 'browser/main/lib/queue'
|
||||
|
||||
class NoteDetail extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
note: Object.assign({}, props.note),
|
||||
isDispatchQueued: false
|
||||
}
|
||||
this.dispatchTimer = null
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps, prevState) {
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.note.key !== this.props.note.key) {
|
||||
if (this.state.isDispatchQueued) {
|
||||
this.dispatch()
|
||||
}
|
||||
this.setState({
|
||||
note: Object.assign({}, nextProps.note),
|
||||
isDispatchQueued: false
|
||||
}, () => {
|
||||
this.refs.content.reload()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
findTitle (value) {
|
||||
let splitted = value.split('\n')
|
||||
let title = null
|
||||
|
||||
for (let i = 0; i < splitted.length; i++) {
|
||||
let trimmedLine = splitted[i].trim()
|
||||
if (trimmedLine.match(/^# .+/)) {
|
||||
title = trimmedLine.substring(1, trimmedLine.length).trim()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (title == null) {
|
||||
for (let i = 0; i < splitted.length; i++) {
|
||||
let trimmedLine = splitted[i].trim()
|
||||
if (trimmedLine.length > 0) {
|
||||
title = trimmedLine
|
||||
break
|
||||
}
|
||||
}
|
||||
if (title == null) {
|
||||
title = ''
|
||||
}
|
||||
}
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
handleChange (e) {
|
||||
let { note } = this.state
|
||||
|
||||
note.content = this.refs.content.value
|
||||
|
||||
this.setState({
|
||||
note,
|
||||
isDispatchQueued: true
|
||||
}, () => {
|
||||
this.queueDispatch()
|
||||
})
|
||||
}
|
||||
|
||||
cancelDispatchQueue () {
|
||||
if (this.dispatchTimer != null) {
|
||||
window.clearTimeout(this.dispatchTimer)
|
||||
this.dispatchTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
queueDispatch () {
|
||||
this.cancelDispatchQueue()
|
||||
|
||||
this.dispatchTimer = window.setTimeout(() => {
|
||||
this.dispatch()
|
||||
this.setState({
|
||||
isDispatchQueued: false
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
|
||||
dispatch () {
|
||||
let { note } = this.state
|
||||
note = Object.assign({}, note)
|
||||
let repoKey = note._repository.key
|
||||
note.title = this.findTitle(note.content)
|
||||
|
||||
let { dispatch } = this.props
|
||||
dispatch({
|
||||
type: 'SAVE_NOTE',
|
||||
repository: repoKey,
|
||||
note: note
|
||||
})
|
||||
queue.save(repoKey, note)
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='NoteDetail'
|
||||
style={this.props.style}
|
||||
styleName='root'
|
||||
>
|
||||
<div styleName='info'>
|
||||
<div styleName='info-left'>
|
||||
<div styleName='info-left-folderSelect'>FOLDER SELECT</div>
|
||||
<div styleName='info-left-tagSelect'>TAG SELECT</div>
|
||||
</div>
|
||||
<div styleName='info-right'>
|
||||
<button styleName='info-right-button'>
|
||||
<i className='fa fa-clipboard fa-fw'/>
|
||||
</button>
|
||||
<button styleName='info-right-button'>
|
||||
<i className='fa fa-share-alt fa-fw'/>
|
||||
</button>
|
||||
<button styleName='info-right-button'>
|
||||
<i className='fa fa-ellipsis-v'/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div styleName='body'>
|
||||
<MarkdownEditor
|
||||
ref='content'
|
||||
styleName='body-noteEditor'
|
||||
value={this.state.note.content}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
ignorePreviewPointerEvents={this.props.ignorePreviewPointerEvents}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
NoteDetail.propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
repositories: PropTypes.array,
|
||||
style: PropTypes.shape({
|
||||
left: PropTypes.number
|
||||
}),
|
||||
ignorePreviewPointerEvents: PropTypes.bool
|
||||
}
|
||||
|
||||
export default CSSModules(NoteDetail, styles)
|
||||
38
browser/main/Detail/NoteDetail.styl
Normal file
38
browser/main/Detail/NoteDetail.styl
Normal file
@@ -0,0 +1,38 @@
|
||||
.root
|
||||
absolute top bottom right
|
||||
border-width 1px 0
|
||||
border-style solid
|
||||
border-color $ui-borderColor
|
||||
|
||||
.info
|
||||
absolute top left right
|
||||
height 50px
|
||||
border-bottom $ui-border
|
||||
background-color $ui-backgroundColor
|
||||
|
||||
.info-left
|
||||
float left
|
||||
|
||||
.info-right
|
||||
float right
|
||||
|
||||
.info-right-button
|
||||
width 34px
|
||||
height 34px
|
||||
border-radius 17px
|
||||
navButtonColor()
|
||||
border $ui-border
|
||||
font-size 14px
|
||||
margin 8px 2px
|
||||
padding 0
|
||||
&:active
|
||||
border-color $ui-button--active-backgroundColor
|
||||
&:hover .left-control-newPostButton-tooltip
|
||||
display block
|
||||
|
||||
.body
|
||||
absolute bottom left right
|
||||
top 50px
|
||||
|
||||
.body-noteEditor
|
||||
absolute top bottom left right
|
||||
65
browser/main/Detail/index.js
Normal file
65
browser/main/Detail/index.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './Detail.styl'
|
||||
import _ from 'lodash'
|
||||
import NoteDetail from './NoteDetail'
|
||||
|
||||
const electron = require('electron')
|
||||
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
|
||||
class Detail extends React.Component {
|
||||
componentDidUpdate (prevProps, prevState) {
|
||||
}
|
||||
|
||||
render () {
|
||||
let { repositories, location } = this.props
|
||||
let note = null
|
||||
if (location.query.key != null) {
|
||||
let splitted = location.query.key.split('-')
|
||||
let repoKey = splitted.shift()
|
||||
let noteKey = splitted.shift()
|
||||
let repo = _.find(repositories, {key: repoKey})
|
||||
if (_.isObject(repo) && _.isArray(repo.notes)) {
|
||||
note = _.find(repo.notes, {key: noteKey})
|
||||
}
|
||||
}
|
||||
|
||||
if (note == null) {
|
||||
return (
|
||||
<div className='Detail'
|
||||
style={this.props.style}
|
||||
styleName='root'
|
||||
tabIndex='0'
|
||||
>
|
||||
<div styleName='empty'>
|
||||
<div styleName='empty-message'>{OSX ? 'Command(⌘)' : 'Ctrl(^)'} + N<br/>to create a new post</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<NoteDetail
|
||||
note={note}
|
||||
{..._.pick(this.props, [
|
||||
'dispatch',
|
||||
'repositories',
|
||||
'style',
|
||||
'ignorePreviewPointerEvents'
|
||||
])}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Detail.propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
repositories: PropTypes.array,
|
||||
style: PropTypes.shape({
|
||||
left: PropTypes.number
|
||||
}),
|
||||
ignorePreviewPointerEvents: PropTypes.bool
|
||||
}
|
||||
|
||||
export default CSSModules(Detail, styles)
|
||||
Reference in New Issue
Block a user