mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 02:06:29 +00:00
Folder indexing
This commit is contained in:
@@ -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(),
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
17
lib/store.js
17
lib/store.js
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user