1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-14 10:16:26 +00:00

Folder indexing

This commit is contained in:
Rokt33r
2015-10-20 00:55:18 +09:00
parent 0899cea4b4
commit 58381b8062
7 changed files with 88 additions and 37 deletions

View File

@@ -12,6 +12,9 @@ import api from 'boost/api'
import auth from 'boost/auth' import auth from 'boost/auth'
import io from 'boost/socket' import io from 'boost/socket'
const TEXT_FILTER = 'TEXT_FILTER'
const FOLDER_FILTER = 'FOLDER_FILTER'
class HomePage extends React.Component { class HomePage extends React.Component {
componentDidMount () { componentDidMount () {
const { dispatch } = this.props const { dispatch } = this.props
@@ -53,7 +56,7 @@ class HomePage extends React.Component {
<div className='HomePage'> <div className='HomePage'>
<UserNavigator users={users} /> <UserNavigator users={users} />
<ArticleNavigator dispatch={dispatch} activeUser={activeUser} status={status}/> <ArticleNavigator dispatch={dispatch} activeUser={activeUser} status={status}/>
<ArticleTopBar/> <ArticleTopBar dispatch={dispatch} status={status}/>
<ArticleList dispatch={dispatch} articles={articles} status={status} activeArticle={activeArticle}/> <ArticleList dispatch={dispatch} articles={articles} status={status} activeArticle={activeArticle}/>
<ArticleDetail dispatch={dispatch} activeUser={activeUser} activeArticle={activeArticle} status={status}/> <ArticleDetail dispatch={dispatch} activeUser={activeUser} activeArticle={activeArticle} status={status}/>
</div> </div>
@@ -72,12 +75,42 @@ function remap (state) {
let activeUser = findWhere(users, {id: parseInt(status.userId, 10)}) let activeUser = findWhere(users, {id: parseInt(status.userId, 10)})
if (activeUser == null) activeUser = users[0] if (activeUser == null) activeUser = users[0]
// Fetch articles
let articles = state.articles['team-' + activeUser.id] let articles = state.articles['team-' + activeUser.id]
if (articles == null) articles = [] if (articles == null) articles = []
articles.sort((a, b) => { articles.sort((a, b) => {
return new Date(b.updatedAt) - new Date(a.updatedAt) return new Date(b.updatedAt) - new Date(a.updatedAt)
}) })
// Filter articles
let filters = status.search.split(' ').map(key => key.trim()).filter(key => key.length > 0).map(key => {
if (key.match(/^in:.+$/)) {
return {type: FOLDER_FILTER, value: key.match(/^in:(.+)$/)[1]}
}
return {type: TEXT_FILTER, value: key}
})
let folderFilters = filters.filter(filter => filter.type === FOLDER_FILTER)
let textFilters = filters.filter(filter => filter.type === TEXT_FILTER)
let targetFolders = activeUser.Folders.filter(folder => {
return findWhere(folderFilters, {value: folder.name})
})
status.targetFolders = targetFolders
if (targetFolders.length > 0) {
articles = articles.filter(article => {
return findWhere(targetFolders, {id: article.FolderId})
})
}
if (textFilters.length > 0) {
articles = textFilters.reduce((articles, textFilter) => {
return articles.filter(article => {
return article.title.match(new RegExp(textFilter.value, 'i')) || article.content.match(new RegExp(textFilter.value, 'i'))
})
}, articles)
}
// Grab active article
let activeArticle = findWhere(articles, {key: status.articleKey}) let activeArticle = findWhere(articles, {key: status.articleKey})
if (activeArticle == null) activeArticle = articles[0] if (activeArticle == null) activeArticle = articles[0]
@@ -120,7 +153,7 @@ function remap (state) {
articles, articles,
activeArticle activeArticle
} }
console.log(props)
return props return props
} }
@@ -131,8 +164,7 @@ HomePage.propTypes = {
userId: PropTypes.string userId: PropTypes.string
}), }),
status: PropTypes.shape({ status: PropTypes.shape({
userId: PropTypes.string, userId: PropTypes.string
folderId: PropTypes.number
}), }),
articles: PropTypes.array, articles: PropTypes.array,
activeArticle: PropTypes.shape(), activeArticle: PropTypes.shape(),

View File

@@ -15,7 +15,6 @@ export default class ArticleList extends React.Component {
render () { render () {
let { articles, activeArticle } = this.props let { articles, activeArticle } = this.props
console.log(articles)
let articlesEl = articles.map(article => { let articlesEl = articles.map(article => {
let tags = Array.isArray(article.Tags) && article.Tags.length > 0 let tags = Array.isArray(article.Tags) && article.Tags.length > 0

View File

@@ -1,7 +1,7 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ProfileImage from 'boost/components/ProfileImage' import ProfileImage from 'boost/components/ProfileImage'
import { findWhere } from 'lodash' import { findWhere } from 'lodash'
import { switchMode, CREATE_MODE } from 'boost/actions' import { setSearchFilter, switchFolder, switchMode, CREATE_MODE } from 'boost/actions'
import { openModal } from 'boost/modal' import { openModal } from 'boost/modal'
import FolderMark from 'boost/components/FolderMark' import FolderMark from 'boost/components/FolderMark'
import Preferences from 'boost/components/modal/Preferences' import Preferences from 'boost/components/modal/Preferences'
@@ -27,16 +27,30 @@ export default class ArticleNavigator extends React.Component {
openModal(CreateNewFolder, {user: activeUser}) openModal(CreateNewFolder, {user: activeUser})
} }
handleFolderButtonClick (name) {
return e => {
let { dispatch } = this.props
dispatch(switchFolder(name))
}
}
handleAllFoldersButtonClick (e) {
let { dispatch } = this.props
dispatch(setSearchFilter(''))
}
render () { render () {
let { activeUser, status } = this.props let { activeUser, status } = this.props
if (activeUser == null) return (<div className='ArticleNavigator'/>) if (activeUser == null) return (<div className='ArticleNavigator'/>)
let { targetFolders } = status
let activeFolder = findWhere(activeUser.Folders, {id: status.folderId}) if (targetFolders == null) targetFolders = []
let folders = activeUser.Folders != null let folders = activeUser.Folders != null
? activeUser.Folders.map((folder, index) => { ? activeUser.Folders.map((folder, index) => {
let isActive = findWhere(targetFolders, {id: folder.id})
return ( return (
<button key={'folder-' + folder.id} className={activeFolder != null && activeFolder.id === folder.id ? 'active' : ''}> <button onClick={e => this.handleFolderButtonClick(folder.name)(e)} key={'folder-' + folder.id} className={isActive ? 'active' : ''}>
<FolderMark id={folder.id}/> {folder.name} {folder.public ? <i className='fa fa-fw fa-lock'/> : null}</button> <FolderMark id={folder.id}/> {folder.name} {folder.public ? <i className='fa fa-fw fa-lock'/> : null}</button>
) )
}) })
@@ -71,7 +85,7 @@ export default class ArticleNavigator extends React.Component {
<button onClick={e => this.handleNewFolderButton(e)} className='addBtn'><i className='fa fa-fw fa-plus'/></button> <button onClick={e => this.handleNewFolderButton(e)} className='addBtn'><i className='fa fa-fw fa-plus'/></button>
</div> </div>
<div className='folderList'> <div className='folderList'>
<button className={activeFolder == null ? 'active' : ''}>All folders</button> <button onClick={e => this.handleAllFoldersButtonClick(e)} className={targetFolders.length === 0 ? 'active' : ''}>All folders</button>
{folders} {folders}
</div> </div>
</div> </div>

View File

@@ -1,14 +1,21 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ExternalLink from 'boost/components/ExternalLink' import ExternalLink from 'boost/components/ExternalLink'
import { setSearchFilter } from 'boost/actions'
export default class ArticleTopBar extends React.Component {
handleSearchChange (e) {
let { dispatch } = this.props
dispatch(setSearchFilter(e.target.value))
}
const ArticleTopBar = React.createClass({
render () { render () {
return ( return (
<div className='ArticleTopBar'> <div className='ArticleTopBar'>
<div className='left'> <div className='left'>
<div className='search'> <div className='search'>
<i className='fa fa-search fa-fw' /> <i className='fa fa-search fa-fw' />
<input placeholder='Search' type='text'/> <input value={this.props.status.search} onChange={e => this.handleSearchChange(e)} placeholder='Search' type='text'/>
</div> </div>
<button className='refreshBtn'><i className='fa fa-fw fa-refresh'/></button> <button className='refreshBtn'><i className='fa fa-fw fa-refresh'/></button>
</div> </div>
@@ -22,6 +29,9 @@ const ArticleTopBar = React.createClass({
</div> </div>
) )
} }
}) }
export default ArticleTopBar ArticleTopBar.propTypes = {
search: PropTypes.string,
dispatch: PropTypes.func
}

View File

@@ -8,6 +8,7 @@ export const SWITCH_USER = 'SWITCH_USER'
export const SWITCH_FOLDER = 'SWITCH_FOLDER' export const SWITCH_FOLDER = 'SWITCH_FOLDER'
export const SWITCH_MODE = 'SWITCH_MODE' export const SWITCH_MODE = 'SWITCH_MODE'
export const SWITCH_ARTICLE = 'SWITCH_ARTICLE' export const SWITCH_ARTICLE = 'SWITCH_ARTICLE'
export const SET_SEARCH_FILTER = 'SET_SEARCH_FILTER'
// Status - mode // Status - mode
export const IDLE_MODE = 'IDLE_MODE' export const IDLE_MODE = 'IDLE_MODE'
@@ -56,10 +57,10 @@ export function switchUser (userId) {
} }
} }
export function switchFolder (folderId) { export function switchFolder (folderName) {
return { return {
type: SWITCH_FOLDER, type: SWITCH_FOLDER,
data: folderId data: folderName
} }
} }
@@ -76,3 +77,10 @@ export function switchArticle (articleKey) {
data: articleKey data: articleKey
} }
} }
export function setSearchFilter (search) {
return {
type: SET_SEARCH_FILTER,
data: search
}
}

View File

@@ -1,10 +1,11 @@
import { combineReducers } from 'redux' import { combineReducers } from 'redux'
import { findIndex } from 'lodash' import { findIndex } from 'lodash'
import { SWITCH_USER, SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, USER_UPDATE, ARTICLE_REFRESH, ARTICLE_UPDATE, ARTICLE_DESTROY, IDLE_MODE, CREATE_MODE } from './actions' 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'
import auth from 'boost/auth' import auth from 'boost/auth'
const initialStatus = { const initialStatus = {
mode: IDLE_MODE mode: IDLE_MODE,
search: ''
} }
function getInitialArticles () { function getInitialArticles () {
@@ -39,20 +40,24 @@ function status (state, action) {
case SWITCH_USER: case SWITCH_USER:
state.userId = action.data state.userId = action.data
state.mode = IDLE_MODE state.mode = IDLE_MODE
state.folderId = null
return state return state
case SWITCH_FOLDER: case SWITCH_FOLDER:
state.folderId = action.data
state.mode = IDLE_MODE state.mode = IDLE_MODE
state.search = `in:${action.data} `
return state return state
case SWITCH_MODE: case SWITCH_MODE:
state.mode = action.data state.mode = action.data
if (state.mode === CREATE_MODE) state.articleKey = null if (state.mode === CREATE_MODE) state.articleKey = null
return state return state
case SWITCH_ARTICLE: case SWITCH_ARTICLE:
state.articleKey = action.data state.articleKey = action.data
state.mode = IDLE_MODE state.mode = IDLE_MODE
return state return state
case SET_SEARCH_FILTER:
state.search = action.data
state.mode = IDLE_MODE
return state
default: default:
if (state == null) return initialStatus if (state == null) return initialStatus
return state return state

View File

@@ -1,23 +1,6 @@
import reducer from './reducer' import reducer from './reducer'
import { createStore } from 'redux' import { createStore } from 'redux'
// import React from 'react'
// import { compose } from 'redux'
// import { devTools, persistState } from 'redux-devtools'
// import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react'
// let finalCreateStore = compose(devTools(), persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)))(createStore)
// let store = finalCreateStore(reducer)
// devToolEl = (
// <DebugPanel top right bottom>
// <DevTools store={store} monitor={LogMonitor} visibleOnLoad={false}/>
// </DebugPanel>
// )
// export let devToolElement = devToolEl
// export default store
let store = createStore(reducer) let store = createStore(reducer)
export let devToolElement = null export let devToolElement = null