Skip to content

Commit 9d2b64e

Browse files
committed
CREATE_MODE(1/2)
1 parent 9a5e4b3 commit 9d2b64e

11 files changed

Lines changed: 226 additions & 70 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
node_modules/*
33
!node_modules/boost
44
Boost-darwin-x64/
5+
backup/

browser/main/HomePage.js

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import React, { PropTypes} from 'react'
22
import { connect } from 'react-redux'
3-
import { switchUser } from './actions'
3+
import { CREATE_MODE, IDLE_MODE, switchUser } from './actions'
44
import UserNavigator from './HomePage/UserNavigator'
55
import ArticleNavigator from './HomePage/ArticleNavigator'
66
import ArticleTopBar from './HomePage/ArticleTopBar'
77
import ArticleList from './HomePage/ArticleList'
88
import ArticleDetail from './HomePage/ArticleDetail'
9-
import { findWhere } from 'lodash'
10-
11-
// var AuthFilter = require('../Mixins/AuthFilter')
12-
// var KeyCaster = require('../Mixins/KeyCaster')
9+
import { findWhere, pick } from 'lodash'
10+
import keygen from 'boost/keygen'
11+
import { NEW } from './actions'
1312

1413
class HomeContainer extends React.Component {
1514
componentDidMount () {
@@ -27,15 +26,15 @@ class HomeContainer extends React.Component {
2726
}
2827

2928
render () {
30-
const { users, user, status, articles, article } = this.props
29+
const { dispatch, status, users, activeUser, articles, activeArticle } = this.props
3130

3231
return (
3332
<div className='HomeContainer'>
3433
<UserNavigator users={users} />
35-
<ArticleNavigator user={user} status={status}/>
34+
<ArticleNavigator dispatch={dispatch} activeUser={activeUser} status={status}/>
3635
<ArticleTopBar/>
37-
<ArticleList articles={articles} status={status}/>
38-
<ArticleDetail user={user} article={article} status={status}/>
36+
<ArticleList dispatch={dispatch} articles={articles} status={status} activeArticle={activeArticle}/>
37+
<ArticleDetail dispatch={dispatch} activeUser={activeUser} activeArticle={activeArticle} status={status}/>
3938
</div>
4039
)
4140
}
@@ -48,24 +47,48 @@ function remap (state) {
4847
let teams = Array.isArray(currentUser.Teams) ? currentUser.Teams : []
4948

5049
let users = [currentUser, ...teams]
51-
let user = findWhere(users, {id: parseInt(status.userId, 10)})
52-
if (user == null) user = users[0]
53-
let articles = state.articles['team-' + user.id]
54-
let article = findWhere(users, {id: status.articleId})
55-
if (article == null) article = articles[0]
50+
let activeUser = findWhere(users, {id: parseInt(status.userId, 10)})
51+
if (activeUser == null) activeUser = users[0]
52+
let articles = state.articles['team-' + activeUser.id]
53+
let activeArticle = findWhere(users, {id: status.articleId})
54+
if (activeArticle == null) activeArticle = articles[0]
55+
56+
if (status.mode === CREATE_MODE && activeUser.Folders.length > 0) {
57+
var newArticle = findWhere(articles, {status: 'NEW'})
58+
if (newArticle == null) {
59+
newArticle = {
60+
id: keygen(),
61+
title: '',
62+
content: '',
63+
mode: 'markdown',
64+
Tags: [],
65+
User: pick(currentUser, ['email', 'name', 'profileName']),
66+
FolderId: activeUser.Folders[0].id,
67+
status: NEW
68+
}
69+
articles.unshift(newArticle)
70+
}
71+
activeArticle = newArticle
72+
} else if (status.mode === CREATE_MODE) {
73+
status.mode = IDLE_MODE
74+
}
75+
if (status.mode !== CREATE_MODE && activeArticle != null && activeArticle.status === NEW) {
76+
articles.splice(articles.indexOf(activeArticle), 1)
77+
activeArticle = articles[0]
78+
}
5679

5780
return {
5881
users,
59-
user,
82+
activeUser,
6083
status,
6184
articles,
62-
article
85+
activeArticle
6386
}
6487
}
6588

6689
HomeContainer.propTypes = {
6790
users: PropTypes.array,
68-
user: PropTypes.object,
91+
activeUser: PropTypes.object,
6992
params: PropTypes.shape({
7093
userId: PropTypes.string
7194
}),
@@ -74,6 +97,7 @@ HomeContainer.propTypes = {
7497
folderId: PropTypes.number
7598
}),
7699
articles: PropTypes.array,
100+
activeArticle: PropTypes.shape(),
77101
dispatch: PropTypes.func
78102
}
79103

Lines changed: 136 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,52 @@
11
import React, { PropTypes } from 'react'
22
import moment from 'moment'
3-
import { findWhere } from 'lodash'
3+
import { findWhere, uniq } from 'lodash'
44
import ModeIcon from 'boost/components/ModeIcon'
55
import MarkdownPreview from 'boost/components/MarkdownPreview'
66
import CodeEditor from 'boost/components/CodeEditor'
7+
import { NEW, IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode } from '../actions'
8+
import aceModes from 'boost/ace-modes'
9+
import Select from 'react-select'
10+
import linkState from 'boost/linkState'
11+
12+
var modeOptions = aceModes.map(function (mode) {
13+
return {
14+
label: mode,
15+
value: mode
16+
}
17+
})
718

819
export default class ArticleDetail extends React.Component {
9-
render () {
10-
let { article, status, user } = this.props
20+
constructor (props) {
21+
super(props)
22+
this.state = {
23+
article: Object.assign({}, props.activeArticle)
24+
}
25+
}
1126

12-
let tags = article.Tags.length > 0 ? article.Tags.map(tag => {
27+
componentWillReceiveProps (nextProps) {
28+
this.setState({article: nextProps.activeArticle})
29+
}
30+
31+
renderEmpty () {
32+
return (
33+
<div className='ArticleDetail'>
34+
Empty article
35+
</div>
36+
)
37+
}
38+
39+
renderIdle () {
40+
let { status, activeArticle, activeUser } = this.props
41+
42+
let tags = activeArticle.Tags.length > 0 ? activeArticle.Tags.map(tag => {
1343
return (
1444
<a key={tag.id}>{tag.name}</a>
1545
)
1646
}) : (
1747
<span className='noTags'>Not tagged yet</span>
1848
)
19-
let folder = findWhere(user.Folders, {id: article.FolderId})
49+
let folder = findWhere(activeUser.Folders, {id: activeArticle.FolderId})
2050
let folderName = folder != null ? folder.name : '(unknown)'
2151

2252
return (
@@ -25,9 +55,9 @@ export default class ArticleDetail extends React.Component {
2555
<div className='left'>
2656
<div className='info'>
2757
<i className='fa fa-fw fa-square'/> {folderName}&nbsp;
28-
by {article.User.profileName}&nbsp;
29-
Created {moment(article.createdAt).format('YYYY/MM/DD')}&nbsp;
30-
Updated {moment(article.updatedAt).format('YYYY/MM/DD')}
58+
by {activeArticle.User.profileName}&nbsp;
59+
Created {moment(activeArticle.createdAt).format('YYYY/MM/DD')}&nbsp;
60+
Updated {moment(activeArticle.updatedAt).format('YYYY/MM/DD')}
3161
</div>
3262
<div className='tags'><i className='fa fa-fw fa-tags'/>{tags}</div>
3363
</div>
@@ -41,19 +71,112 @@ export default class ArticleDetail extends React.Component {
4171
<div className='detailBody'>
4272
<div className='detailPanel'>
4373
<div className='header'>
44-
<ModeIcon className='mode' mode={article.mode}/>
45-
<div className='title'>{article.title}</div>
74+
<ModeIcon className='mode' mode={activeArticle.mode}/>
75+
<div className='title'>{activeArticle.title}</div>
4676
</div>
47-
{article.mode === 'markdown' ? <MarkdownPreview content={article.content}/> : <CodeEditor readOnly={true} onChange={this.handleContentChange} mode={article.mode} code={article.content}/>}
77+
{activeArticle.mode === 'markdown' ? <MarkdownPreview content={activeArticle.content}/> : <CodeEditor readOnly={true} onChange={this.handleContentChange} mode={activeArticle.mode} code={activeArticle.content}/>}
4878
</div>
4979
</div>
5080
</div>
5181
)
5282
}
83+
84+
handleCancelButtonClick (e) {
85+
this.props.dispatch(switchMode(IDLE_MODE))
86+
}
87+
88+
handleSaveButtonClick (e) {
89+
console.log(this.state.article)
90+
}
91+
92+
handleFolderIdChange (value) {
93+
let article = this.state.article
94+
article.FolderId = value
95+
this.setState({article: article})
96+
}
97+
98+
handleTagsChange (tag, tags) {
99+
tags = uniq(tags, function (tag) {
100+
return tag.value
101+
})
102+
103+
var article = this.state.article
104+
article.Tags = tags.map(function (tag) {
105+
return tag.value
106+
})
107+
108+
this.setState({article: article})
109+
}
110+
111+
handleModeChange (value) {
112+
let article = this.state.article
113+
article.mode = value
114+
this.setState({article: article})
115+
}
116+
117+
handleContentChange (e, value) {
118+
let article = this.state.article
119+
article.content = value
120+
this.setState({article: article})
121+
}
122+
123+
renderEdit () {
124+
let { status, activeUser } = this.props
125+
126+
let folderOptions = activeUser.Folders.map(folder => {
127+
return {
128+
label: folder.name,
129+
value: folder.id
130+
}
131+
})
132+
133+
return (
134+
<div className='ArticleDetail edit'>
135+
<div className='detailInfo'>
136+
<div className='left'>
137+
<Select ref='folder' onChange={value => this.handleFolderIdChange(value)} clearable={false} placeholder='select folder...' options={folderOptions} value={this.state.article.FolderId} className='folder'/>
138+
<Select onChange={(tag, tags) => this.handleTagsChange(tag, tags)} clearable={false} multi={true} placeholder='add some tags...' allowCreate={true} value={this.state.article.Tags} className='tags'/>
139+
</div>
140+
<div className='right'>
141+
<button onClick={e => this.handleCancelButtonClick(e)}>Cancel</button>
142+
<button onClick={e => this.handleSaveButtonClick(e)} className='primary'>Save</button>
143+
</div>
144+
</div>
145+
<div className='detailBody'>
146+
<div className='detailPanel'>
147+
<div className='header'>
148+
<div className='title'>
149+
<input ref='title' valueLink={this.linkState('article.title')}/>
150+
</div>
151+
<Select ref='mode' onChange={value => this.handleModeChange(value)} clearable={false} options={modeOptions}placeholder='select mode...' value={this.state.article.mode} className='mode'/>
152+
</div>
153+
<CodeEditor onChange={(e, value) => this.handleContentChange(e, value)} mode={this.state.article.mode} code={this.state.article.content}/>
154+
</div>
155+
</div>
156+
</div>
157+
)
158+
}
159+
160+
render () {
161+
let { status, activeArticle } = this.props
162+
163+
if (activeArticle == null) return this.renderEmpty()
164+
165+
switch (status.mode) {
166+
case CREATE_MODE:
167+
case EDIT_MODE:
168+
return this.renderEdit()
169+
case IDLE_MODE:
170+
default:
171+
return this.renderIdle()
172+
173+
}
174+
}
53175
}
54176

55177
ArticleDetail.propTypes = {
56-
article: PropTypes.shape(),
57178
status: PropTypes.shape(),
58-
user: PropTypes.shape()
179+
activeArticle: PropTypes.shape(),
180+
activeUser: PropTypes.shape()
59181
}
182+
ArticleDetail.prototype.linkState = linkState

browser/main/HomePage/ArticleList.js

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import React, { PropTypes } from 'react'
22
import ProfileImage from 'boost/components/ProfileImage'
33
import ModeIcon from 'boost/components/ModeIcon'
44
import moment from 'moment'
5-
import { IDLE_MODE, CREATE_MODE, EDIT_MODE } from '../actions'
5+
import { IDLE_MODE, CREATE_MODE, EDIT_MODE, NEW } from '../actions'
66

77
export default class ArticleList extends React.Component {
88
render () {
9-
let { articles, status } = this.props
9+
let { status, articles, activeArticle } = this.props
1010

1111
let articlesEl = articles.map(article => {
1212
let tags = Array.isArray(article.Tags) && article.Tags.length > 0 ? article.Tags.map(tag => {
@@ -19,14 +19,14 @@ export default class ArticleList extends React.Component {
1919

2020
return (
2121
<div key={'article-' + article.id}>
22-
<div className={'articleItem' + (false ? ' active' : '')}>
22+
<div className={'articleItem' + (activeArticle.id === article.id ? ' active' : '')}>
2323
<div className='top'>
2424
<i className='fa fa-fw fa-square'/>
2525
by <ProfileImage className='profileImage' size='20' email={article.User.email}/> {article.User.profileName}
2626
<span className='updatedAt'>{article.status != null ? article.status : moment(article.updatedAt).fromNow()}</span>
2727
</div>
2828
<div className='middle'>
29-
<ModeIcon className='mode' mode={article.mode}/> <div className='title'>{article.status !== 'new' ? article.title : '(New article)'}</div>
29+
<ModeIcon className='mode' mode={article.mode}/> <div className='title'>{article.status !== NEW ? article.title : '(New article)'}</div>
3030
</div>
3131
<div className='bottom'>
3232
<div className='tags'><i className='fa fa-fw fa-tags'/>{tags}</div>
@@ -39,28 +39,14 @@ export default class ArticleList extends React.Component {
3939

4040
return (
4141
<div className='ArticleList'>
42-
{ status.mode === 'CREATE_MODE' ? (
43-
<div key={'article-' + article.id}>
44-
<div className={'articleItem'}>
45-
<div className='top'>
46-
<span className='updatedAt'>{}</span>
47-
</div>
48-
<div className='middle'>
49-
<ModeIcon className='mode' mode={article.mode}/> <div className='title'>'(New article)'</div>
50-
</div>
51-
<div className='bottom'>
52-
<div className='tags'><i className='fa fa-fw fa-tags'/></div>
53-
</div>
54-
</div>
55-
<div className='divider'></div>
56-
</div>
57-
) : null}
5842
{articlesEl}
5943
</div>
6044
)
6145
}
6246
}
6347

6448
ArticleList.propTypes = {
65-
articles: PropTypes.array
49+
status: PropTypes.shape(),
50+
articles: PropTypes.array,
51+
activeArticle: PropTypes.shape()
6652
}

0 commit comments

Comments
 (0)