1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00
Files
Boostnote/browser/main/Containers/PlanetContainer.jsx
2015-07-24 19:05:11 +09:00

505 lines
15 KiB
JavaScript

var React = require('react/addons')
var ReactRouter = require('react-router')
var PlanetHeader = require('../Components/PlanetHeader')
var PlanetNavigator = require('../Components/PlanetNavigator')
var PlanetArticleList = require('../Components/PlanetArticleList')
var PlanetArticleDetail = require('../Components/PlanetArticleDetail')
var ModalBase = require('../Components/ModalBase')
var LaunchModal = require('../Components/LaunchModal')
var SnippetEditModal = require('../Components/SnippetEditModal')
var SnippetDeleteModal = require('../Components/SnippetDeleteModal')
var BlueprintEditModal = require('../Components/BlueprintEditModal')
var BlueprintDeleteModal = require('../Components/BlueprintDeleteModal')
var PlanetAddUserModal = require('../Components/PlanetAddUserModal')
var PlanetSettingModal = require('../Components/PlanetSettingModal')
var PlanetActions = require('../Actions/PlanetActions')
var AuthStore = require('../Stores/AuthStore')
var PlanetStore = require('../Stores/PlanetStore')
var searchArticle = function (search, articles) {
if (search === '' || search == null) return articles
var firstFiltered = articles.filter(function (article) {
var first = article.type === 'snippet' ? article.callSign : article.title
if (first.match(new RegExp(search, 'i'))) return true
return false
})
var secondFiltered = articles.filter(function (article) {
var second = article.type === 'snippet' ? article.description : article.content
if (second.match(new RegExp(search, 'i'))) return true
return false
})
var thirdFiltered = articles.filter(function (article) {
if (article.type === 'snippet') {
if (article.content.match(new RegExp(search, 'i'))) return true
}
return false
})
return firstFiltered.concat(secondFiltered, thirdFiltered).filter(function (value, index, self) {
return self.indexOf(value) === index
})
}
module.exports = React.createClass({
mixins: [ReactRouter.Navigation, ReactRouter.State],
propTypes: {
params: React.PropTypes.object,
planetName: React.PropTypes.string
},
getInitialState: function () {
return {
currentUser: AuthStore.getUser(),
currentPlanet: null,
search: '',
isFetched: false
}
},
componentDidMount: function () {
this.unsubscribePlanet = PlanetStore.listen(this.onFetched)
this.unsubscribeAuth = AuthStore.listen(this.onListenAuth)
PlanetActions.fetchPlanet(this.props.params.userName, this.props.params.planetName)
},
componentWillUnmount: function () {
this.unsubscribePlanet()
this.unsubscribeAuth()
},
componentDidUpdate: function () {
if (this.state.currentPlanet == null || this.state.currentPlanet.name !== this.props.params.planetName || this.state.currentPlanet.userName !== this.props.params.userName) {
PlanetActions.fetchPlanet(this.props.params.userName, this.props.params.planetName)
this.focus()
}
},
getFilteredIndexOfCurrentArticle: function () {
var params = this.props.params
var index = 0
if (this.isActive('snippets')) {
this.refs.list.props.articles.some(function (_article, _index) {
if (_article.type === 'snippet' && _article.localId === parseInt(params.localId, 10)) {
index = _index
}
})
} else if (this.isActive('blueprints')) {
this.refs.list.props.articles.some(function (_article, _index) {
if (_article.type === 'blueprint' && _article.localId === parseInt(params.localId, 10)) {
index = _index
return true
}
return false
})
}
return index
},
getIndexOfCurrentArticle: function () {
var params = this.props.params
var index = 0
if (this.isActive('snippets')) {
this.state.currentPlanet.Articles.some(function (_article, _index) {
if (_article.type === 'snippet' && _article.localId === parseInt(params.localId, 10)) {
index = _index
}
})
} else if (this.isActive('blueprints')) {
this.state.currentPlanet.Articles.some(function (_article, _index) {
if (_article.type === 'blueprint' && _article.localId === parseInt(params.localId, 10)) {
index = _index
return true
}
return false
})
}
return index
},
selectArticleByIndex: function (index) {
var article = this.refs.list.props.articles[index]
var params = this.props.params
if (article == null) {
this.transitionTo('planetHome', params)
return
}
if (article.type === 'snippet') {
params.localId = article.localId
this.transitionTo('snippets', params)
return
}
if (article.type === 'blueprint') {
params.localId = article.localId
this.transitionTo('blueprints', params)
return
}
},
selectNextArticle: function () {
if (this.state.currentPlanet == null) return
var index = this.getFilteredIndexOfCurrentArticle()
if (index < this.refs.list.props.articles.length - 1) {
this.selectArticleByIndex(index + 1)
}
},
selectPriorArticle: function () {
if (this.state.currentPlanet == null) {
return
}
var index = this.getFilteredIndexOfCurrentArticle()
if (index > 0) {
this.selectArticleByIndex(index - 1)
} else {
React.findDOMNode(this).querySelector('.PlanetHeader .searchInput input').focus()
}
},
onListenAuth: function (res) {
if (res.status === 'userProfileUpdated') {
if (this.state.currentPlanet != null) {
res.data.Planets.some(function (planet) {
if (planet.id === this.state.currentPlanet.id) {
this.transitionTo('planet', {userName: planet.userName, planetName: planet.name})
return true
}
return false
}.bind(this))
}
}
},
onFetched: function (res) {
if (res == null) {
return
}
var articles = this.state.currentPlanet == null ? null : this.state.currentPlanet.Articles
if (res.status === 'planetFetched') {
var planet = res.data
this.setState({isFetched: true, currentPlanet: planet, filteredArticles: planet.Articles}, function () {
if (this.refs.detail.props.article == null) {
var params = this.props.params
delete params.localId
var articles = this.refs.list.props.articles
if (articles.length > 0) {
console.log('need to redirect', this.refs.list.props.articles)
var article = articles[0]
params.localId = article.localId
if (article.type === 'snippet') {
this.transitionTo('snippets', params)
} else {
this.transitionTo('blueprints', params)
}
}
}
})
return
}
if (res.status === 'userAdded') {
var user = res.data
if (user == null) {
return null
}
this.state.currentPlanet.Users.push(user)
this.setState({currentPlanet: this.state.currentPlanet}, function () {
if (this.state.isAddUserModalOpen) {this.closeAddUserModal()}
})
return
}
if (res.status === 'userRemoved') {
var user = res.data
if (user == null) {
return null
}
this.state.currentPlanet.Users.some(function (_user, index) {
if (user.id === _user.id) {
this.state.currentPlanet.Users.splice(index, 1)
return true
}
return false
}.bind(this))
this.setState({currentPlanet: this.state.currentPlanet}, function () {
if (this.state.isAddUserModalOpen) {this.closeAddUserModal()}
})
return
}
if (res.status === 'nameChanged') {
var params = Object.assign({}, this.props.params)
params.planetName = res.data.name
this.transitionTo('planet', params)
return
}
var article = res.data
var filteredIndex = this.getFilteredIndexOfCurrentArticle()
var index = this.getIndexOfCurrentArticle()
if (article.PlanetId === this.state.currentPlanet.id) {
switch (res.status) {
case 'articleCreated':
articles.unshift(article)
this.setState({planet: this.state.currentPlanet, search: ''}, function () {
this.closeLaunchModal()
this.selectArticleByIndex(0)
})
break
case 'articleUpdated':
articles.splice(index, 1)
articles.unshift(article)
this.setState({planet: this.state.currentPlanet}, function () {
this.closeEditModal()
})
break
case 'articleDeleted':
articles.splice(index, 1)
this.setState({planet: this.state.currentPlanet}, function () {
this.closeDeleteModal()
if (index > 0) {
this.selectArticleByIndex(filteredIndex - 1)
} else {
this.selectArticleByIndex(filteredIndex)
}
})
}
}
},
handleSearchChange: function (e) {
this.setState({search: e.target.value}, function () {
this.selectArticleByIndex(0)
})
},
openLaunchModal: function () {
this.setState({isLaunchModalOpen: true})
},
closeLaunchModal: function () {
this.setState({isLaunchModalOpen: false}, function () {
this.focus()
})
},
openAddUserModal: function () {
this.setState({isAddUserModalOpen: true})
},
closeAddUserModal: function () {
this.setState({isAddUserModalOpen: false}, function () {
this.focus()
})
},
openEditModal: function () {
if (this.refs.detail.props.article == null) {return}
this.setState({isEditModalOpen: true})
},
closeEditModal: function () {
this.setState({isEditModalOpen: false}, function () {
this.focus()
})
},
submitEditModal: function () {
this.setState({isEditModalOpen: false})
},
openDeleteModal: function () {
if (this.refs.detail.props.article == null) {return}
this.setState({isDeleteModalOpen: true})
},
closeDeleteModal: function () {
this.setState({isDeleteModalOpen: false}, function () {
this.focus()
})
},
submitDeleteModal: function () {
this.setState({isDeleteModalOpen: false})
},
openSettingModal: function () {
this.setState({isSettingModalOpen: true})
},
closeSettingModal: function () {
this.setState({isSettingModalOpen: false}, function () {
this.focus()
})
},
focus: function () {
React.findDOMNode(this).focus()
},
handleKeyDown: function (e) {
// Bypath for modal open state
if (this.state.isLaunchModalOpen) {
if (e.keyCode === 27) {
this.closeLaunchModal()
}
return
}
if (this.state.isEditModalOpen) {
if (e.keyCode === 27) {
this.closeEditModal()
}
return
}
if (this.state.isDeleteModalOpen) {
if (e.keyCode === 27) {
this.closeDeleteModal()
}
return
}
if (this.state.isAddUserModalOpen) {
if (e.keyCode === 27) {
this.closeAddUserModal()
}
return
}
if (this.state.isSettingModalOpen) {
if (e.keyCode === 27) {
this.closeSettingModal()
}
return
}
// LaunchModal
if ((e.keyCode === 13 && e.metaKey)) {
e.preventDefault()
this.openLaunchModal()
}
// Focus(blur) search input
var searchInput = React.findDOMNode(this).querySelector('.PlanetHeader .searchInput input')
if (document.activeElement === searchInput) {
switch (e.keyCode) {
case 38:
this.focus()
break
case 40:
e.preventDefault()
this.focus()
break
case 27:
e.preventDefault()
this.focus()
break
}
return
}
// Article indexing
if (document.activeElement !== searchInput) {
switch (e.keyCode) {
case 38:
e.preventDefault()
this.selectPriorArticle()
break
case 40:
e.preventDefault()
this.selectNextArticle()
break
case 27:
searchInput.focus()
break
}
// Other hotkeys
switch (e.keyCode) {
case 65:
e.preventDefault()
this.openLaunchModal()
break
case 68:
e.preventDefault()
this.openDeleteModal()
break
case 69:
e.preventDefault()
this.openEditModal()
}
}
},
render: function () {
if (this.state.currentUser == null) return (<div/>)
if (this.state.currentPlanet == null) return (<div/>)
var localId = parseInt(this.props.params.localId, 10)
var article
if (this.isActive('snippets')) {
this.state.currentPlanet.Articles.some(function (_article) {
if (_article.type === 'snippet' && localId === _article.localId) {
article = _article
return true
}
return false
})
} else if (this.isActive('blueprints')) {
this.state.currentPlanet.Articles.some(function (_article) {
if (_article.type === 'blueprint' && localId === _article.localId) {
article = _article
return true
}
return false
})
}
var filteredArticles = this.state.isFetched ? searchArticle(this.state.search, this.state.currentPlanet.Articles) : []
var editModal = article != null ? (article.type === 'snippet' ? (
<SnippetEditModal snippet={article} submit={this.submitEditModal} close={this.closeEditModal}/>
) : (
<BlueprintEditModal blueprint={article} submit={this.submitEditModal} close={this.closeEditModal}/>
)) : null
var deleteModal = article != null ? (article.type === 'snippet' ? (
<SnippetDeleteModal snippet={article} close={this.closeDeleteModal}/>
) : (
<BlueprintDeleteModal blueprint={article} close={this.closeDeleteModal}/>
)) : null
return (
<div tabIndex='1' onKeyDown={this.handleKeyDown} className='PlanetContainer'>
<ModalBase isOpen={this.state.isLaunchModalOpen} close={this.closeLaunchModal}>
<LaunchModal close={this.closeLaunchModal}/>
</ModalBase>
<ModalBase isOpen={this.state.isEditModalOpen} close={this.closeEditModal}>
{editModal}
</ModalBase>
<ModalBase isOpen={this.state.isDeleteModalOpen} close={this.closeDeleteModal}>
{deleteModal}
</ModalBase>
<ModalBase isOpen={this.state.isAddUserModalOpen} close={this.closeAddUserModal}>
<PlanetAddUserModal close={this.closeAddUserModal}/>
</ModalBase>
<ModalBase isOpen={this.state.isSettingModalOpen} close={this.closeSettingModal}>
<PlanetSettingModal currentPlanet={this.state.currentPlanet} close={this.closeSettingModal}/>
</ModalBase>
<PlanetHeader search={this.state.search}
openSettingModal={this.openSettingModal} onSearchChange={this.handleSearchChange} currentPlanet={this.state.currentPlanet}/>
<PlanetNavigator openLaunchModal={this.openLaunchModal} openAddUserModal={this.openAddUserModal} currentPlanet={this.state.currentPlanet}/>
<PlanetArticleList ref='list' articles={filteredArticles}/>
<PlanetArticleDetail ref='detail' article={article} onOpenEditModal={this.openEditModal} onOpenDeleteModal={this.openDeleteModal}/>
</div>
)
}
})