mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Add pinn to top
This commit is contained in:
@@ -72,6 +72,9 @@ const NoteItem = ({ isActive, note, dateDisplay, handleNoteClick, handleNoteCont
|
|||||||
{note.isStarred
|
{note.isStarred
|
||||||
? <i styleName='item-star' className='fa fa-star' /> : ''
|
? <i styleName='item-star' className='fa fa-star' /> : ''
|
||||||
}
|
}
|
||||||
|
{note.isPinned
|
||||||
|
? <i styleName='item-pin' className='fa fa-map-pin' /> : ''
|
||||||
|
}
|
||||||
{note.type === 'MARKDOWN_NOTE'
|
{note.type === 'MARKDOWN_NOTE'
|
||||||
? <TodoProcess todoStatus={getTodoStatus(note.content)} />
|
? <TodoProcess todoStatus={getTodoStatus(note.content)} />
|
||||||
: ''
|
: ''
|
||||||
@@ -101,6 +104,7 @@ NoteItem.propTypes = {
|
|||||||
isTrashed: PropTypes.bool.isRequired
|
isTrashed: PropTypes.bool.isRequired
|
||||||
}),
|
}),
|
||||||
handleNoteClick: PropTypes.func.isRequired,
|
handleNoteClick: PropTypes.func.isRequired,
|
||||||
|
handleNoteContextMenu: PropTypes.func.isRequired,
|
||||||
handleDragStart: PropTypes.func.isRequired,
|
handleDragStart: PropTypes.func.isRequired,
|
||||||
handleDragEnd: PropTypes.func.isRequired
|
handleDragEnd: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { hashHistory } from 'react-router'
|
|||||||
import markdown from 'browser/lib/markdown'
|
import markdown from 'browser/lib/markdown'
|
||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import stripgtags from 'striptags'
|
import stripgtags from 'striptags'
|
||||||
|
import store from 'browser/main/store'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { Menu, MenuItem, dialog } = remote
|
const { Menu, MenuItem, dialog } = remote
|
||||||
@@ -283,6 +284,21 @@ class NoteList extends React.Component {
|
|||||||
return folderNoteKeyList.map((uniqueKey) => data.noteMap.get(uniqueKey))
|
return folderNoteKeyList.map((uniqueKey) => data.noteMap.get(uniqueKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortByPinn (unorderedNotes) {
|
||||||
|
const { data, params } = this.props
|
||||||
|
let storageKey = params.storageKey
|
||||||
|
let folderKey = params.folderKey
|
||||||
|
let storage = data.storageMap.get(storageKey)
|
||||||
|
if (storage == null) return []
|
||||||
|
|
||||||
|
let folder = _.find(storage.folders, {key: folderKey})
|
||||||
|
const pinnedNotes = unorderedNotes.filter((el) => {
|
||||||
|
return folder.pinnedNotes && folder.pinnedNotes.includes(el.key)
|
||||||
|
})
|
||||||
|
|
||||||
|
return pinnedNotes.concat(unorderedNotes)
|
||||||
|
}
|
||||||
|
|
||||||
handleNoteClick (e, uniqueKey) {
|
handleNoteClick (e, uniqueKey) {
|
||||||
let { router } = this.context
|
let { router } = this.context
|
||||||
let { location } = this.props
|
let { location } = this.props
|
||||||
@@ -413,6 +429,56 @@ class NoteList extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNoteContextMenu (e, uniqueKey) {
|
||||||
|
let menu = new Menu()
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
label: 'Pin to Top',
|
||||||
|
click: (e) => this.handlePinToTop(e, uniqueKey)
|
||||||
|
}))
|
||||||
|
menu.popup()
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePinToTop (e, uniqueKey) {
|
||||||
|
const { data, location } = this.props
|
||||||
|
let splitted = location.pathname.split('/')
|
||||||
|
const storageKey = splitted[2]
|
||||||
|
const folderKey = splitted[4]
|
||||||
|
|
||||||
|
const currentStorage = data.storageMap.get(storageKey)
|
||||||
|
const currentFolder = _.find(currentStorage.folders, {key: folderKey})
|
||||||
|
|
||||||
|
dataApi
|
||||||
|
.updateFolder(storageKey, folderKey, {
|
||||||
|
color: currentFolder.color,
|
||||||
|
name: currentFolder.name,
|
||||||
|
pinnedNote: uniqueKey.split('-').pop()
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'UPDATE_FOLDER',
|
||||||
|
storage: data.storage
|
||||||
|
})
|
||||||
|
this.setState({
|
||||||
|
status: 'IDLE'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let targetIndex = _.findIndex(this.notes, (note) => {
|
||||||
|
return note != null && note.storage + '-' + note.key === location.query.key
|
||||||
|
})
|
||||||
|
let note = this.notes[targetIndex]
|
||||||
|
|
||||||
|
dataApi
|
||||||
|
.updateNote(note.storage, note.key, note)
|
||||||
|
.then((note) => {
|
||||||
|
note.isPinned = true
|
||||||
|
store.dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: note
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { location, notes, config, dispatch } = this.props
|
let { location, notes, config, dispatch } = this.props
|
||||||
let sortFunc = config.sortBy === 'CREATED_AT'
|
let sortFunc = config.sortBy === 'CREATED_AT'
|
||||||
@@ -420,8 +486,8 @@ class NoteList extends React.Component {
|
|||||||
: config.sortBy === 'ALPHABETICAL'
|
: config.sortBy === 'ALPHABETICAL'
|
||||||
? sortByAlphabetical
|
? sortByAlphabetical
|
||||||
: sortByUpdatedAt
|
: sortByUpdatedAt
|
||||||
this.notes = notes = this.getNotes()
|
const sortedNotes = this.getNotes().sort(sortFunc)
|
||||||
.sort(sortFunc)
|
this.notes = notes = this.sortByPinn(sortedNotes)
|
||||||
.filter((note) => {
|
.filter((note) => {
|
||||||
// this is for the trash box
|
// this is for the trash box
|
||||||
if (note.isTrashed !== true || location.pathname === '/trashed') return true
|
if (note.isTrashed !== true || location.pathname === '/trashed') return true
|
||||||
@@ -450,6 +516,7 @@ class NoteList extends React.Component {
|
|||||||
key={key}
|
key={key}
|
||||||
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
|
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
|
||||||
handleNoteClick={this.handleNoteClick.bind(this)}
|
handleNoteClick={this.handleNoteClick.bind(this)}
|
||||||
|
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
|
||||||
handleDragStart={this.handleDragStart.bind(this)}
|
handleDragStart={this.handleDragStart.bind(this)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -526,4 +593,4 @@ NoteList.propTypes = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(NoteList, styles)
|
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ function createFolder (storageKey, input) {
|
|||||||
let newFolder = {
|
let newFolder = {
|
||||||
key,
|
key,
|
||||||
color: input.color,
|
color: input.color,
|
||||||
name: input.name
|
name: input.name,
|
||||||
|
pinnedNotes: []
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.folders.push(newFolder)
|
storage.folders.push(newFolder)
|
||||||
|
|||||||
@@ -44,6 +44,12 @@ function updateFolder (storageKey, folderKey, input) {
|
|||||||
if (targetFolder == null) throw new Error('Target folder doesn\'t exist.')
|
if (targetFolder == null) throw new Error('Target folder doesn\'t exist.')
|
||||||
targetFolder.name = input.name
|
targetFolder.name = input.name
|
||||||
targetFolder.color = input.color
|
targetFolder.color = input.color
|
||||||
|
// For compativility
|
||||||
|
if (targetFolder.pinnedNotes) {
|
||||||
|
targetFolder.pinnedNotes.push(input.pinnedNote)
|
||||||
|
} else {
|
||||||
|
targetFolder.pinnedNotes = [input.pinnedNote]
|
||||||
|
}
|
||||||
|
|
||||||
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
|
CSON.writeFileSync(path.join(storage.path, 'boostnote.json'), _.pick(storage, ['folders', 'version']))
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ function updateNote (storageKey, noteKey, input) {
|
|||||||
noteData.isStarred = false
|
noteData.isStarred = false
|
||||||
noteData.isTrashed = false
|
noteData.isTrashed = false
|
||||||
noteData.tags = []
|
noteData.tags = []
|
||||||
|
noteData.isPinned = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noteData.type === 'SNIPPET_NOTE') {
|
if (noteData.type === 'SNIPPET_NOTE') {
|
||||||
|
|||||||
Reference in New Issue
Block a user