mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
415 lines
13 KiB
JavaScript
415 lines
13 KiB
JavaScript
/* global localStorage*/
|
|
var React = require('react')
|
|
var ReactRouter = require('react-router')
|
|
var Reflux = require('reflux')
|
|
|
|
var PlanetHeader = require('../Components/PlanetHeader')
|
|
var PlanetNavigator = require('../Components/PlanetNavigator')
|
|
var PlanetArticleList = require('../Components/PlanetArticleList')
|
|
var PlanetArticleDetail = require('../Components/PlanetArticleDetail')
|
|
|
|
var Hq = require('../Services/Hq')
|
|
|
|
var Modal = require('../Mixins/Modal')
|
|
var ArticleFilter = require('../Mixins/ArticleFilter')
|
|
var Helper = require('../Mixins/Helper')
|
|
var KeyCaster = require('../Mixins/KeyCaster')
|
|
|
|
var UserStore = require('../Stores/UserStore')
|
|
var PlanetStore = require('../Stores/PlanetStore')
|
|
|
|
module.exports = React.createClass({
|
|
mixins: [ReactRouter.Navigation, ReactRouter.State, Modal, Reflux.listenTo(UserStore, 'onUserChange'), Reflux.listenTo(PlanetStore, 'onPlanetChange'), ArticleFilter, Helper, KeyCaster('planetContainer')],
|
|
propTypes: {
|
|
params: React.PropTypes.object,
|
|
planetName: React.PropTypes.string
|
|
},
|
|
getInitialState: function () {
|
|
return {
|
|
currentUser: JSON.parse(localStorage.getItem('currentUser')),
|
|
planet: null,
|
|
search: ''
|
|
}
|
|
},
|
|
componentDidMount: function () {
|
|
this.fetchPlanet(this.props.params.userName, this.props.params.planetName)
|
|
},
|
|
componentDidUpdate: function () {
|
|
if (this.isActive('planetHome') && this.refs.list != null && this.refs.list.props.articles.length > 0) {
|
|
var article = this.refs.list.props.articles[0]
|
|
var planet = this.state.planet
|
|
switch (article.type) {
|
|
case 'code':
|
|
this.transitionTo('codes', {userName: planet.Owner.name, planetName: planet.name, localId: article.localId})
|
|
break
|
|
case 'note':
|
|
this.transitionTo('notes', {userName: planet.Owner.name, planetName: planet.name, localId: article.localId})
|
|
break
|
|
}
|
|
}
|
|
},
|
|
componentWillReceiveProps: function (nextProps) {
|
|
if (this.state.planet == null) {
|
|
this.fetchPlanet(nextProps.params.userName, nextProps.params.planetName)
|
|
return
|
|
}
|
|
|
|
if (nextProps.params.userName !== this.state.planet.Owner.name || nextProps.params.planetName !== this.state.planet.name) {
|
|
this.setState({
|
|
planet: null
|
|
}, function () {
|
|
this.fetchPlanet(nextProps.params.userName, nextProps.params.planetName)
|
|
})
|
|
}
|
|
},
|
|
onKeyCast: function (e) {
|
|
switch (e.status) {
|
|
case 'openLaunchModal':
|
|
this.refs.navigator.openLaunchModal()
|
|
break
|
|
case 'selectNextArticle':
|
|
this.selectNextArticle()
|
|
break
|
|
case 'selectPriorArticle':
|
|
this.selectPriorArticle()
|
|
break
|
|
case 'toggleFocusSearchInput':
|
|
this.toggleFocusSearchInput()
|
|
break
|
|
case 'openEditModal':
|
|
this.refs.detail.openEditModal()
|
|
break
|
|
case 'openDeleteModal':
|
|
this.refs.detail.openDeleteModal()
|
|
break
|
|
}
|
|
},
|
|
onPlanetChange: function (res) {
|
|
if (this.state.planet == null) return
|
|
|
|
var planet, code, note, articleIndex, articlesCount
|
|
switch (res.status) {
|
|
case 'updated':
|
|
planet = res.data
|
|
if (this.state.planet.id === planet.id) {
|
|
if (this.state.planet.name === planet.name) {
|
|
this.setState({planet: planet})
|
|
} else {
|
|
this.transitionTo('planetHome', {userName: planet.Owner.name, planetName: planet.name})
|
|
}
|
|
}
|
|
break
|
|
case 'destroyed':
|
|
planet = res.data
|
|
if (this.state.planet.id === planet.id) {
|
|
this.transitionTo('userHome', {userName: this.state.planet.Owner.name})
|
|
}
|
|
break
|
|
case 'codeUpdated':
|
|
code = res.data
|
|
if (code.PlanetId === this.state.planet.id) {
|
|
this.state.planet.Codes = this.updateItemToTargetArray(code, this.state.planet.Codes)
|
|
|
|
this.setState({planet: this.state.planet})
|
|
}
|
|
break
|
|
case 'noteUpdated':
|
|
note = res.data
|
|
if (note.PlanetId === this.state.planet.id) {
|
|
this.state.planet.Notes = this.updateItemToTargetArray(note, this.state.planet.Notes)
|
|
|
|
this.setState({planet: this.state.planet})
|
|
}
|
|
break
|
|
case 'codeDestroyed':
|
|
code = res.data
|
|
if (code.PlanetId === this.state.planet.id) {
|
|
this.state.planet.Codes = this.deleteItemFromTargetArray(code, this.state.planet.Codes)
|
|
|
|
if (this.refs.detail.props.article != null && this.refs.detail.props.article.type === code.type && this.refs.detail.props.article.localId === code.localId) {
|
|
articleIndex = this.getFilteredIndexOfCurrentArticle()
|
|
articlesCount = this.refs.list.props.articles.length
|
|
|
|
this.setState({planet: this.state.planet}, function () {
|
|
if (articlesCount > 1) {
|
|
if (articleIndex > 0) {
|
|
this.selectArticleByListIndex(articleIndex - 1)
|
|
} else {
|
|
this.selectArticleByListIndex(articleIndex)
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|
|
|
|
this.setState({planet: this.state.planet})
|
|
}
|
|
break
|
|
case 'noteDestroyed':
|
|
note = res.data
|
|
if (note.PlanetId === this.state.planet.id) {
|
|
this.state.planet.Notes = this.deleteItemFromTargetArray(note, this.state.planet.Notes)
|
|
|
|
if (this.refs.detail.props.article != null && this.refs.detail.props.article.type === note.type && this.refs.detail.props.article.localId === note.localId) {
|
|
articleIndex = this.getFilteredIndexOfCurrentArticle()
|
|
articlesCount = this.refs.list.props.articles.length
|
|
|
|
this.setState({planet: this.state.planet}, function () {
|
|
if (articlesCount > 1) {
|
|
if (articleIndex > 0) {
|
|
this.selectArticleByListIndex(articleIndex - 1)
|
|
} else {
|
|
this.selectArticleByListIndex(articleIndex)
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|
|
|
|
this.setState({planet: this.state.planet})
|
|
}
|
|
break
|
|
}
|
|
},
|
|
onUserChange: function () {
|
|
|
|
},
|
|
fetchPlanet: function (userName, planetName) {
|
|
if (userName == null) userName = this.props.params.userName
|
|
if (planetName == null) planetName = this.props.params.planetName
|
|
|
|
Hq.fetchPlanet(userName, planetName)
|
|
.then(function (res) {
|
|
var planet = res.body
|
|
|
|
planet.Codes.forEach(function (code) {
|
|
code.type = 'code'
|
|
})
|
|
|
|
planet.Notes.forEach(function (note) {
|
|
note.type = 'note'
|
|
})
|
|
|
|
localStorage.setItem('planet-' + planet.id, JSON.stringify(planet))
|
|
|
|
this.setState({planet: planet})
|
|
}.bind(this))
|
|
.catch(function (err) {
|
|
console.error(err)
|
|
})
|
|
},
|
|
getFilteredIndexOfCurrentArticle: function () {
|
|
var params = this.props.params
|
|
var index = 0
|
|
|
|
if (this.isActive('codes')) {
|
|
this.refs.list.props.articles.some(function (_article, _index) {
|
|
if (_article.type === 'code' && _article.localId === parseInt(params.localId, 10)) {
|
|
index = _index
|
|
}
|
|
})
|
|
} else if (this.isActive('notes')) {
|
|
this.refs.list.props.articles.some(function (_article, _index) {
|
|
if (_article.type === 'note' && _article.localId === parseInt(params.localId, 10)) {
|
|
index = _index
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
}
|
|
|
|
return index
|
|
},
|
|
selectArticleByListIndex: function (index) {
|
|
var article = this.refs.list.props.articles[index]
|
|
var params = this.props.params
|
|
|
|
if (article == null) {
|
|
this.transitionTo('planetHome', params)
|
|
return
|
|
}
|
|
|
|
var listElement = this.refs.list.refs.articles.getDOMNode()
|
|
var articleElement = listElement.querySelectorAll('li')[index]
|
|
|
|
var overflowBelow = listElement.clientHeight + listElement.scrollTop < articleElement.offsetTop + articleElement.clientHeight
|
|
if (overflowBelow) {
|
|
listElement.scrollTop = articleElement.offsetTop + articleElement.clientHeight - listElement.clientHeight
|
|
}
|
|
var overflowAbove = listElement.scrollTop > articleElement.offsetTop
|
|
if (overflowAbove) {
|
|
listElement.scrollTop = articleElement.offsetTop
|
|
}
|
|
|
|
if (article.type === 'code') {
|
|
params.localId = article.localId
|
|
this.transitionTo('codes', params)
|
|
return
|
|
}
|
|
|
|
if (article.type === 'note') {
|
|
params.localId = article.localId
|
|
this.transitionTo('notes', params)
|
|
return
|
|
}
|
|
},
|
|
selectNextArticle: function () {
|
|
if (this.state.planet == null) return
|
|
|
|
var index = this.getFilteredIndexOfCurrentArticle()
|
|
|
|
if (index < this.refs.list.props.articles.length - 1) {
|
|
this.selectArticleByListIndex(index + 1)
|
|
}
|
|
},
|
|
selectPriorArticle: function () {
|
|
if (this.state.planet == null) {
|
|
return
|
|
}
|
|
var index = this.getFilteredIndexOfCurrentArticle()
|
|
|
|
if (index > 0) {
|
|
this.selectArticleByListIndex(index - 1)
|
|
} else {
|
|
React.findDOMNode(this.refs.header.refs.search).focus()
|
|
}
|
|
},
|
|
toggleFocusSearchInput: function () {
|
|
var search = React.findDOMNode(this.refs.header.refs.search)
|
|
if (document.activeElement === search) {
|
|
React.findDOMNode(this.refs.header.refs.search).blur()
|
|
return
|
|
}
|
|
React.findDOMNode(this.refs.header.refs.search).focus()
|
|
},
|
|
handleSearchChange: function (e) {
|
|
this.setState({search: e.target.value}, function () {
|
|
this.selectArticleByListIndex(0)
|
|
})
|
|
},
|
|
showAll: function () {
|
|
this.setState({search: ''})
|
|
},
|
|
toggleCodeFilter: function () {
|
|
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
|
|
|
var usingCodeFilter = false
|
|
var usingNoteFilter = false
|
|
keywords = keywords.filter(function (keyword) {
|
|
if (keyword === '$n') {
|
|
usingNoteFilter = true
|
|
return false
|
|
}
|
|
if (keyword === '$c') usingCodeFilter = true
|
|
return true
|
|
})
|
|
|
|
if (usingCodeFilter && !usingNoteFilter) {
|
|
keywords = keywords.filter(function (keyword) {
|
|
return keyword !== '$c'
|
|
})
|
|
}
|
|
|
|
if (!usingCodeFilter) {
|
|
keywords.unshift('$c')
|
|
}
|
|
|
|
this.setState({search: keywords.join(' ')}, function () {
|
|
this.selectArticleByListIndex(0)
|
|
})
|
|
},
|
|
toggleNoteFilter: function () {
|
|
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
|
|
|
var usingCodeFilter = false
|
|
var usingNoteFilter = false
|
|
keywords = keywords.filter(function (keyword) {
|
|
if (keyword === '$c') {
|
|
usingCodeFilter = true
|
|
return false
|
|
}
|
|
if (keyword === '$n') usingNoteFilter = true
|
|
return true
|
|
})
|
|
|
|
if (usingNoteFilter && !usingCodeFilter) {
|
|
keywords = keywords.filter(function (keyword) {
|
|
return keyword !== '$n'
|
|
})
|
|
}
|
|
|
|
if (!usingNoteFilter) {
|
|
keywords.unshift('$n')
|
|
}
|
|
|
|
this.setState({search: keywords.join(' ')}, function () {
|
|
this.selectArticleByListIndex(0)
|
|
})
|
|
},
|
|
applyTagFilter: function (tag) {
|
|
return function () {
|
|
this.setState({search: '#' + tag})
|
|
}.bind(this)
|
|
},
|
|
render: function () {
|
|
if (this.state.planet == null) return (<div/>)
|
|
|
|
var localId = parseInt(this.props.params.localId, 10)
|
|
|
|
var codes = this.state.planet.Codes
|
|
var notes = this.state.planet.Notes
|
|
|
|
var article
|
|
if (this.isActive('codes')) {
|
|
codes.some(function (_article) {
|
|
if (localId === _article.localId) {
|
|
article = _article
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
} else if (this.isActive('notes')) {
|
|
notes.some(function (_article) {
|
|
if (localId === _article.localId) {
|
|
article = _article
|
|
return true
|
|
}
|
|
return false
|
|
})
|
|
}
|
|
|
|
var articles = codes.concat(notes)
|
|
|
|
var filteredArticles = this.searchArticle(this.state.search, articles)
|
|
|
|
return (
|
|
<div className='PlanetContainer'>
|
|
<PlanetHeader
|
|
ref='header'
|
|
search={this.state.search}
|
|
fetchPlanet={this.fetchPlanet}
|
|
onSearchChange={this.handleSearchChange}
|
|
currentPlanet={this.state.planet}
|
|
/>
|
|
|
|
<PlanetNavigator
|
|
ref='navigator'
|
|
search={this.state.search}
|
|
showAll={this.showAll}
|
|
toggleCodeFilter={this.toggleCodeFilter}
|
|
toggleNoteFilter={this.toggleNoteFilter}
|
|
planet={this.state.planet}
|
|
currentUser={this.state.currentUser}/>
|
|
|
|
<PlanetArticleList showOnlyWithTag={this.applyTagFilter} ref='list' articles={filteredArticles}/>
|
|
|
|
<PlanetArticleDetail
|
|
ref='detail'
|
|
article={article}
|
|
planet={this.state.planet}
|
|
showOnlyWithTag={this.applyTagFilter}/>
|
|
</div>
|
|
)
|
|
}
|
|
})
|