Skip to content

Commit 58381b8

Browse files
committed
Folder indexing
1 parent 0899cea commit 58381b8

7 files changed

Lines changed: 88 additions & 37 deletions

File tree

browser/main/HomePage.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import api from 'boost/api'
1212
import auth from 'boost/auth'
1313
import io from 'boost/socket'
1414

15+
const TEXT_FILTER = 'TEXT_FILTER'
16+
const FOLDER_FILTER = 'FOLDER_FILTER'
17+
1518
class HomePage extends React.Component {
1619
componentDidMount () {
1720
const { dispatch } = this.props
@@ -53,7 +56,7 @@ class HomePage extends React.Component {
5356
<div className='HomePage'>
5457
<UserNavigator users={users} />
5558
<ArticleNavigator dispatch={dispatch} activeUser={activeUser} status={status}/>
56-
<ArticleTopBar/>
59+
<ArticleTopBar dispatch={dispatch} status={status}/>
5760
<ArticleList dispatch={dispatch} articles={articles} status={status} activeArticle={activeArticle}/>
5861
<ArticleDetail dispatch={dispatch} activeUser={activeUser} activeArticle={activeArticle} status={status}/>
5962
</div>
@@ -72,12 +75,42 @@ function remap (state) {
7275
let activeUser = findWhere(users, {id: parseInt(status.userId, 10)})
7376
if (activeUser == null) activeUser = users[0]
7477

78+
// Fetch articles
7579
let articles = state.articles['team-' + activeUser.id]
7680
if (articles == null) articles = []
7781
articles.sort((a, b) => {
7882
return new Date(b.updatedAt) - new Date(a.updatedAt)
7983
})
8084

85+
// Filter articles
86+
let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0).map(key => {
87+
if (key.match(/^in:.+$/)) {
88+
return {type: FOLDER_FILTER, value: key.match(/^in:(.+)$/)[1]}
89+
}
90+
return {type: TEXT_FILTER, value: key}
91+
})
92+
let folderFilters = filters.filter(filter => filter.type === FOLDER_FILTER)
93+
let textFilters = filters.filter(filter => filter.type === TEXT_FILTER)
94+
95+
let targetFolders = activeUser.Folders.filter(folder => {
96+
return findWhere(folderFilters, {value: folder.name})
97+
})
98+
status.targetFolders = targetFolders
99+
100+
if (targetFolders.length > 0) {
101+
articles = articles.filter(article => {
102+
return findWhere(targetFolders, {id: article.FolderId})
103+
})
104+
}
105+
if (textFilters.length > 0) {
106+
articles = textFilters.reduce((articles, textFilter) => {
107+
return articles.filter(article => {
108+
return article.title.match(new RegExp(textFilter.value, 'i')) || article.content.match(new RegExp(textFilter.value, 'i'))
109+
})
110+
}, articles)
111+
}
112+
113+
// Grab active article
81114
let activeArticle = findWhere(articles, {key: status.articleKey})
82115
if (activeArticle == null) activeArticle = articles[0]
83116

@@ -120,7 +153,7 @@ function remap (state) {
120153
articles,
121154
activeArticle
122155
}
123-
console.log(props)
156+
124157
return props
125158
}
126159

@@ -131,8 +164,7 @@ HomePage.propTypes = {
131164
userId: PropTypes.string
132165
}),
133166
status: PropTypes.shape({
134-
userId: PropTypes.string,
135-
folderId: PropTypes.number
167+
userId: PropTypes.string
136168
}),
137169
articles: PropTypes.array,
138170
activeArticle: PropTypes.shape(),

browser/main/HomePage/ArticleList.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export default class ArticleList extends React.Component {
1515

1616
render () {
1717
let { articles, activeArticle } = this.props
18-
console.log(articles)
1918

2019
let articlesEl = articles.map(article => {
2120
let tags = Array.isArray(article.Tags) && article.Tags.length > 0

browser/main/HomePage/ArticleNavigator.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { PropTypes } from 'react'
22
import ProfileImage from 'boost/components/ProfileImage'
33
import { findWhere } from 'lodash'
4-
import { switchMode, CREATE_MODE } from 'boost/actions'
4+
import { setSearchFilter, switchFolder, switchMode, CREATE_MODE } from 'boost/actions'
55
import { openModal } from 'boost/modal'
66
import FolderMark from 'boost/components/FolderMark'
77
import Preferences from 'boost/components/modal/Preferences'
@@ -27,16 +27,30 @@ export default class ArticleNavigator extends React.Component {
2727
openModal(CreateNewFolder, {user: activeUser})
2828
}
2929

30+
handleFolderButtonClick (name) {
31+
return e => {
32+
let { dispatch } = this.props
33+
dispatch(switchFolder(name))
34+
}
35+
}
36+
37+
handleAllFoldersButtonClick (e) {
38+
let { dispatch } = this.props
39+
dispatch(setSearchFilter(''))
40+
}
41+
3042
render () {
3143
let { activeUser, status } = this.props
3244
if (activeUser == null) return (<div className='ArticleNavigator'/>)
33-
34-
let activeFolder = findWhere(activeUser.Folders, {id: status.folderId})
45+
let { targetFolders } = status
46+
if (targetFolders == null) targetFolders = []
3547

3648
let folders = activeUser.Folders != null
3749
? activeUser.Folders.map((folder, index) => {
50+
let isActive = findWhere(targetFolders, {id: folder.id})
51+
3852
return (
39-
<button key={'folder-' + folder.id} className={activeFolder != null && activeFolder.id === folder.id ? 'active' : ''}>
53+
<button onClick={e => this.handleFolderButtonClick(folder.name)(e)} key={'folder-' + folder.id} className={isActive ? 'active' : ''}>
4054
<FolderMark id={folder.id}/> {folder.name} {folder.public ? <i className='fa fa-fw fa-lock'/> : null}</button>
4155
)
4256
})
@@ -71,7 +85,7 @@ export default class ArticleNavigator extends React.Component {
7185
<button onClick={e => this.handleNewFolderButton(e)} className='addBtn'><i className='fa fa-fw fa-plus'/></button>
7286
</div>
7387
<div className='folderList'>
74-
<button className={activeFolder == null ? 'active' : ''}>All folders</button>
88+
<button onClick={e => this.handleAllFoldersButtonClick(e)} className={targetFolders.length === 0 ? 'active' : ''}>All folders</button>
7589
{folders}
7690
</div>
7791
</div>

browser/main/HomePage/ArticleTopBar.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
import React, { PropTypes } from 'react'
22
import ExternalLink from 'boost/components/ExternalLink'
3+
import { setSearchFilter } from 'boost/actions'
4+
5+
export default class ArticleTopBar extends React.Component {
6+
handleSearchChange (e) {
7+
let { dispatch } = this.props
8+
9+
dispatch(setSearchFilter(e.target.value))
10+
}
311

4-
const ArticleTopBar = React.createClass({
512
render () {
613
return (
714
<div className='ArticleTopBar'>
815
<div className='left'>
916
<div className='search'>
1017
<i className='fa fa-search fa-fw' />
11-
<input placeholder='Search' type='text'/>
18+
<input value={this.props.status.search} onChange={e => this.handleSearchChange(e)} placeholder='Search' type='text'/>
1219
</div>
1320
<button className='refreshBtn'><i className='fa fa-fw fa-refresh'/></button>
1421
</div>
@@ -22,6 +29,9 @@ const ArticleTopBar = React.createClass({
2229
</div>
2330
)
2431
}
25-
})
32+
}
2633

27-
export default ArticleTopBar
34+
ArticleTopBar.propTypes = {
35+
search: PropTypes.string,
36+
dispatch: PropTypes.func
37+
}

lib/actions.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const SWITCH_USER = 'SWITCH_USER'
88
export const SWITCH_FOLDER = 'SWITCH_FOLDER'
99
export const SWITCH_MODE = 'SWITCH_MODE'
1010
export const SWITCH_ARTICLE = 'SWITCH_ARTICLE'
11+
export const SET_SEARCH_FILTER = 'SET_SEARCH_FILTER'
1112

1213
// Status - mode
1314
export const IDLE_MODE = 'IDLE_MODE'
@@ -56,10 +57,10 @@ export function switchUser (userId) {
5657
}
5758
}
5859

59-
export function switchFolder (folderId) {
60+
export function switchFolder (folderName) {
6061
return {
6162
type: SWITCH_FOLDER,
62-
data: folderId
63+
data: folderName
6364
}
6465
}
6566

@@ -76,3 +77,10 @@ export function switchArticle (articleKey) {
7677
data: articleKey
7778
}
7879
}
80+
81+
export function setSearchFilter (search) {
82+
return {
83+
type: SET_SEARCH_FILTER,
84+
data: search
85+
}
86+
}

lib/reducer.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { combineReducers } from 'redux'
22
import { findIndex } from 'lodash'
3-
import { SWITCH_USER, SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, USER_UPDATE, ARTICLE_REFRESH, ARTICLE_UPDATE, ARTICLE_DESTROY, IDLE_MODE, CREATE_MODE } from './actions'
3+
import { SWITCH_USER, SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, USER_UPDATE, ARTICLE_REFRESH, ARTICLE_UPDATE, ARTICLE_DESTROY, IDLE_MODE, CREATE_MODE } from './actions'
44
import auth from 'boost/auth'
55

66
const initialStatus = {
7-
mode: IDLE_MODE
7+
mode: IDLE_MODE,
8+
search: ''
89
}
910

1011
function getInitialArticles () {
@@ -39,20 +40,24 @@ function status (state, action) {
3940
case SWITCH_USER:
4041
state.userId = action.data
4142
state.mode = IDLE_MODE
42-
state.folderId = null
4343
return state
4444
case SWITCH_FOLDER:
45-
state.folderId = action.data
4645
state.mode = IDLE_MODE
46+
state.search = `in:${action.data} `
4747
return state
4848
case SWITCH_MODE:
4949
state.mode = action.data
5050
if (state.mode === CREATE_MODE) state.articleKey = null
51+
5152
return state
5253
case SWITCH_ARTICLE:
5354
state.articleKey = action.data
5455
state.mode = IDLE_MODE
5556
return state
57+
case SET_SEARCH_FILTER:
58+
state.search = action.data
59+
state.mode = IDLE_MODE
60+
return state
5661
default:
5762
if (state == null) return initialStatus
5863
return state

lib/store.js

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,6 @@
11
import reducer from './reducer'
22
import { createStore } from 'redux'
33

4-
// import React from 'react'
5-
// import { compose } from 'redux'
6-
// import { devTools, persistState } from 'redux-devtools'
7-
// import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react'
8-
9-
// let finalCreateStore = compose(devTools(), persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)))(createStore)
10-
// let store = finalCreateStore(reducer)
11-
12-
// devToolEl = (
13-
// <DebugPanel top right bottom>
14-
// <DevTools store={store} monitor={LogMonitor} visibleOnLoad={false}/>
15-
// </DebugPanel>
16-
// )
17-
18-
// export let devToolElement = devToolEl
19-
// export default store
20-
214
let store = createStore(reducer)
225

236
export let devToolElement = null

0 commit comments

Comments
 (0)