import React, { PropTypes } from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './StorageItem.styl' import { hashHistory } from 'react-router' import modal from 'browser/main/lib/modal' import CreateFolderModal from 'browser/main/modals/CreateFolderModal' import RenameFolderModal from 'browser/main/modals/RenameFolderModal' import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import eventEmitter from 'browser/main/lib/eventEmitter' const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote class StorageItem extends React.Component { constructor (props) { super(props) this.state = { isOpen: true } } handleHeaderContextMenu (e) { let menu = new Menu() menu.append(new MenuItem({ label: 'Add Folder', click: (e) => this.handleAddFolderButtonClick(e) })) menu.append(new MenuItem({ type: 'separator' })) menu.append(new MenuItem({ label: 'Unlink Storage', click: (e) => this.handleUnlinkStorageClick(e) })) menu.popup() } handleUnlinkStorageClick (e) { let index = dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', message: 'Unlink Storage', detail: 'This work will just detatches a storage from Boostnote. (Any data won\'t be deleted.)', buttons: ['Confirm', 'Cancel'] }) if (index === 0) { let { storage, dispatch } = this.props dataApi.removeStorage(storage.key) .then(() => { dispatch({ type: 'REMOVE_STORAGE', storageKey: storage.key }) }) .catch((err) => { throw err }) } } handleToggleButtonClick (e) { this.setState({ isOpen: !this.state.isOpen }) } handleAddFolderButtonClick (e) { let { storage } = this.props modal.open(CreateFolderModal, { storage }) } handleHeaderInfoClick (e) { let { storage } = this.props hashHistory.push('/storages/' + storage.key) } handleFolderButtonClick (folderKey) { return (e) => { let { storage } = this.props hashHistory.push('/storages/' + storage.key + '/folders/' + folderKey) } } handleFolderButtonContextMenu (e, folder) { let menu = new Menu() menu.append(new MenuItem({ label: 'Rename Folder', click: (e) => this.handleRenameFolderClick(e, folder) })) menu.append(new MenuItem({ type: 'separator' })) menu.append(new MenuItem({ label: 'Delete Folder', click: (e) => this.handleFolderDeleteClick(e, folder) })) menu.popup() } handleRenameFolderClick (e, folder) { let { storage } = this.props modal.open(RenameFolderModal, { storage, folder }) } handleFolderDeleteClick (e, folder) { let index = dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', message: 'Delete Folder', detail: 'This work will deletes all notes in the folder and can not be undone.', buttons: ['Confirm', 'Cancel'] }) if (index === 0) { let { storage, dispatch } = this.props dataApi .deleteFolder(storage.key, folder.key) .then((data) => { dispatch({ type: 'DELETE_FOLDER', storage: data.storage, folderKey: data.folderKey }) }) } } handleDragEnter (e) { e.dataTransfer.setData('defaultColor', e.target.style.backgroundColor) e.target.style.backgroundColor = 'rgba(129, 130, 131, 0.08)' } handleDragLeave (e) { e.target.style.opacity = '1' e.target.style.backgroundColor = e.dataTransfer.getData('defaultColor') } handleDrop (e, storage, folder, dispatch, location) { e.target.style.opacity = '1' e.target.style.backgroundColor = e.dataTransfer.getData('defaultColor') const noteData = JSON.parse(e.dataTransfer.getData('note')) const newNoteData = Object.assign({}, noteData, {storage: storage, folder: folder.key}) if (folder.key === noteData.folder) return dataApi .createNote(storage.key, newNoteData) .then((note) => { dataApi .deleteNote(noteData.storage, noteData.key) .then((data) => { let dispatchHandler = () => { dispatch({ type: 'DELETE_NOTE', storageKey: data.storageKey, noteKey: data.noteKey }) } eventEmitter.once('list:moved', dispatchHandler) eventEmitter.emit('list:next') }) .catch((err) => { console.error(err) }) dispatch({ type: 'UPDATE_NOTE', note: note }) hashHistory.push({ pathname: location.pathname, query: {key: `${note.storage}-${note.key}`} }) }) } render () { let { storage, location, isFolded, data, dispatch } = this.props let { folderNoteMap } = data let folderList = storage.folders.map((folder) => { let isActive = !!(location.pathname.match(new RegExp('\/storages\/' + storage.key + '\/folders\/' + folder.key))) let noteSet = folderNoteMap.get(storage.key + '-' + folder.key) let noteCount = noteSet != null ? noteSet.size : 0 return ( this.handleFolderButtonClick(folder.key)(e)} handleContextMenu={(e) => this.handleFolderButtonContextMenu(e, folder)} folderName={folder.name} folderColor={folder.color} isFolded={isFolded} noteCount={noteCount} handleDrop={(e) => this.handleDrop(e, storage, folder, dispatch, location)} handleDragEnter={this.handleDragEnter} handleDragLeave={this.handleDragLeave} /> ) }) let isActive = location.pathname.match(new RegExp('\/storages\/' + storage.key + '$')) return (
this.handleHeaderContextMenu(e)} > {!isFolded && }
{this.state.isOpen &&
{folderList}
}
) } } StorageItem.propTypes = { isFolded: PropTypes.bool } export default CSSModules(StorageItem, styles)