@@ -4,10 +4,11 @@ import { findWhere, uniq } from 'lodash'
44import ModeIcon from 'boost/components/ModeIcon'
55import MarkdownPreview from 'boost/components/MarkdownPreview'
66import CodeEditor from 'boost/components/CodeEditor'
7- import { NEW , IDLE_MODE , CREATE_MODE , EDIT_MODE , switchMode } from '../actions'
7+ import { UNSYNCED , IDLE_MODE , CREATE_MODE , EDIT_MODE , switchMode , switchArticle , updateArticle , destroyArticle } from '../actions'
88import aceModes from 'boost/ace-modes'
99import Select from 'react-select'
1010import linkState from 'boost/linkState'
11+ import api from 'boost/api'
1112
1213var modeOptions = aceModes . map ( function ( mode ) {
1314 return {
@@ -16,16 +17,27 @@ var modeOptions = aceModes.map(function (mode) {
1617 }
1718} )
1819
20+ function makeInstantArticle ( article ) {
21+ let instantArticle = Object . assign ( { } , article )
22+ instantArticle . Tags = instantArticle . Tags . map ( tag => tag . name )
23+ return instantArticle
24+ }
25+
1926export default class ArticleDetail extends React . Component {
2027 constructor ( props ) {
2128 super ( props )
29+
2230 this . state = {
23- article : Object . assign ( { } , props . activeArticle )
31+ article : makeInstantArticle ( props . activeArticle )
2432 }
2533 }
2634
2735 componentWillReceiveProps ( nextProps ) {
28- this . setState ( { article : nextProps . activeArticle } )
36+ if ( nextProps . activeArticle != null && nextProps . activeArticle . id !== this . state . article . id ) {
37+ this . setState ( { article : makeInstantArticle ( nextProps . activeArticle ) } , function ( ) {
38+ console . log ( 'receive props' )
39+ } )
40+ }
2941 }
3042
3143 renderEmpty ( ) {
@@ -36,12 +48,46 @@ export default class ArticleDetail extends React.Component {
3648 )
3749 }
3850
51+ handleEditButtonClick ( e ) {
52+ let { dispatch } = this . props
53+ dispatch ( switchMode ( EDIT_MODE ) )
54+ }
55+
56+ handleDeleteButtonClick ( e ) {
57+ this . setState ( { openDeleteConfirmMenu : true } )
58+ }
59+
60+ handleDeleteConfirmButtonClick ( e ) {
61+ let { dispatch, activeUser, activeArticle } = this . props
62+
63+ api . destroyArticle ( activeArticle . id )
64+ . then ( res => {
65+ console . log ( res . body )
66+ } )
67+ . catch ( err => {
68+ // connect failed need to queue data
69+ if ( err . code === 'ECONNREFUSED' ) {
70+ return
71+ }
72+
73+ if ( err . status != null ) throw err
74+ else console . log ( err )
75+ } )
76+
77+ dispatch ( destroyArticle ( activeUser . id , activeArticle . id ) )
78+ this . setState ( { openDeleteConfirmMenu : false } )
79+ }
80+
81+ handleDeleteCancleButtonClick ( e ) {
82+ this . setState ( { openDeleteConfirmMenu : false } )
83+ }
84+
3985 renderIdle ( ) {
40- let { status , activeArticle, activeUser } = this . props
86+ let { activeArticle, activeUser } = this . props
4187
4288 let tags = activeArticle . Tags . length > 0 ? activeArticle . Tags . map ( tag => {
4389 return (
44- < a key = { tag . id } > { tag . name } </ a >
90+ < a key = { tag . name } > { tag . name } </ a >
4591 )
4692 } ) : (
4793 < span className = 'noTags' > Not tagged yet</ span >
@@ -50,24 +96,37 @@ export default class ArticleDetail extends React.Component {
5096 let folderName = folder != null ? folder . name : '(unknown)'
5197
5298 return (
53- < div className = 'ArticleDetail show' >
54- < div className = 'detailInfo' >
55- < div className = 'left' >
56- < div className = 'info' >
57- < i className = 'fa fa-fw fa-square' /> { folderName }
58- by { activeArticle . User . profileName }
59- Created { moment ( activeArticle . createdAt ) . format ( 'YYYY/MM/DD' ) }
60- Updated { moment ( activeArticle . updatedAt ) . format ( 'YYYY/MM/DD' ) }
99+ < div className = 'ArticleDetail idle' >
100+ { this . state . openDeleteConfirmMenu
101+ ? (
102+ < div className = 'deleteConfirm' >
103+ < div className = 'right' >
104+ Are you sure to delete this article?
105+ < button onClick = { e => this . handleDeleteConfirmButtonClick ( e ) } className = 'primary' > < i className = 'fa fa-fw fa-check' /> Sure</ button >
106+ < button onClick = { e => this . handleDeleteCancleButtonClick ( e ) } > < i className = 'fa fa-fw fa-times' /> Cancle</ button >
107+ </ div >
61108 </ div >
62- < div className = 'tags' > < i className = 'fa fa-fw fa-tags' /> { tags } </ div >
63- </ div >
109+ )
110+ : (
111+ < div className = 'detailInfo' >
112+ < div className = 'left' >
113+ < div className = 'info' >
114+ < i className = 'fa fa-fw fa-square' /> { folderName }
115+ by { activeArticle . User . profileName }
116+ Created { moment ( activeArticle . createdAt ) . format ( 'YYYY/MM/DD' ) }
117+ Updated { moment ( activeArticle . updatedAt ) . format ( 'YYYY/MM/DD' ) }
118+ </ div >
119+ < div className = 'tags' > < i className = 'fa fa-fw fa-tags' /> { tags } </ div >
120+ </ div >
121+ < div className = 'right' >
122+ < button onClick = { e => this . handleEditButtonClick ( e ) } > < i className = 'fa fa-fw fa-edit' /> </ button >
123+ < button onClick = { e => this . handleDeleteButtonClick ( e ) } > < i className = 'fa fa-fw fa-trash' /> </ button >
124+ < button > < i className = 'fa fa-fw fa-share-alt' /> </ button >
125+ </ div >
126+ </ div >
127+ )
128+ }
64129
65- < div className = 'right' >
66- < button > < i className = 'fa fa-fw fa-edit' /> </ button >
67- < button > < i className = 'fa fa-fw fa-trash' /> </ button >
68- < button > < i className = 'fa fa-fw fa-share-alt' /> </ button >
69- </ div >
70- </ div >
71130 < div className = 'detailBody' >
72131 < div className = 'detailPanel' >
73132 < div className = 'header' >
@@ -86,7 +145,67 @@ export default class ArticleDetail extends React.Component {
86145 }
87146
88147 handleSaveButtonClick ( e ) {
89- console . log ( this . state . article )
148+ let { activeArticle } = this . props
149+
150+ if ( typeof activeArticle . id === 'string' ) this . saveAsNew ( )
151+ else this . save ( )
152+ }
153+
154+ saveAsNew ( ) {
155+ let { dispatch, activeUser } = this . props
156+ let article = this . state . article
157+ let newArticle = Object . assign ( { } , article )
158+ article . tags = article . Tags
159+
160+ api . createArticle ( article )
161+ . then ( res => {
162+ console . log ( res . body )
163+ } )
164+ . catch ( err => {
165+ // connect failed need to queue data
166+ if ( err . code === 'ECONNREFUSED' ) {
167+ return
168+ }
169+
170+ if ( err . status != null ) throw err
171+ else console . log ( err )
172+ } )
173+
174+ newArticle . status = UNSYNCED
175+ newArticle . Tags = newArticle . Tags . map ( tag => { return { name : tag } } )
176+
177+ dispatch ( updateArticle ( activeUser . id , newArticle ) )
178+ dispatch ( switchMode ( IDLE_MODE ) )
179+ dispatch ( switchArticle ( article . id ) )
180+ }
181+
182+ save ( ) {
183+ let { dispatch, activeUser } = this . props
184+ let article = this . state . article
185+ let newArticle = Object . assign ( { } , article )
186+
187+ article . tags = article . Tags
188+
189+ api . saveArticle ( article )
190+ . then ( res => {
191+ console . log ( res . body )
192+ } )
193+ . catch ( err => {
194+ // connect failed need to queue data
195+ if ( err . code === 'ECONNREFUSED' ) {
196+ return
197+ }
198+
199+ if ( err . status != null ) throw err
200+ else console . log ( err )
201+ } )
202+
203+ newArticle . status = UNSYNCED
204+ newArticle . Tags = newArticle . Tags . map ( tag => { return { name : tag } } )
205+
206+ dispatch ( updateArticle ( activeUser . id , newArticle ) )
207+ dispatch ( switchMode ( IDLE_MODE ) )
208+ dispatch ( switchArticle ( article . id ) )
90209 }
91210
92211 handleFolderIdChange ( value ) {
@@ -121,7 +240,7 @@ export default class ArticleDetail extends React.Component {
121240 }
122241
123242 renderEdit ( ) {
124- let { status , activeUser } = this . props
243+ let { activeUser } = this . props
125244
126245 let folderOptions = activeUser . Folders . map ( folder => {
127246 return {
@@ -146,7 +265,7 @@ export default class ArticleDetail extends React.Component {
146265 < div className = 'detailPanel' >
147266 < div className = 'header' >
148267 < div className = 'title' >
149- < input ref = 'title' valueLink = { this . linkState ( 'article.title' ) } />
268+ < input placeholder = 'Title' ref = 'title' valueLink = { this . linkState ( 'article.title' ) } />
150269 </ div >
151270 < Select ref = 'mode' onChange = { value => this . handleModeChange ( value ) } clearable = { false } options = { modeOptions } placeholder = 'select mode...' value = { this . state . article . mode } className = 'mode' />
152271 </ div >
0 commit comments