@@ -2,6 +2,13 @@ import React, { PropTypes } from 'react'
22import CSSModules from 'browser/lib/CSSModules'
33import styles from './StorageItem.styl'
44import { hashHistory } from 'react-router'
5+ import modal from 'browser/main/lib/modal'
6+ import CreateFolderModal from 'browser/main/modals/CreateFolderModal'
7+ import RenameFolderModal from 'browser/main/modals/RenameFolderModal'
8+ import dataApi from 'browser/main/lib/dataApi'
9+
10+ const { remote } = require ( 'electron' )
11+ const { Menu, MenuItem, dialog } = remote
512
613class StorageItem extends React . Component {
714 constructor ( props ) {
@@ -12,12 +19,59 @@ class StorageItem extends React.Component {
1219 }
1320 }
1421
22+ handleHeaderContextMenu ( e ) {
23+ let menu = new Menu ( )
24+ menu . append ( new MenuItem ( {
25+ label : 'Add Folder' ,
26+ click : ( e ) => this . handleAddFolderButtonClick ( e )
27+ } ) )
28+ menu . append ( new MenuItem ( {
29+ type : 'separator'
30+ } ) )
31+ menu . append ( new MenuItem ( {
32+ label : 'Unlink Storage' ,
33+ click : ( e ) => this . handleUnlinkStorageClick ( e )
34+ } ) )
35+ menu . popup ( )
36+ }
37+
38+ handleUnlinkStorageClick ( e ) {
39+ let index = dialog . showMessageBox ( remote . getCurrentWindow ( ) , {
40+ type : 'warning' ,
41+ message : 'Unlink Storage' ,
42+ detail : 'This work will just detatches a storage from Boostnote. (Any data won\'t be deleted.)' ,
43+ buttons : [ 'Confirm' , 'Cancel' ]
44+ } )
45+
46+ if ( index === 0 ) {
47+ let { storage, dispatch } = this . props
48+ dataApi . removeStorage ( storage . key )
49+ . then ( ( ) => {
50+ dispatch ( {
51+ type : 'REMOVE_STORAGE' ,
52+ storageKey : storage . key
53+ } )
54+ } )
55+ . catch ( ( err ) => {
56+ throw err
57+ } )
58+ }
59+ }
60+
1561 handleToggleButtonClick ( e ) {
1662 this . setState ( {
1763 isOpen : ! this . state . isOpen
1864 } )
1965 }
2066
67+ handleAddFolderButtonClick ( e ) {
68+ let { storage } = this . props
69+
70+ modal . open ( CreateFolderModal , {
71+ storage
72+ } )
73+ }
74+
2175 handleHeaderInfoClick ( e ) {
2276 let { storage } = this . props
2377 hashHistory . push ( '/storages/' + storage . key )
@@ -30,22 +84,78 @@ class StorageItem extends React.Component {
3084 }
3185 }
3286
87+ handleFolderButtonContextMenu ( e , folder ) {
88+ let menu = new Menu ( )
89+ menu . append ( new MenuItem ( {
90+ label : 'Rename Folder' ,
91+ click : ( e ) => this . handleRenameFolderClick ( e , folder )
92+ } ) )
93+ menu . append ( new MenuItem ( {
94+ type : 'separator'
95+ } ) )
96+ menu . append ( new MenuItem ( {
97+ label : 'Delete Folder' ,
98+ click : ( e ) => this . handleFolderDeleteClick ( e , folder )
99+ } ) )
100+ menu . popup ( )
101+ }
102+
103+ handleRenameFolderClick ( e , folder ) {
104+ let { storage } = this . props
105+ modal . open ( RenameFolderModal , {
106+ storage,
107+ folder
108+ } )
109+ }
110+
111+ handleFolderDeleteClick ( e , folder ) {
112+ let index = dialog . showMessageBox ( remote . getCurrentWindow ( ) , {
113+ type : 'warning' ,
114+ message : 'Delete Folder' ,
115+ detail : 'This work will deletes all notes in the folder and can not be undone.' ,
116+ buttons : [ 'Confirm' , 'Cancel' ]
117+ } )
118+
119+ if ( index === 0 ) {
120+ let { storage, dispatch } = this . props
121+ dataApi
122+ . deleteFolder ( storage . key , folder . key )
123+ . then ( ( data ) => {
124+ dispatch ( {
125+ type : 'DELETE_FOLDER' ,
126+ storage : data . storage ,
127+ folderKey : data . folderKey
128+ } )
129+ } )
130+ }
131+ }
132+
33133 render ( ) {
34- let { storage, location, isFolded } = this . props
134+ let { storage, location, isFolded, data } = this . props
135+ let { folderNoteMap } = data
35136 let folderList = storage . folders . map ( ( folder ) => {
36137 let isActive = location . pathname . match ( new RegExp ( '\/storages\/' + storage . key + '\/folders\/' + folder . key ) )
138+ let noteSet = folderNoteMap . get ( storage . key + '-' + folder . key )
139+
140+ let noteCount = noteSet != null
141+ ? noteSet . size
142+ : 0
37143 return < button styleName = { isActive
38144 ? 'folderList-item--active'
39145 : 'folderList-item'
40146 }
41147 key = { folder . key }
42148 onClick = { ( e ) => this . handleFolderButtonClick ( folder . key ) ( e ) }
149+ onContextMenu = { ( e ) => this . handleFolderButtonContextMenu ( e , folder ) }
43150 >
44151 < span styleName = 'folderList-item-name'
45152 style = { { borderColor : folder . color } }
46153 >
47154 { isFolded ? folder . name . substring ( 0 , 1 ) : folder . name }
48155 </ span >
156+ { ! isFolded &&
157+ < span styleName = 'folderList-item-noteCount' > { noteCount } </ span >
158+ }
49159 { isFolded &&
50160 < span styleName = 'folderList-item-tooltip' >
51161 { folder . name }
@@ -61,9 +171,11 @@ class StorageItem extends React.Component {
61171 key = { storage . key }
62172 >
63173 < div styleName = { isActive
64- ? 'header--active'
65- : 'header'
66- } >
174+ ? 'header--active'
175+ : 'header'
176+ }
177+ onContextMenu = { ( e ) => this . handleHeaderContextMenu ( e ) }
178+ >
67179 < button styleName = 'header-toggleButton'
68180 onMouseDown = { ( e ) => this . handleToggleButtonClick ( e ) }
69181 >
@@ -73,21 +185,24 @@ class StorageItem extends React.Component {
73185 }
74186 />
75187 </ button >
188+
189+ { ! isFolded &&
190+ < button styleName = 'header-addFolderButton'
191+ onClick = { ( e ) => this . handleAddFolderButtonClick ( e ) }
192+ >
193+ < i className = 'fa fa-plus' />
194+ </ button >
195+ }
196+
76197 < button styleName = 'header-info'
77198 onClick = { ( e ) => this . handleHeaderInfoClick ( e ) }
78199 >
79200 < span styleName = 'header-info-name' >
80201 { isFolded ? storage . name . substring ( 0 , 1 ) : storage . name }
81202 </ span >
82- < span styleName = 'header-info-path' >
83- ({ storage . path } )
84- </ span >
85203 { isFolded &&
86204 < span styleName = 'header-info--folded-tooltip' >
87205 { storage . name }
88- < span styleName = 'header-info--folded-tooltip-path' >
89- ({ storage . path } )
90- </ span >
91206 </ span >
92207 }
93208 </ button >
0 commit comments