mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Merge pull request #692 from asmsuechan/add-info-button
Add info button
This commit is contained in:
@@ -8,7 +8,7 @@ import moment from 'moment'
|
|||||||
* @param {mixed}
|
* @param {mixed}
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
export function getLastUpdated (date) {
|
export function formatDate (date) {
|
||||||
const m = moment(date)
|
const m = moment(date)
|
||||||
if (!m.isValid()) {
|
if (!m.isValid()) {
|
||||||
throw Error('Invalid argument.')
|
throw Error('Invalid argument.')
|
||||||
|
|||||||
19
browser/main/Detail/InfoButton.js
Normal file
19
browser/main/Detail/InfoButton.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import React, { PropTypes } from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './InfoButton.styl'
|
||||||
|
|
||||||
|
const InfoButton = ({
|
||||||
|
onClick
|
||||||
|
}) => (
|
||||||
|
<button styleName='control-infoButton'
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
<i className='fa fa-info-circle infoButton' styleName='info-button' />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
InfoButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(InfoButton, styles)
|
||||||
18
browser/main/Detail/InfoButton.styl
Normal file
18
browser/main/Detail/InfoButton.styl
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.control-infoButton
|
||||||
|
float right
|
||||||
|
topBarButtonLight()
|
||||||
|
|
||||||
|
.control-infoPanel
|
||||||
|
position fixed
|
||||||
|
pointer-events none
|
||||||
|
top 50px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.control-infoButton
|
||||||
|
topBarButtonDark()
|
||||||
62
browser/main/Detail/InfoPanel.js
Normal file
62
browser/main/Detail/InfoPanel.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import React, { PropTypes } from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './InfoPanel.styl'
|
||||||
|
|
||||||
|
const InfoPanel = ({
|
||||||
|
storageName, folderName, noteKey, updatedAt, createdAt
|
||||||
|
}) => (
|
||||||
|
<div className='infoPanel' styleName='control-infoButton-panel' style={{display: 'none'}}>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
Storage
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
{storageName}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
Folder
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
{folderName}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
CreatedAt
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
{createdAt}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
UpdatedAt
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
{updatedAt}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
Note Link
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input value={noteKey} onClick={(e) => { e.target.select() }} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div styleName='group-export' />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
InfoPanel.propTypes = {
|
||||||
|
storageName: PropTypes.string.isRequired,
|
||||||
|
folderName: PropTypes.string.isRequired,
|
||||||
|
noteKey: PropTypes.string.isRequired,
|
||||||
|
updatedAt: PropTypes.string.isRequired,
|
||||||
|
createdAt: PropTypes.string.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(InfoPanel, styles)
|
||||||
44
browser/main/Detail/InfoPanel.styl
Normal file
44
browser/main/Detail/InfoPanel.styl
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
.control-infoPanel
|
||||||
|
position fixed
|
||||||
|
pointer-events none
|
||||||
|
top 50px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
.control-infoButton-panel
|
||||||
|
z-index 200
|
||||||
|
margin-top 60px
|
||||||
|
margin-left -160px
|
||||||
|
position absolute
|
||||||
|
padding 10px
|
||||||
|
padding-left 15px
|
||||||
|
width 300px
|
||||||
|
background-color #EAEAEA
|
||||||
|
border 1px solid #d0d0d0
|
||||||
|
box-shadow 0 0 1px rgba(76,86,103,0.15), 0 2px 18px rgba(31,37,50,0.22)
|
||||||
|
|
||||||
|
.group-section
|
||||||
|
display flex
|
||||||
|
line-height 30px
|
||||||
|
font-size 12px
|
||||||
|
|
||||||
|
.group-section-label
|
||||||
|
width 70px
|
||||||
|
height 20px
|
||||||
|
text-align left
|
||||||
|
margin-right 30px
|
||||||
|
font-size 11px
|
||||||
|
color #939395
|
||||||
|
|
||||||
|
.group-section-control
|
||||||
|
flex 1
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.control-infoButton-panel
|
||||||
|
background-color #3a404c
|
||||||
|
border 1px solid #474f5c
|
||||||
|
color #ffffff
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @fileoverview Component for show updated date of the detail.
|
* @fileoverview Component for show updated date of the detail.
|
||||||
*/
|
*/
|
||||||
import React, { PropTypes } from 'react'
|
import React, { PropTypes } from 'react'
|
||||||
import { getLastUpdated } from 'browser/lib/date-formatter'
|
import { formatDate } from 'browser/lib/date-formatter'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './LastUpdatedString.styl'
|
import styles from './LastUpdatedString.styl'
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ const LastUpdatedString = ({ date }) => {
|
|||||||
let text = ''
|
let text = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
text = `Last updated at ${getLastUpdated(date)}`
|
text = `Last updated at ${formatDate(date)}`
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
text = ''
|
text = ''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import _ from 'lodash'
|
|||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
|
import InfoButton from './InfoButton'
|
||||||
|
import InfoPanel from './InfoPanel'
|
||||||
|
import { formatDate } from 'browser/lib/date-formatter'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote } = electron
|
const { remote } = electron
|
||||||
@@ -229,9 +232,27 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
this.focus()
|
this.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleInfoButtonClick (e) {
|
||||||
|
const infoPanel = document.querySelector('.infoPanel')
|
||||||
|
if (infoPanel.style) infoPanel.style.display = infoPanel.style.display === 'none' ? 'inline' : 'none'
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { data, config } = this.props
|
let { data, config, location } = this.props
|
||||||
let { note } = this.state
|
let { note } = this.state
|
||||||
|
let storageKey = note.storage
|
||||||
|
let folderKey = note.folder
|
||||||
|
|
||||||
|
let options = []
|
||||||
|
data.storageMap.forEach((storage, index) => {
|
||||||
|
storage.folders.forEach((folder) => {
|
||||||
|
options.push({
|
||||||
|
storage: storage,
|
||||||
|
folder: folder
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
let currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='NoteDetail'
|
<div className='NoteDetail'
|
||||||
@@ -287,6 +308,16 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
>
|
>
|
||||||
<i className='fa fa-expand' styleName='fullScreen-button' />
|
<i className='fa fa-expand' styleName='fullScreen-button' />
|
||||||
</button>
|
</button>
|
||||||
|
<InfoButton
|
||||||
|
onClick={(e) => this.handleInfoButtonClick(e)}
|
||||||
|
/>
|
||||||
|
<InfoPanel
|
||||||
|
storageName={currentOption.storage.name}
|
||||||
|
folderName={currentOption.folder.name}
|
||||||
|
noteKey={location.query.key}
|
||||||
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
|
createdAt={formatDate(note.createdAt)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ document.addEventListener('dragover', function (e) {
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
document.addEventListener('click', function (e) {
|
||||||
|
const isInfoButton = e.target.className.includes('infoButton')
|
||||||
|
const isInfoPanel = e.target.offsetParent.className.includes('infoPanel')
|
||||||
|
if (isInfoButton || isInfoPanel) return
|
||||||
|
const infoPanel = document.querySelector('.infoPanel')
|
||||||
|
if (infoPanel) infoPanel.style.display = 'none'
|
||||||
|
})
|
||||||
|
|
||||||
let el = document.getElementById('content')
|
let el = document.getElementById('content')
|
||||||
const history = syncHistoryWithStore(hashHistory, store)
|
const history = syncHistoryWithStore(hashHistory, store)
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
* @fileoverview Unit test for browser/lib/date-formatter.js
|
* @fileoverview Unit test for browser/lib/date-formatter.js
|
||||||
*/
|
*/
|
||||||
const test = require('ava')
|
const test = require('ava')
|
||||||
const { getLastUpdated } = require('browser/lib/date-formatter')
|
const { formatDate } = require('browser/lib/date-formatter')
|
||||||
|
|
||||||
test(t => {
|
test(t => {
|
||||||
t.throws(
|
t.throws(
|
||||||
() => getLastUpdated('invalid argument'),
|
() => formatDate('invalid argument'),
|
||||||
'Invalid argument.'
|
'Invalid argument.'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user