mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
on Refactoring...
This commit is contained in:
@@ -81,7 +81,7 @@ function searchArticle (search, articles) {
|
|||||||
// Filter end
|
// Filter end
|
||||||
|
|
||||||
function fetchArticles () {
|
function fetchArticles () {
|
||||||
var user = JSON.parse(localStorage.getItem('user'))
|
var user = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
console.log('need to login')
|
console.log('need to login')
|
||||||
return []
|
return []
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
var Reflux = require('reflux')
|
|
||||||
|
|
||||||
module.exports = Reflux.createActions([
|
|
||||||
'login',
|
|
||||||
'register',
|
|
||||||
'logout',
|
|
||||||
'updateProfile',
|
|
||||||
'refreshUser'
|
|
||||||
])
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
var Reflux = require('reflux')
|
|
||||||
|
|
||||||
module.exports = Reflux.createActions([
|
|
||||||
'createPlanet',
|
|
||||||
'fetchPlanet',
|
|
||||||
'deletePlanet',
|
|
||||||
|
|
||||||
'changeName',
|
|
||||||
'addUser',
|
|
||||||
'removeUser',
|
|
||||||
|
|
||||||
'createSnippet',
|
|
||||||
'updateSnippet',
|
|
||||||
'deleteSnippet',
|
|
||||||
|
|
||||||
'createBlueprint',
|
|
||||||
'updateBlueprint',
|
|
||||||
'deleteBlueprint'
|
|
||||||
])
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
var React = require('react')
|
|
||||||
|
|
||||||
var BlueprintForm = require('./BlueprintForm')
|
|
||||||
|
|
||||||
var BlueprintEditModal = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
close: React.PropTypes.func,
|
|
||||||
blueprint: React.PropTypes.object
|
|
||||||
},
|
|
||||||
stopPropagation: function (e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<div onClick={this.stopPropagation} className='BlueprintEditModal modal'>
|
|
||||||
<div className='modal-header'>
|
|
||||||
<h1>Edit Blueprint</h1>
|
|
||||||
</div>
|
|
||||||
<BlueprintForm blueprint={this.props.blueprint} close={this.props.close}/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = BlueprintEditModal
|
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
var React = require('react')
|
var React = require('react')
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var SnippetDeleteModal = React.createClass({
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
close: React.PropTypes.func,
|
planet: React.PropTypes.object,
|
||||||
snippet: React.PropTypes.object
|
code: React.PropTypes.object,
|
||||||
|
close: React.PropTypes.func
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
React.findDOMNode(this).focus()
|
React.findDOMNode(this).focus()
|
||||||
@@ -13,21 +16,22 @@ var SnippetDeleteModal = React.createClass({
|
|||||||
stopPropagation: function (e) {
|
stopPropagation: function (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
},
|
},
|
||||||
handleKeyDown: function (e) {
|
|
||||||
console.log(e)
|
|
||||||
if (e.keyCode === 13 && e.metaKey) {
|
|
||||||
e.preventDefault()
|
|
||||||
this.submit()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
submit: function () {
|
submit: function () {
|
||||||
PlanetActions.deleteSnippet(this.props.snippet.id)
|
var planet = this.props.planet
|
||||||
|
Hq.destroyCode(planet.userName, planet.name, this.props.code.localId)
|
||||||
|
.then(function (res) {
|
||||||
|
PlanetStore.Actions.destroyCode(res.body)
|
||||||
|
this.props.close()
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<div tabIndex='3' onKeyDown={this.handleKeyDown} onClick={this.stopPropagation} className='SnippetDeleteModal modal'>
|
<div className='CodeDeleteModal modal'>
|
||||||
<div className='modal-header'>
|
<div className='modal-header'>
|
||||||
<h1>Delete Snippet</h1>
|
<h1>Delete Code</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className='modal-body'>
|
<div className='modal-body'>
|
||||||
<p>Are you sure to delete it?</p>
|
<p>Are you sure to delete it?</p>
|
||||||
@@ -42,5 +46,3 @@ var SnippetDeleteModal = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = SnippetDeleteModal
|
|
||||||
20
browser/main/Components/CodeEditModal.jsx
Normal file
20
browser/main/Components/CodeEditModal.jsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
var React = require('react')
|
||||||
|
var CodeForm = require('./CodeForm')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
close: React.PropTypes.func,
|
||||||
|
code: React.PropTypes.object,
|
||||||
|
planet: React.PropTypes.object
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div className='CodeEditModal modal'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<h1>Edit Code</h1>
|
||||||
|
</div>
|
||||||
|
<CodeForm code={this.props.code} planet={this.props.planet} close={this.props.close}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
|
|
||||||
var ace = window.ace
|
var ace = window.ace
|
||||||
var CodeEditor = React.createClass({
|
|
||||||
|
module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
code: React.PropTypes.string,
|
code: React.PropTypes.string,
|
||||||
mode: React.PropTypes.string,
|
mode: React.PropTypes.string,
|
||||||
@@ -48,5 +49,3 @@ var CodeEditor = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = CodeEditor
|
|
||||||
|
|||||||
@@ -1,96 +1,99 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
|
||||||
var CodeEditor = require('./CodeEditor')
|
var CodeEditor = require('./CodeEditor')
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
|
||||||
var Select = require('react-select')
|
var Select = require('react-select')
|
||||||
var request = require('superagent')
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
var aceModes = require('../../../modules/ace-modes')
|
var aceModes = require('../../../modules/ace-modes')
|
||||||
|
|
||||||
var getOptions = function (input, callback) {
|
var getOptions = function (input, callback) {
|
||||||
request
|
Hq.searchTag(input)
|
||||||
.get(apiUrl + 'tags/search')
|
.then(function (res) {
|
||||||
.query({name: input})
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
callback(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback(null, {
|
callback(null, {
|
||||||
options: res.body.map(function (tag) {
|
options: res.body.map(function (tag) {
|
||||||
return {
|
return {
|
||||||
label: tag.name,
|
label: tag.name,
|
||||||
value: tag.name
|
value: tag.name
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
complete: false
|
complete: false
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var SnippetForm = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin, ReactRouter.State],
|
mixins: [LinkedState],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
planet: React.PropTypes.object,
|
||||||
close: React.PropTypes.func,
|
close: React.PropTypes.func,
|
||||||
snippet: React.PropTypes.object
|
transitionTo: React.PropTypes.func,
|
||||||
|
code: React.PropTypes.object
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
var snippet = Object.assign({
|
var code = Object.assign({
|
||||||
description: '',
|
description: '',
|
||||||
mode: '',
|
mode: '',
|
||||||
content: '',
|
content: '',
|
||||||
callSign: '',
|
|
||||||
Tags: []
|
Tags: []
|
||||||
}, this.props.snippet)
|
}, this.props.code)
|
||||||
snippet.Tags = snippet.Tags.map(function (tag) {
|
|
||||||
|
code.Tags = code.Tags.map(function (tag) {
|
||||||
return {
|
return {
|
||||||
label: tag.name,
|
label: tag.name,
|
||||||
value: tag.name
|
value: tag.name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
snippet: snippet
|
code: code
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
|
||||||
React.findDOMNode(this.refs.description).focus()
|
|
||||||
},
|
|
||||||
handleModeChange: function (selected) {
|
handleModeChange: function (selected) {
|
||||||
var snippet = this.state.snippet
|
var code = this.state.code
|
||||||
snippet.mode = selected
|
code.mode = selected
|
||||||
console.log(selected, 'selected')
|
this.setState({code: code})
|
||||||
this.setState({snippet: snippet})
|
|
||||||
},
|
},
|
||||||
handleTagsChange: function (selected, all) {
|
handleTagsChange: function (selected, all) {
|
||||||
var snippet = this.state.snippet
|
var code = this.state.code
|
||||||
snippet.Tags = all
|
code.Tags = all
|
||||||
this.setState({snippet: snippet})
|
this.setState({code: code})
|
||||||
},
|
},
|
||||||
handleContentChange: function (e, value) {
|
handleContentChange: function (e, value) {
|
||||||
var snippet = this.state.snippet
|
var code = this.state.code
|
||||||
snippet.content = value
|
code.content = value
|
||||||
this.setState({snippet: snippet})
|
this.setState({code: code})
|
||||||
},
|
},
|
||||||
submit: function () {
|
submit: function () {
|
||||||
var snippet = Object.assign({}, this.state.snippet)
|
var planet = this.props.planet
|
||||||
snippet.Tags = snippet.Tags.map(function (tag) {
|
var code = this.state.code
|
||||||
|
code.Tags = code.Tags.map(function (tag) {
|
||||||
return tag.value
|
return tag.value
|
||||||
})
|
})
|
||||||
if (this.props.snippet == null) {
|
if (this.props.code == null) {
|
||||||
var params = this.getParams()
|
Hq.createCode(planet.userName, planet.name, this.state.code)
|
||||||
var userName = params.userName
|
.then(function (res) {
|
||||||
var planetName = params.planetName
|
var code = res.body
|
||||||
|
PlanetStore.Actions.updateCode(code)
|
||||||
PlanetActions.createSnippet(userName + '/' + planetName, snippet)
|
this.props.close()
|
||||||
|
this.props.transitionTo('codes', {userName: planet.userName, planetName: planet.name, localId: code.localId})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
var snippetId = snippet.id
|
Hq.updateCode(planet.userName, planet.name, this.props.code.localId, this.state.code)
|
||||||
delete snippet.id
|
.then(function (res) {
|
||||||
|
var code = res.body
|
||||||
PlanetActions.updateSnippet(snippetId, snippet)
|
PlanetStore.Actions.updateCode(code)
|
||||||
|
this.props.close()
|
||||||
|
}.bind(this))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleKeyDown: function (e) {
|
handleKeyDown: function (e) {
|
||||||
@@ -107,30 +110,29 @@ var SnippetForm = React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
<div onKeyDown={this.handleKeyDown} className='SnippetForm'>
|
<div className='CodeForm'>
|
||||||
<div className='modal-body'>
|
<div className='modal-body'>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<textarea ref='description' className='snippetDescription block-input' valueLink={this.linkState('snippet.description')} placeholder='Description'/>
|
<textarea ref='description' className='codeDescription block-input' valueLink={this.linkState('code.description')} placeholder='Description'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='inline-input' valueLink={this.linkState('snippet.callSign')} type='text' placeholder='Callsign'/>
|
|
||||||
<Select
|
<Select
|
||||||
name='mode'
|
name='mode'
|
||||||
className='modeSelect'
|
className='modeSelect'
|
||||||
value={this.state.snippet.mode}
|
value={this.state.code.mode}
|
||||||
placeholder='Select Language'
|
placeholder='Select Language'
|
||||||
options={modeOptions}
|
options={modeOptions}
|
||||||
onChange={this.handleModeChange}/>
|
onChange={this.handleModeChange}/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<CodeEditor onChange={this.handleContentChange} code={this.state.snippet.content} mode={this.state.snippet.mode}/>
|
<CodeEditor onChange={this.handleContentChange} code={this.state.code.content} mode={this.state.code.mode}/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<Select
|
<Select
|
||||||
name='Tags'
|
name='Tags'
|
||||||
multi={true}
|
multi={true}
|
||||||
allowCreate={true}
|
allowCreate={true}
|
||||||
value={this.state.snippet.Tags}
|
value={this.state.code.Tags}
|
||||||
placeholder='Tags...'
|
placeholder='Tags...'
|
||||||
asyncOptions={getOptions}
|
asyncOptions={getOptions}
|
||||||
onChange={this.handleTagsChange}
|
onChange={this.handleTagsChange}
|
||||||
@@ -140,12 +142,10 @@ var SnippetForm = React.createClass({
|
|||||||
<div className='modal-footer'>
|
<div className='modal-footer'>
|
||||||
<div className='modal-control'>
|
<div className='modal-control'>
|
||||||
<button onClick={this.props.close} className='btn-default'>Cancel</button>
|
<button onClick={this.props.close} className='btn-default'>Cancel</button>
|
||||||
<button onClick={this.submit} className='btn-primary'>{this.props.snippet == null ? 'Launch' : 'Relaunch'}</button>
|
<button onClick={this.submit} className='btn-primary'>{this.props.code == null ? 'Launch' : 'Relaunch'}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = SnippetForm
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
|
|
||||||
var ace = window.ace
|
var ace = window.ace
|
||||||
var CodeViewer = React.createClass({
|
|
||||||
|
module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
code: React.PropTypes.string,
|
code: React.PropTypes.string,
|
||||||
mode: React.PropTypes.string
|
mode: React.PropTypes.string
|
||||||
@@ -42,5 +43,3 @@ var CodeViewer = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = CodeViewer
|
|
||||||
|
|||||||
167
browser/main/Components/EditProfileModal.jsx
Normal file
167
browser/main/Components/EditProfileModal.jsx
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
|
var React = require('react/addons')
|
||||||
|
|
||||||
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
|
var UserStore = require('../Stores/UserStore')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
mixins: [LinkedState],
|
||||||
|
propTypes: {
|
||||||
|
targetUser: React.PropTypes.shape({
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
profileName: React.PropTypes.string,
|
||||||
|
email: React.PropTypes.string
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getInitialState: function () {
|
||||||
|
var targetUser = this.props.targetUser
|
||||||
|
return {
|
||||||
|
currentTab: 'userInfo',
|
||||||
|
user: {
|
||||||
|
name: targetUser.name,
|
||||||
|
profileName: targetUser.profileName,
|
||||||
|
email: targetUser.email
|
||||||
|
},
|
||||||
|
userSubmitStatus: null,
|
||||||
|
password: {
|
||||||
|
currentPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
passwordConfirmation: ''
|
||||||
|
},
|
||||||
|
passwordSubmitStatus: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectTab: function (tabName) {
|
||||||
|
return function () {
|
||||||
|
this.setState({currentTab: tabName})
|
||||||
|
}.bind(this)
|
||||||
|
},
|
||||||
|
saveUserInfo: function () {
|
||||||
|
this.setState({
|
||||||
|
userSubmitStatus: 'sending'
|
||||||
|
}, function () {
|
||||||
|
Hq.updateUser(this.props.targetUser.name, this.state.user)
|
||||||
|
.then(function (res) {
|
||||||
|
this.setState({userSubmitStatus: 'done'}, function () {
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
||||||
|
UserStore.Actions.update(res.body)
|
||||||
|
})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
this.setState({userSubmitStatus: 'error'})
|
||||||
|
}.bind(this))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
savePassword: function () {
|
||||||
|
this.setState({
|
||||||
|
passwordSubmitStatus: 'sending'
|
||||||
|
}, function () {
|
||||||
|
console.log(this.state.password)
|
||||||
|
Hq.changePassword(this.state.password)
|
||||||
|
.then(function (res) {
|
||||||
|
this.setState({
|
||||||
|
passwordSubmitStatus: 'done',
|
||||||
|
currentPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
passwordConfirmation: ''
|
||||||
|
})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
this.setState({
|
||||||
|
passwordSubmitStatus: 'error',
|
||||||
|
currentPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
passwordConfirmation: ''
|
||||||
|
})
|
||||||
|
}.bind(this))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
var content
|
||||||
|
|
||||||
|
switch (this.state.currentTab) {
|
||||||
|
case 'userInfo':
|
||||||
|
content = this.renderUserInfoTab()
|
||||||
|
break
|
||||||
|
case 'password':
|
||||||
|
content = this.renderPasswordTab()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='EditProfileModal modal'>
|
||||||
|
<div className='leftPane'>
|
||||||
|
<div className='tabLabel'>Edit profile</div>
|
||||||
|
<div className='tabList'>
|
||||||
|
<button className={this.state.currentTab === 'userInfo' ? 'active' : ''} onClick={this.selectTab('userInfo')}><i className='fa fa-user fa-fw'/> User Info</button>
|
||||||
|
<button className={this.state.currentTab === 'password' ? 'active' : ''} onClick={this.selectTab('password')}><i className='fa fa-lock fa-fw'/> Password</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='rightPane'>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renderUserInfoTab: function () {
|
||||||
|
return (
|
||||||
|
<div className='userInfoTab'>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Profile Name</label>
|
||||||
|
<input valueLink={this.linkState('user.profileName')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Name</label>
|
||||||
|
<input valueLink={this.linkState('user.name')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>E-mail</label>
|
||||||
|
<input valueLink={this.linkState('user.email')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formConfirm'>
|
||||||
|
<button disabled={this.state.userSubmitStatus === 'sending'} onClick={this.saveUserInfo}>Save</button>
|
||||||
|
|
||||||
|
<div className={'alertInfo' + (this.state.userSubmitStatus === 'sending' ? '' : ' hide')}>on Sending...</div>
|
||||||
|
|
||||||
|
<div className={'alertError' + (this.state.userSubmitStatus === 'error' ? '' : ' hide')}>Connection failed.. Try again.</div>
|
||||||
|
|
||||||
|
<div className={'alertSuccess' + (this.state.userSubmitStatus === 'done' ? '' : ' hide')}>Successfully done!!</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renderPasswordTab: function () {
|
||||||
|
return (
|
||||||
|
<div className='paswordTab'>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Current password</label>
|
||||||
|
<input valueLink={this.linkState('password.currentPassword')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>New password</label>
|
||||||
|
<input valueLink={this.linkState('password.newPassword')}/>
|
||||||
|
</div>
|
||||||
|
<div className='formField'>
|
||||||
|
<label>Confirmation</label>
|
||||||
|
<input valueLink={this.linkState('password.passwordConfirmation')}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='formConfirm'>
|
||||||
|
<button disabled={this.state.password.newPassword.length === 0 || this.state.password.newPassword !== this.state.password.passwordConfirmation || this.state.passwordSubmitStatus === 'sending'} onClick={this.savePassword}>Save</button>
|
||||||
|
|
||||||
|
<div className={'alertInfo' + (this.state.passwordSubmitStatus === 'sending' ? '' : ' hide')}>on Sending...</div>
|
||||||
|
|
||||||
|
<div className={'alertError' + (this.state.passwordSubmitStatus === 'error' ? '' : ' hide')}>Connection failed.. Try again.</div>
|
||||||
|
|
||||||
|
<div className={'alertSuccess' + (this.state.passwordSubmitStatus === 'done' ? '' : ' hide')}>Successfully done!!</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
154
browser/main/Components/HomeNavigator.jsx
Normal file
154
browser/main/Components/HomeNavigator.jsx
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
|
var React = require('react/addons')
|
||||||
|
var ReactRouter = require('react-router')
|
||||||
|
var Navigation = ReactRouter.Navigation
|
||||||
|
var State = ReactRouter.State
|
||||||
|
var Link = ReactRouter.Link
|
||||||
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
|
var Modal = require('../Mixins/Modal')
|
||||||
|
|
||||||
|
var UserStore = require('../Stores/UserStore')
|
||||||
|
|
||||||
|
var PreferencesModal = require('./PreferencesModal')
|
||||||
|
var PlanetCreateModal = require('./PlanetCreateModal')
|
||||||
|
var ProfileImage = require('./ProfileImage')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
mixins: [Navigation, State, Reflux.listenTo(UserStore, 'onUserChange'), Modal],
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
isPlanetCreateModalOpen: false,
|
||||||
|
currentUser: JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onUserChange: function (res) {
|
||||||
|
switch (res.status) {
|
||||||
|
case 'userUpdated':
|
||||||
|
if (this.state.currentUser.id === res.data.id) {
|
||||||
|
this.setState({currentUser: res.data})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openPreferencesModal: function () {
|
||||||
|
this.openModal(PreferencesModal)
|
||||||
|
},
|
||||||
|
openPlanetCreateModal: function () {
|
||||||
|
this.openModal(PlanetCreateModal, {transitionTo: this.transitionTo})
|
||||||
|
},
|
||||||
|
handleKeyDown: function (e) {
|
||||||
|
if (this.state.currentUser == null) return
|
||||||
|
if (e.metaKey && e.keyCode > 48 && e.keyCode < 58) {
|
||||||
|
var planet = this.state.currentUser.Planets[e.keyCode - 49]
|
||||||
|
if (planet != null) {
|
||||||
|
this.transitionTo('planet', {userName: planet.userName, planetName: planet.name})
|
||||||
|
}
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toggleProfilePopup: function () {
|
||||||
|
this.openProfilePopup()
|
||||||
|
},
|
||||||
|
openProfilePopup: function () {
|
||||||
|
this.setState({isProfilePopupOpen: true}, function () {
|
||||||
|
document.addEventListener('click', this.closeProfilePopup)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeProfilePopup: function () {
|
||||||
|
document.removeEventListener('click', this.closeProfilePopup)
|
||||||
|
this.setState({isProfilePopupOpen: false})
|
||||||
|
},
|
||||||
|
handleLogoutClick: function () {
|
||||||
|
localStorage.removeItem('currentUser')
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
this.transitionTo('login')
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
var params = this.getParams()
|
||||||
|
|
||||||
|
if (this.state.currentUser == null) {
|
||||||
|
return (
|
||||||
|
<div className='HomeNavigator'>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var planets = ((this.state.currentUser == null || this.state.currentUser.Planets == null) ? [] : this.state.currentUser.Planets).map(function (planet, index) {
|
||||||
|
return (
|
||||||
|
<li key={planet.id} className={params.userName === planet.userName && params.planetName === planet.name ? 'active' : ''}>
|
||||||
|
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>
|
||||||
|
{planet.name[0]}
|
||||||
|
<div className='planetTooltip'>{planet.userName}/{planet.name}</div>
|
||||||
|
</Link>
|
||||||
|
<div className='shortCut'>⌘{index + 1}</div>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
var popup = this.renderPopup()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='HomeNavigator'>
|
||||||
|
<button onClick={this.toggleProfilePopup} className='profileButton'>
|
||||||
|
<ProfileImage size='55' email={this.state.currentUser.email}/>
|
||||||
|
</button>
|
||||||
|
{popup}
|
||||||
|
<ul className='planetList'>
|
||||||
|
{planets}
|
||||||
|
</ul>
|
||||||
|
<button onClick={this.openPlanetCreateModal} className='newPlanet'><i className='fa fa-plus'/></button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renderPopup: function () {
|
||||||
|
return (
|
||||||
|
<div ref='profilePopup' className={'profilePopup' + (this.state.isProfilePopupOpen ? '' : ' close')}>
|
||||||
|
<div className='profileGroup'>
|
||||||
|
<div className='profileGroupLabel'>
|
||||||
|
<span>You</span>
|
||||||
|
</div>
|
||||||
|
<ul className='profileGroupList'>
|
||||||
|
<li>
|
||||||
|
<Link to='userHome' params={{userName: this.state.currentUser.name}} className='userName'>Profile</Link>
|
||||||
|
<div className='userSetting'><i className='fa fa-gear'/></div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='profileGroup'>
|
||||||
|
<div className='profileGroupLabel'>
|
||||||
|
<span>Team</span>
|
||||||
|
</div>
|
||||||
|
<ul className='profileGroupList'>
|
||||||
|
<li>
|
||||||
|
<div className='userName'>A team</div>
|
||||||
|
<div className='userSetting'><i className='fa fa-gear'/></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div className='userName'>B team</div>
|
||||||
|
<div className='userSetting'><i className='fa fa-gear'/></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div className='userName'>C team</div>
|
||||||
|
<div className='userSetting'><i className='fa fa-gear'/></div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button className='createNewTeam'><i className='fa fa-plus-square-o'/> create new team</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul className='controlGroup'>
|
||||||
|
<li>
|
||||||
|
<button onClick={this.openPreferencesModal}><i className='fa fa-gear fa-fw'/> Preferences</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button onClick={this.handleLogoutClick}><i className='fa fa-sign-out fa-fw'/> Logout</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,54 +1,56 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
|
||||||
|
|
||||||
var SnippetForm = require('./SnippetForm')
|
var CodeForm = require('./CodeForm')
|
||||||
var BlueprintForm = require('./BlueprintForm')
|
var NoteForm = require('./NoteForm')
|
||||||
|
|
||||||
var LaunchModal = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin, ReactRouter.State],
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
planet: React.PropTypes.object,
|
||||||
|
transitionTo: React.PropTypes.func,
|
||||||
close: React.PropTypes.func
|
close: React.PropTypes.func
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
currentTab: 'snippet'
|
currentTab: 'code'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
componentDidMount: function () {
|
||||||
|
|
||||||
},
|
},
|
||||||
stopPropagation: function (e) {
|
stopPropagation: function (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
},
|
},
|
||||||
selectSnippetTab: function () {
|
selectCodeTab: function () {
|
||||||
this.setState({currentTab: 'snippet'})
|
this.setState({currentTab: 'code'})
|
||||||
},
|
},
|
||||||
selectBlueprintTab: function () {
|
selectNoteTab: function () {
|
||||||
this.setState({currentTab: 'blueprint'})
|
this.setState({currentTab: 'note'})
|
||||||
},
|
},
|
||||||
handleKeyDown: function (e) {
|
handleKeyDown: function (e) {
|
||||||
if (e.keyCode === 37 && e.metaKey) {
|
if (e.keyCode === 37 && e.metaKey) {
|
||||||
this.selectSnippetTab()
|
this.selectCodeTab()
|
||||||
}
|
}
|
||||||
if (e.keyCode === 39 && e.metaKey) {
|
if (e.keyCode === 39 && e.metaKey) {
|
||||||
this.selectBlueprintTab()
|
this.selectNoteTab()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var modalBody
|
var modalBody
|
||||||
if (this.state.currentTab === 'snippet') {
|
if (this.state.currentTab === 'code') {
|
||||||
modalBody = (
|
modalBody = (
|
||||||
<SnippetForm close={this.props.close}/>
|
<CodeForm planet={this.props.planet} transitionTo={this.props.transitionTo} close={this.props.close}/>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
modalBody = (
|
modalBody = (
|
||||||
<BlueprintForm close={this.props.close}/>
|
<NoteForm planet={this.props.planet} transitionTo={this.props.transitionTo} close={this.props.close}/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onKeyDown={this.handleKeyDown} onClick={this.stopPropagation} className='LaunchModal modal'>
|
<div className='LaunchModal modal'>
|
||||||
<div className='modal-header'>
|
<div className='modal-header'>
|
||||||
<div className='modal-tab'>
|
<div className='modal-tab'>
|
||||||
<button className={this.state.currentTab === 'snippet' ? 'btn-primary active' : 'btn-default'} onClick={this.selectSnippetTab}>Snippet</button><button className={this.state.currentTab === 'blueprint' ? 'btn-primary active' : 'btn-default'} onClick={this.selectBlueprintTab}>Blueprint</button>
|
<button className={this.state.currentTab === 'code' ? 'btn-primary active' : 'btn-default'} onClick={this.selectCodeTab}>Code</button><button className={this.state.currentTab === 'note' ? 'btn-primary active' : 'btn-default'} onClick={this.selectNoteTab}>Note</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{modalBody}
|
{modalBody}
|
||||||
@@ -56,5 +58,3 @@ var LaunchModal = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = LaunchModal
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
var React = require('react/addons')
|
|
||||||
|
|
||||||
var ModalBase = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
isOpen: React.PropTypes.bool,
|
|
||||||
children: React.PropTypes.element,
|
|
||||||
close: React.PropTypes.func
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
if (this.props.isOpen) {
|
|
||||||
return (
|
|
||||||
<div ref='modal' onClick={this.props.close} className='ModalBase'>
|
|
||||||
{this.props.children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className='Modal hide'></div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = ModalBase
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
var React = require('react/addons')
|
|
||||||
|
|
||||||
var ModeSelect = React.createClass({
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = ModeSelect
|
|
||||||
@@ -1,32 +1,34 @@
|
|||||||
var React = require('react')
|
var React = require('react')
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var BlueprintDeleteModal = React.createClass({
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
close: React.PropTypes.func,
|
planet: React.PropTypes.object,
|
||||||
blueprint: React.PropTypes.object
|
note: React.PropTypes.object,
|
||||||
|
close: React.PropTypes.func
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
React.findDOMNode(this).focus()
|
React.findDOMNode(this).focus()
|
||||||
},
|
},
|
||||||
stopPropagation: function (e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
},
|
|
||||||
handleKeyDown: function (e) {
|
|
||||||
if ((e.keyCode === 13 && e.metaKey)) {
|
|
||||||
e.preventDefault()
|
|
||||||
this.submit()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
submit: function () {
|
submit: function () {
|
||||||
PlanetActions.deleteBlueprint(this.props.blueprint.id)
|
var planet = this.props.planet
|
||||||
|
Hq.destroyNote(planet.userName, planet.name, this.props.note.localId)
|
||||||
|
.then(function (res) {
|
||||||
|
PlanetStore.Actions.destroyNote(res.body)
|
||||||
|
this.props.close()
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<div tabIndex='3' onKeyDown={this.handleKeyDown} onClick={this.stopPropagation} className='BlueprintDeleteModal modal'>
|
<div className='NoteDeleteModal modal'>
|
||||||
<div className='modal-header'>
|
<div className='modal-header'>
|
||||||
<h1>Delete Blueprint</h1>
|
<h1>Delete Note</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className='modal-body'>
|
<div className='modal-body'>
|
||||||
<p>Are you sure to delete it?</p>
|
<p>Are you sure to delete it?</p>
|
||||||
@@ -41,5 +43,3 @@ var BlueprintDeleteModal = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = BlueprintDeleteModal
|
|
||||||
21
browser/main/Components/NoteEditModal.jsx
Normal file
21
browser/main/Components/NoteEditModal.jsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
var React = require('react')
|
||||||
|
|
||||||
|
var NoteForm = require('./NoteForm')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
close: React.PropTypes.func,
|
||||||
|
note: React.PropTypes.object,
|
||||||
|
planet: React.PropTypes.object
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div className='NoteEditModal modal'>
|
||||||
|
<div className='modal-header'>
|
||||||
|
<h1>Edit Note</h1>
|
||||||
|
</div>
|
||||||
|
<NoteForm note={this.props.note} planet={this.props.planet} close={this.props.close}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,24 +1,19 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var CodeEditor = require('./CodeEditor')
|
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
|
||||||
var Markdown = require('../Mixins/Markdown')
|
|
||||||
var Select = require('react-select')
|
var Select = require('react-select')
|
||||||
var request = require('superagent')
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
var Markdown = require('../Mixins/Markdown')
|
||||||
|
|
||||||
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
|
var CodeEditor = require('./CodeEditor')
|
||||||
|
|
||||||
var getOptions = function (input, callback) {
|
var getOptions = function (input, callback) {
|
||||||
request
|
Hq.searchTag(input)
|
||||||
.get(apiUrl + 'tags/search')
|
.then(function (res) {
|
||||||
.query({name: input})
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
callback(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback(null, {
|
callback(null, {
|
||||||
options: res.body.map(function (tag) {
|
options: res.body.map(function (tag) {
|
||||||
return {
|
return {
|
||||||
@@ -26,96 +21,103 @@ var getOptions = function (input, callback) {
|
|||||||
value: tag.name
|
value: tag.name
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
complete: true
|
complete: false
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var BlueprintForm = React.createClass({
|
var NoteForm = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin, ReactRouter.State, Markdown],
|
mixins: [LinkedState, ReactRouter.State, Markdown],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
planet: React.PropTypes.object,
|
||||||
close: React.PropTypes.func,
|
close: React.PropTypes.func,
|
||||||
blueprint: React.PropTypes.object
|
transitionTo: React.PropTypes.func,
|
||||||
|
note: React.PropTypes.object
|
||||||
},
|
},
|
||||||
statics: {
|
statics: {
|
||||||
EDIT_MODE: 0,
|
EDIT_MODE: 0,
|
||||||
PREVIEW_MODE: 1
|
PREVIEW_MODE: 1
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
var blueprint = Object.assign({
|
var note = Object.assign({
|
||||||
title: '',
|
title: '',
|
||||||
content: '',
|
content: '',
|
||||||
Tags: []
|
Tags: []
|
||||||
}, this.props.blueprint)
|
}, this.props.note)
|
||||||
blueprint.Tags = blueprint.Tags.map(function (tag) {
|
note.Tags = note.Tags.map(function (tag) {
|
||||||
return {
|
return {
|
||||||
label: tag.name,
|
label: tag.name,
|
||||||
value: tag.name
|
value: tag.name
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
blueprint: blueprint,
|
note: note,
|
||||||
mode: BlueprintForm.EDIT_MODE
|
mode: NoteForm.EDIT_MODE
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
React.findDOMNode(this.refs.title).focus()
|
React.findDOMNode(this.refs.title).focus()
|
||||||
},
|
},
|
||||||
handleTagsChange: function (selected, all) {
|
handleTagsChange: function (selected, all) {
|
||||||
var blueprint = this.state.blueprint
|
var note = this.state.note
|
||||||
blueprint.Tags = all
|
note.Tags = all
|
||||||
this.setState({blueprint: blueprint})
|
this.setState({note: note})
|
||||||
},
|
},
|
||||||
handleContentChange: function (e, value) {
|
handleContentChange: function (e, value) {
|
||||||
var blueprint = this.state.blueprint
|
var note = this.state.note
|
||||||
blueprint.content = value
|
note.content = value
|
||||||
this.setState({blueprint: blueprint})
|
this.setState({note: note})
|
||||||
},
|
},
|
||||||
togglePreview: function () {
|
togglePreview: function () {
|
||||||
this.setState({mode: this.state.mode === BlueprintForm.EDIT_MODE ? BlueprintForm.PREVIEW_MODE : BlueprintForm.EDIT_MODE})
|
this.setState({mode: this.state.mode === NoteForm.EDIT_MODE ? NoteForm.PREVIEW_MODE : NoteForm.EDIT_MODE})
|
||||||
},
|
},
|
||||||
submit: function () {
|
submit: function () {
|
||||||
console.log(this.state.blueprint)
|
var planet = this.props.planet
|
||||||
var blueprint = Object.assign({}, this.state.blueprint)
|
var note = this.state.note
|
||||||
blueprint.Tags = blueprint.Tags.map(function (tag) {
|
note.Tags = note.Tags.map(function (tag) {
|
||||||
return tag.value
|
return tag.value
|
||||||
})
|
})
|
||||||
if (this.props.blueprint == null) {
|
|
||||||
var params = this.getParams()
|
|
||||||
var userName = params.userName
|
|
||||||
var planetName = params.planetName
|
|
||||||
|
|
||||||
PlanetActions.createBlueprint(userName + '/' + planetName, blueprint)
|
if (this.props.note == null) {
|
||||||
|
Hq.createNote(planet.userName, planet.name, this.state.note)
|
||||||
|
.then(function (res) {
|
||||||
|
var note = res.body
|
||||||
|
PlanetStore.Actions.updateNote(note)
|
||||||
|
this.props.close()
|
||||||
|
this.props.transitionTo('notes', {userName: planet.userName, planetName: planet.name, localId: note.localId})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
var blueprintId = blueprint.id
|
Hq.updateNote(planet.userName, planet.name, this.props.note.localId, this.state.note)
|
||||||
delete blueprint.id
|
.then(function (res) {
|
||||||
|
var note = res.body
|
||||||
PlanetActions.updateBlueprint(blueprintId, blueprint)
|
PlanetStore.Actions.updateNote(note)
|
||||||
}
|
this.props.close()
|
||||||
},
|
}.bind(this))
|
||||||
handleKeyDown: function (e) {
|
|
||||||
if (e.keyCode === 13 && e.metaKey) {
|
|
||||||
this.submit()
|
|
||||||
e.stopPropagation()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var content = this.state.mode === BlueprintForm.EDIT_MODE ? (
|
var content = this.state.mode === NoteForm.EDIT_MODE ? (
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<CodeEditor onChange={this.handleContentChange} code={this.state.blueprint.content} mode={'markdown'}/>
|
<CodeEditor onChange={this.handleContentChange} code={this.state.note.content} mode={'markdown'}/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className='form-group relative'>
|
<div className='form-group relative'>
|
||||||
<div className='previewMode'>Preview mode</div>
|
<div className='previewMode'>Preview mode</div>
|
||||||
<div className='marked' dangerouslySetInnerHTML={{__html: ' ' + this.markdown(this.state.blueprint.content)}}></div>
|
<div className='marked' dangerouslySetInnerHTML={{__html: ' ' + this.markdown(this.state.note.content)}}></div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onKeyDown={this.handleKeyDown} className='BlueprintForm'>
|
<div className='NoteForm'>
|
||||||
<div className='modal-body'>
|
<div className='modal-body'>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input ref='title' className='block-input' valueLink={this.linkState('blueprint.title')} placeholder='Title'/>
|
<input ref='title' className='block-input' valueLink={this.linkState('note.title')} placeholder='Title'/>
|
||||||
</div>
|
</div>
|
||||||
{content}
|
{content}
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
@@ -123,7 +125,7 @@ var BlueprintForm = React.createClass({
|
|||||||
name='Tags'
|
name='Tags'
|
||||||
multi={true}
|
multi={true}
|
||||||
allowCreate={true}
|
allowCreate={true}
|
||||||
value={this.state.blueprint.Tags}
|
value={this.state.note.Tags}
|
||||||
placeholder='Tags...'
|
placeholder='Tags...'
|
||||||
asyncOptions={getOptions}
|
asyncOptions={getOptions}
|
||||||
onChange={this.handleTagsChange}
|
onChange={this.handleTagsChange}
|
||||||
@@ -132,7 +134,7 @@ var BlueprintForm = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='modal-footer'>
|
<div className='modal-footer'>
|
||||||
<button onClick={this.togglePreview} className={'btn-default' + (this.state.mode === BlueprintForm.PREVIEW_MODE ? ' active' : '')}>Preview mode</button>
|
<button onClick={this.togglePreview} className={'btn-default' + (this.state.mode === NoteForm.PREVIEW_MODE ? ' active' : '')}>Preview mode</button>
|
||||||
<div className='modal-control'>
|
<div className='modal-control'>
|
||||||
<button onClick={this.props.close} className='btn-default'>Cancel</button>
|
<button onClick={this.props.close} className='btn-default'>Cancel</button>
|
||||||
<button onClick={this.submit} className='btn-primary'>Launch</button>
|
<button onClick={this.submit} className='btn-primary'>Launch</button>
|
||||||
@@ -143,4 +145,4 @@ var BlueprintForm = React.createClass({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = BlueprintForm
|
module.exports = NoteForm
|
||||||
@@ -3,22 +3,45 @@ var moment = require('moment')
|
|||||||
|
|
||||||
var CodeViewer = require('../Components/CodeViewer')
|
var CodeViewer = require('../Components/CodeViewer')
|
||||||
|
|
||||||
|
var CodeEditModal = require('../Components/CodeEditModal')
|
||||||
|
var CodeDeleteModal = require('../Components/CodeDeleteModal')
|
||||||
|
var NoteEditModal = require('../Components/NoteEditModal')
|
||||||
|
var NoteDeleteModal = require('../Components/NoteDeleteModal')
|
||||||
|
|
||||||
|
var Modal = require('../Mixins/Modal')
|
||||||
var ForceUpdate = require('../Mixins/ForceUpdate')
|
var ForceUpdate = require('../Mixins/ForceUpdate')
|
||||||
var Markdown = require('../Mixins/Markdown')
|
var Markdown = require('../Mixins/Markdown')
|
||||||
|
|
||||||
var PlanetArticleDetail = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [ForceUpdate(60000), Markdown],
|
mixins: [ForceUpdate(60000), Markdown, Modal],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
article: React.PropTypes.object,
|
article: React.PropTypes.object,
|
||||||
onOpenEditModal: React.PropTypes.func,
|
showOnlyWithTag: React.PropTypes.func,
|
||||||
onOpenDeleteModal: React.PropTypes.func,
|
planet: React.PropTypes.object
|
||||||
showOnlyWithTag: React.PropTypes.func
|
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
isEditModalOpen: false
|
isEditModalOpen: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
openEditModal: function () {
|
||||||
|
switch (this.props.article.type) {
|
||||||
|
case 'code' :
|
||||||
|
this.openModal(CodeEditModal, {code: this.props.article, planet: this.props.planet})
|
||||||
|
break
|
||||||
|
case 'note' :
|
||||||
|
this.openModal(NoteEditModal, {note: this.props.article, planet: this.props.planet})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openDeleteModal: function () {
|
||||||
|
switch (this.props.article.type) {
|
||||||
|
case 'code' :
|
||||||
|
this.openModal(CodeDeleteModal, {code: this.props.article, planet: this.props.planet})
|
||||||
|
break
|
||||||
|
case 'note' :
|
||||||
|
this.openModal(NoteDeleteModal, {note: this.props.article, planet: this.props.planet})
|
||||||
|
}
|
||||||
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var article = this.props.article
|
var article = this.props.article
|
||||||
if (article == null) {
|
if (article == null) {
|
||||||
@@ -35,14 +58,14 @@ var PlanetArticleDetail = React.createClass({
|
|||||||
}.bind(this)) : (
|
}.bind(this)) : (
|
||||||
<a className='noTag'>Not tagged yet</a>
|
<a className='noTag'>Not tagged yet</a>
|
||||||
)
|
)
|
||||||
if (article.type === 'snippet') {
|
if (article.type === 'code') {
|
||||||
return (
|
return (
|
||||||
<div className='PlanetArticleDetail snippetDetail'>
|
<div className='PlanetArticleDetail codeDetail'>
|
||||||
<div className='viewer-header'>
|
<div className='viewer-header'>
|
||||||
<i className='fa fa-code fa-fw'></i> {article.callSign} <small className='updatedAt'>{moment(article.updatedAt).fromNow()}</small>
|
<i className='fa fa-code fa-fw'></i> {article.callSign} <small className='updatedAt'>{moment(article.updatedAt).fromNow()}</small>
|
||||||
<span className='control-group'>
|
<span className='control-group'>
|
||||||
<button onClick={this.props.onOpenEditModal} className='btn-default btn-square btn-sm'><i className='fa fa-edit fa-fw'></i></button>
|
<button onClick={this.openEditModal} className='btn-default btn-square btn-sm'><i className='fa fa-edit fa-fw'></i></button>
|
||||||
<button onClick={this.props.onOpenDeleteModal} className='btn-default btn-square btn-sm'><i className='fa fa-trash fa-fw'></i></button>
|
<button onClick={this.openDeleteModal} className='btn-default btn-square btn-sm'><i className='fa fa-trash fa-fw'></i></button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='viewer-body'>
|
<div className='viewer-body'>
|
||||||
@@ -58,12 +81,12 @@ var PlanetArticleDetail = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className='PlanetArticleDetail blueprintDetail'>
|
<div className='PlanetArticleDetail noteDetail'>
|
||||||
<div className='viewer-header'>
|
<div className='viewer-header'>
|
||||||
<i className='fa fa-file-text-o fa-fw'></i> {article.title} <small className='updatedAt'>{moment(article.updatedAt).fromNow()}</small>
|
<i className='fa fa-file-text-o fa-fw'></i> {article.title} <small className='updatedAt'>{moment(article.updatedAt).fromNow()}</small>
|
||||||
<span className='control-group'>
|
<span className='control-group'>
|
||||||
<button onClick={this.props.onOpenEditModal} className='btn-default btn-square btn-sm'><i className='fa fa-edit fa-fw'></i></button>
|
<button onClick={this.openEditModal} className='btn-default btn-square btn-sm'><i className='fa fa-edit fa-fw'></i></button>
|
||||||
<button onClick={this.props.onOpenDeleteModal} className='btn-default btn-square btn-sm'><i className='fa fa-trash fa-fw'></i></button>
|
<button onClick={this.openDeleteModal} className='btn-default btn-square btn-sm'><i className='fa fa-trash fa-fw'></i></button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='viewer-body'>
|
<div className='viewer-body'>
|
||||||
@@ -74,5 +97,3 @@ var PlanetArticleDetail = React.createClass({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = PlanetArticleDetail
|
|
||||||
|
|||||||
@@ -5,15 +5,14 @@ var moment = require('moment')
|
|||||||
var ForceUpdate = require('../Mixins/ForceUpdate')
|
var ForceUpdate = require('../Mixins/ForceUpdate')
|
||||||
var Markdown = require('../Mixins/Markdown')
|
var Markdown = require('../Mixins/Markdown')
|
||||||
|
|
||||||
var PlanetArticleList = React.createClass({
|
var ProfileImage = require('../Components/ProfileImage')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
mixins: [ReactRouter.Navigation, ReactRouter.State, ForceUpdate(60000), Markdown],
|
mixins: [ReactRouter.Navigation, ReactRouter.State, ForceUpdate(60000), Markdown],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
articles: React.PropTypes.array,
|
articles: React.PropTypes.array,
|
||||||
showOnlyWithTag: React.PropTypes.func
|
showOnlyWithTag: React.PropTypes.func
|
||||||
},
|
},
|
||||||
handleKeyDown: function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
},
|
|
||||||
render: function () {
|
render: function () {
|
||||||
var articles = this.props.articles.map(function (article) {
|
var articles = this.props.articles.map(function (article) {
|
||||||
var tags = article.Tags.length > 0 ? article.Tags.map(function (tag) {
|
var tags = article.Tags.length > 0 ? article.Tags.map(function (tag) {
|
||||||
@@ -24,14 +23,14 @@ var PlanetArticleList = React.createClass({
|
|||||||
<a className='noTag'>Not tagged yet</a>
|
<a className='noTag'>Not tagged yet</a>
|
||||||
)
|
)
|
||||||
var params = this.getParams()
|
var params = this.getParams()
|
||||||
var isActive = article.type === 'snippet' ? this.isActive('snippets') && parseInt(params.localId, 10) === article.localId : this.isActive('blueprints') && parseInt(params.localId, 10) === article.localId
|
var isActive = article.type === 'code' ? this.isActive('codes') && parseInt(params.localId, 10) === article.localId : this.isActive('notes') && parseInt(params.localId, 10) === article.localId
|
||||||
|
|
||||||
var handleClick
|
var handleClick
|
||||||
|
|
||||||
if (article.type === 'snippet') {
|
if (article.type === 'code') {
|
||||||
|
|
||||||
handleClick = function () {
|
handleClick = function () {
|
||||||
this.transitionTo('snippets', {
|
this.transitionTo('codes', {
|
||||||
userName: params.userName,
|
userName: params.userName,
|
||||||
planetName: params.planetName,
|
planetName: params.planetName,
|
||||||
localId: article.localId
|
localId: article.localId
|
||||||
@@ -39,14 +38,17 @@ var PlanetArticleList = React.createClass({
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li onClick={handleClick} key={'snippet-' + article.id}>
|
<li onClick={handleClick} key={'code-' + article.id}>
|
||||||
<div className={'articleItem snippetItem' + (isActive ? ' active' : '')}>
|
<div className={'articleItem' + (isActive ? ' active' : '')}>
|
||||||
<div className='itemHeader'>
|
<div className='itemLeft'>
|
||||||
<div className='callSign'><i className='fa fa-code fa-fw'></i> {article.callSign}</div>
|
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||||
<div className='updatedAt'>{moment(article.updatedAt).fromNow()}</div>
|
<i className='fa fa-code fa-fw'></i>
|
||||||
|
</div>
|
||||||
|
<div className='itemRight'>
|
||||||
|
<div className='updatedAt'>{moment(article.updatedAt).fromNow()}</div>
|
||||||
|
<div className='description'>{article.description.length > 50 ? article.description.substring(0, 50) + ' …' : article.description}</div>
|
||||||
|
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='description'>{article.description.length > 50 ? article.description.substring(0, 50) + ' …' : article.description}</div>
|
|
||||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='divider'></div>
|
<div className='divider'></div>
|
||||||
</li>
|
</li>
|
||||||
@@ -54,7 +56,7 @@ var PlanetArticleList = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleClick = function () {
|
handleClick = function () {
|
||||||
this.transitionTo('blueprints', {
|
this.transitionTo('notes', {
|
||||||
userName: params.userName,
|
userName: params.userName,
|
||||||
planetName: params.planetName,
|
planetName: params.planetName,
|
||||||
localId: article.localId
|
localId: article.localId
|
||||||
@@ -62,13 +64,18 @@ var PlanetArticleList = React.createClass({
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li onClick={handleClick} key={'blueprint-' + article.id}>
|
<li onClick={handleClick} key={'note-' + article.id}>
|
||||||
<div className={'articleItem blueprintItem' + (isActive ? ' active' : '')}>
|
<div className={'articleItem blueprintItem' + (isActive ? ' active' : '')}>
|
||||||
<div className='itemHeader'>
|
<div className='itemLeft'>
|
||||||
<div className='callSign'><i className='fa fa-file-text-o fa-fw'></i> {article.title}</div>
|
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||||
<div className='updatedAt'>{moment(article.updatedAt).fromNow()}</div>
|
<i className='fa fa-file-text-o fa-fw'></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='itemRight'>
|
||||||
|
<div className='updatedAt'>{moment(article.updatedAt).fromNow()}</div>
|
||||||
|
<div className='description'>{article.title}</div>
|
||||||
|
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='divider'></div>
|
<div className='divider'></div>
|
||||||
</li>
|
</li>
|
||||||
@@ -78,12 +85,10 @@ var PlanetArticleList = React.createClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='PlanetArticleList'>
|
<div className='PlanetArticleList'>
|
||||||
<ul onKeyDown={this.handleKeyDown} tabIndex='2'>
|
<ul>
|
||||||
{articles}
|
{articles}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = PlanetArticleList
|
|
||||||
|
|||||||
@@ -1,26 +1,34 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
var Select = require('react-select')
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
|
var UserStore = require('../Stores/UserStore')
|
||||||
var PlanetStore = require('../Stores/PlanetStore')
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin],
|
mixins: [LinkedState],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
transitionTo: React.PropTypes.func,
|
||||||
close: React.PropTypes.func
|
close: React.PropTypes.func
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
|
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
return {
|
return {
|
||||||
planetName: ''
|
user: currentUser,
|
||||||
|
planet: {
|
||||||
|
name: '',
|
||||||
|
OwnerId: currentUser.id,
|
||||||
|
public: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
React.findDOMNode(this.refs.name).focus()
|
React.findDOMNode(this.refs.name).focus()
|
||||||
this.unsubscribe = PlanetStore.listen(this.onListen)
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribe()
|
|
||||||
},
|
},
|
||||||
onListen: function (res) {
|
onListen: function (res) {
|
||||||
if (res.status === 'planetCreated') {
|
if (res.status === 'planetCreated') {
|
||||||
@@ -28,26 +36,47 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleSubmit: function () {
|
handleSubmit: function () {
|
||||||
PlanetActions.createPlanet({
|
Hq.createPlanet(this.state.user.name, this.state.planet)
|
||||||
name: this.state.planetName
|
.then(function (res) {
|
||||||
})
|
var planet = res.body
|
||||||
},
|
|
||||||
handleKeyDown: function (e) {
|
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
if (e.keyCode === 13 && e.metaKey) {
|
|
||||||
this.handleSubmit()
|
var isNew = !currentUser.Planets.some(function (_planet, index) {
|
||||||
return
|
if (planet.id === _planet) {
|
||||||
}
|
currentUser.Planets.splice(index, 1, planet)
|
||||||
if (e.keyCode === 27) {
|
return true
|
||||||
this.props.close()
|
}
|
||||||
}
|
return false
|
||||||
},
|
})
|
||||||
stopPropagation: function (e) {
|
if (isNew) currentUser.Planets.push(planet)
|
||||||
e.stopPropagation()
|
|
||||||
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
|
UserStore.Actions.update(currentUser)
|
||||||
|
this.props.transitionTo('planetHome', {userName: planet.userName, planetName: planet.name})
|
||||||
|
this.props.close()
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<div tabIndex='3' onKeyDown={this.handleKeyDown} onClick={this.stopPropagation} className='PlanetCreateModal modal'>
|
<div className='PlanetCreateModal modal'>
|
||||||
<input ref='name' valueLink={this.linkState('planetName')} className='nameInput stripInput' placeholder='Crate new Planet'/>
|
<input ref='name' valueLink={this.linkState('planet.name')} className='nameInput stripInput' placeholder='Crate new Planet'/>
|
||||||
|
|
||||||
|
<div className='formField'>
|
||||||
|
of
|
||||||
|
<select valueLink={this.linkState('planet.OwnerId')}>
|
||||||
|
<option value={this.state.user.id}>Me({this.state.user.name})</option>
|
||||||
|
</select>
|
||||||
|
as
|
||||||
|
<select valueLink={this.linkState('planet.public')}>
|
||||||
|
<option value={true}>Public</option>
|
||||||
|
<option value={false}>Private</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button onClick={this.handleSubmit} className='submitButton'>
|
<button onClick={this.handleSubmit} className='submitButton'>
|
||||||
<i className='fa fa-check'/>
|
<i className='fa fa-check'/>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
|
var shell = require('shell')
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
module.exports = React.createClass({
|
||||||
|
|
||||||
var PlanetHeader = React.createClass({
|
|
||||||
mixins: [ReactRouter.State],
|
mixins: [ReactRouter.State],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
openSettingModal: React.PropTypes.func,
|
|
||||||
currentPlanet: React.PropTypes.object,
|
|
||||||
onSearchChange: React.PropTypes.func,
|
|
||||||
search: React.PropTypes.string,
|
search: React.PropTypes.string,
|
||||||
openPersonalSettingModal: React.PropTypes.func
|
fetchPlanet: React.PropTypes.func,
|
||||||
|
onSearchChange: React.PropTypes.func,
|
||||||
|
currentPlanet: React.PropTypes.object
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
@@ -20,37 +19,37 @@ var PlanetHeader = React.createClass({
|
|||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
React.findDOMNode(this.refs.search).focus()
|
React.findDOMNode(this.refs.search).focus()
|
||||||
},
|
},
|
||||||
interceptClick: function (e) {
|
handleLogoClick: function (e) {
|
||||||
e.stopPropagation()
|
shell.openExternal('http://b00st.io')
|
||||||
|
e.preventDefault()
|
||||||
},
|
},
|
||||||
refreshPlanet: function () {
|
refresh: function () {
|
||||||
var params = this.getParams()
|
this.props.fetchPlanet()
|
||||||
PlanetActions.fetchPlanet(params.userName, params.planetName)
|
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var currentPlanetName = this.props.currentPlanet.name
|
var currentPlanetName = this.props.currentPlanet.name
|
||||||
var currentUserName = this.props.currentPlanet.userName
|
var currentUserName = this.props.currentPlanet.userName
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={this.interceptClick} className='PlanetHeader'>
|
<div className='PlanetHeader'>
|
||||||
<div className='headerLabel'>
|
<div className='headerLabel'>
|
||||||
<span className='userName'>{currentUserName}</span><br/>
|
<span className='userName'>{currentUserName}</span><br/>
|
||||||
<span className='planetName'>{currentPlanetName}</span>
|
<span className='planetName'>{currentPlanetName}</span>
|
||||||
<button onClick={this.props.openSettingModal} className='menuBtn'>
|
<button className='menuBtn'>
|
||||||
<i className='fa fa-chevron-down'></i>
|
<i className='fa fa-chevron-down'></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className='headerControl'>
|
<div className='headerControl'>
|
||||||
<div className='searchInput'>
|
<div className='searchInput'>
|
||||||
<i className='fa fa-search'/>
|
<i className='fa fa-search'/>
|
||||||
<input onChange={this.props.onSearchChange} value={this.props.search} ref='search' tabIndex='1' type='text' className='inline-input circleInput' placeholder='Search...'/>
|
<input onChange={this.props.onSearchChange} value={this.props.search} ref='search' type='text' className='inline-input circleInput' placeholder='Search...'/>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={this.refreshPlanet} className='refreshButton'><i className='fa fa-refresh'/></button>
|
<button onClick={this.refresh} className='refreshButton'><i className='fa fa-refresh'/></button>
|
||||||
<button onClick={this.props.openPersonalSettingModal} className='settingButton'><i className='fa fa-gears'/></button>
|
<a onClick={this.handleLogoClick} href='http://b00st.io' className='logo'>
|
||||||
|
<img width='44' height='44' src='resources/favicon-230x230.png'/>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = PlanetHeader
|
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var Link = ReactRouter.Link
|
var Navigation = ReactRouter.Navigation
|
||||||
|
|
||||||
var ProfileImage = require('./ProfileImage')
|
var Modal = require('../Mixins/Modal')
|
||||||
|
var LaunchModal = require('../Components/LaunchModal')
|
||||||
|
|
||||||
var PlanetNavigator = React.createClass({
|
var PlanetNavigator = React.createClass({
|
||||||
|
mixins: [Modal, Navigation],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
currentPlanet: React.PropTypes.shape({
|
planet: React.PropTypes.shape({
|
||||||
name: React.PropTypes.string,
|
name: React.PropTypes.string
|
||||||
Users: React.PropTypes.array
|
|
||||||
}),
|
}),
|
||||||
search: React.PropTypes.string,
|
search: React.PropTypes.string,
|
||||||
openLaunchModal: React.PropTypes.func,
|
toggleCodeFilter: React.PropTypes.func,
|
||||||
openAddUserModal: React.PropTypes.func,
|
toggleNoteFilter: React.PropTypes.func
|
||||||
toggleSnippetFilter: React.PropTypes.func,
|
|
||||||
toggleBlueprintFilter: React.PropTypes.func
|
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
@@ -24,46 +23,33 @@ var PlanetNavigator = React.createClass({
|
|||||||
submitLaunchModal: function (ret) {
|
submitLaunchModal: function (ret) {
|
||||||
this.setState({isLaunchModalOpen: false})
|
this.setState({isLaunchModalOpen: false})
|
||||||
},
|
},
|
||||||
|
openLaunchModal: function () {
|
||||||
|
this.openModal(LaunchModal, {planet: this.props.planet, transitionTo: this.transitionTo})
|
||||||
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var users = this.props.currentPlanet.Users.map(function (user) {
|
|
||||||
return (
|
|
||||||
<li key={'user-' + user.id}>
|
|
||||||
<Link to='user' params={{userName: user.name}}>
|
|
||||||
<ProfileImage className='userPhoto' size='44' email={user.email}/>
|
|
||||||
<div className='userTooltip'>{user.profileName}</div>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
var keywords = this.props.search.split(' ')
|
var keywords = this.props.search.split(' ')
|
||||||
var usingSnippetFilter = keywords.some(function (keyword) {
|
var usingCodeFilter = keywords.some(function (keyword) {
|
||||||
if (keyword === '$s') return true
|
if (keyword === '$c') return true
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
var usingBlueprintFilter = keywords.some(function (keyword) {
|
var usingNoteFilter = keywords.some(function (keyword) {
|
||||||
if (keyword === '$b') return true
|
if (keyword === '$n') return true
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='PlanetNavigator'>
|
<div className='PlanetNavigator'>
|
||||||
<button onClick={this.props.openLaunchModal} className='launchButton btn-primary btn-block'>
|
<button onClick={this.openLaunchModal} className='launchButton btn-primary btn-block'>
|
||||||
<i className='fa fa-rocket fa-fw'/> Launch
|
<i className='fa fa-rocket fa-fw'/> Launch
|
||||||
</button>
|
</button>
|
||||||
<nav>
|
<nav>
|
||||||
<a className={usingSnippetFilter && !usingBlueprintFilter ? 'active' : ''} onClick={this.props.toggleSnippetFilter}>
|
<a className={usingCodeFilter && !usingNoteFilter ? 'active' : ''} onClick={this.props.toggleCodeFilter}>
|
||||||
<i className='fa fa-code fa-fw'/> Snippets
|
<i className='fa fa-code fa-fw'/> Codes
|
||||||
</a>
|
</a>
|
||||||
<a className={!usingSnippetFilter && usingBlueprintFilter ? 'active' : ''} onClick={this.props.toggleBlueprintFilter}>
|
<a className={!usingCodeFilter && usingNoteFilter ? 'active' : ''} onClick={this.props.toggleNoteFilter}>
|
||||||
<i className='fa fa-file-text-o fa-fw'/> Blueprints
|
<i className='fa fa-file-text-o fa-fw'/> Notes
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div className='usersLabel'>Users</div>
|
|
||||||
<ul className='users'>
|
|
||||||
{users}
|
|
||||||
<li onClick={this.props.openAddUserModal} className='addUserButton btn-default'><i className='fa fa-plus'/></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,10 @@
|
|||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var request = require('superagent')
|
|
||||||
var Select = require('react-select')
|
var Select = require('react-select')
|
||||||
|
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
var Catalyst = require('../Mixins/Catalyst')
|
||||||
|
|
||||||
var ProfileImage = require('./ProfileImage')
|
var ProfileImage = require('./ProfileImage')
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
|
||||||
|
|
||||||
var getOptions = function (input, callback) {
|
|
||||||
request
|
|
||||||
.get(apiUrl + 'users/search')
|
|
||||||
.query({name: input})
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
callback(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback(null, {
|
|
||||||
options: res.body.map(function (user) {
|
|
||||||
return {
|
|
||||||
label: user.name,
|
|
||||||
value: user.name
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
complete: false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin],
|
mixins: [Catalyst.LinkedStateMixin],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
@@ -48,10 +21,6 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
activePlanetProfile: function () {
|
activePlanetProfile: function () {
|
||||||
this.setState({currentTab: 'planetProfile'})
|
this.setState({currentTab: 'planetProfile'})
|
||||||
|
|
||||||
},
|
|
||||||
activeMembers: function () {
|
|
||||||
this.setState({currentTab: 'members'})
|
|
||||||
},
|
},
|
||||||
saveProfile: function () {
|
saveProfile: function () {
|
||||||
var currentPlanet = this.props.currentPlanet
|
var currentPlanet = this.props.currentPlanet
|
||||||
@@ -60,14 +29,6 @@ module.exports = React.createClass({
|
|||||||
handleChange: function (value) {
|
handleChange: function (value) {
|
||||||
this.setState({userName: value})
|
this.setState({userName: value})
|
||||||
},
|
},
|
||||||
addUser: function () {
|
|
||||||
PlanetActions.addUser(this.props.currentPlanet.userName + '/' + this.props.currentPlanet.name, this.state.userName)
|
|
||||||
},
|
|
||||||
removeUser: function (userName) {
|
|
||||||
return function () {
|
|
||||||
PlanetActions.removeUser(this.props.currentPlanet.userName + '/' + this.props.currentPlanet.name, userName)
|
|
||||||
}.bind(this)
|
|
||||||
},
|
|
||||||
doubleCheckDeletePlanet: function () {
|
doubleCheckDeletePlanet: function () {
|
||||||
if (this.state.isDeletePlanetChecked) {
|
if (this.state.isDeletePlanetChecked) {
|
||||||
PlanetActions.deletePlanet(this.props.currentPlanet.userName, this.props.currentPlanet.name)
|
PlanetActions.deletePlanet(this.props.currentPlanet.userName, this.props.currentPlanet.name)
|
||||||
@@ -84,61 +45,26 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var content
|
var content
|
||||||
if (this.state.currentTab === 'planetProfile') {
|
|
||||||
content = (
|
|
||||||
<div className='planetProfile'>
|
|
||||||
<div className='planetProfileForm'>
|
|
||||||
<label>Planet name </label>
|
|
||||||
<input valueLink={this.linkState('planetName')} className='inline-input'/>
|
|
||||||
<button onClick={this.saveProfile} className='saveButton btn-primary'>Save</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='planetDeleteForm'>
|
content = (
|
||||||
<div className='planetDeleteControl'>
|
<div className='planetProfile'>
|
||||||
<div className={'toggle' + (this.state.isDeletePlanetChecked ? '' : ' hide')}>
|
<div className='planetProfileForm'>
|
||||||
<div className='planetDeleteLabel'>Are you sure to delete this planet?</div>
|
<label>Planet name </label>
|
||||||
<button ref='deleteCancelButton' onClick={this.cancelDeletePlanet} className='cancelButton btn-default'>Cancel</button>
|
<input valueLink={this.linkState('planetName')} className='inline-input'/>
|
||||||
</div>
|
<button onClick={this.saveProfile} className='saveButton btn-primary'>Save</button>
|
||||||
<button onClick={this.doubleCheckDeletePlanet} className='deleteButton btn-primary'>{!this.state.isDeletePlanetChecked ? 'Delete Planet' : 'Confirm'}</button>
|
</div>
|
||||||
|
|
||||||
|
<div className='planetDeleteForm'>
|
||||||
|
<div className='planetDeleteControl'>
|
||||||
|
<div className={'toggle' + (this.state.isDeletePlanetChecked ? '' : ' hide')}>
|
||||||
|
<div className='planetDeleteLabel'>Are you sure to delete this planet?</div>
|
||||||
|
<button ref='deleteCancelButton' onClick={this.cancelDeletePlanet} className='cancelButton btn-default'>Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button onClick={this.doubleCheckDeletePlanet} className='deleteButton btn-primary'>{!this.state.isDeletePlanetChecked ? 'Delete Planet' : 'Confirm'}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
} else {
|
)
|
||||||
var members = this.props.currentPlanet.Users.map(function (user) {
|
|
||||||
return (
|
|
||||||
<li key={'user-' + user.id}>
|
|
||||||
<ProfileImage className='userPhoto' size='44' email={user.email}/>
|
|
||||||
<div className='userName'>{user.name}</div>
|
|
||||||
<div className='userControl'>
|
|
||||||
{this.props.currentPlanet.OwnerId !== user.id ? <button onClick={this.removeUser(user.name)} className='btn-default'>Delete</button> : <span className='ownerLabel'>Owner</span>}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}.bind(this))
|
|
||||||
|
|
||||||
content = (
|
|
||||||
<div className='members'>
|
|
||||||
<ul className='userList'>
|
|
||||||
{members}
|
|
||||||
</ul>
|
|
||||||
<div className='addUserForm'>
|
|
||||||
<div className='addUserLabel'>Invite user</div>
|
|
||||||
<div className='addUserControl'>
|
|
||||||
<Select
|
|
||||||
name='userName'
|
|
||||||
value={this.state.userName}
|
|
||||||
placeholder='Username'
|
|
||||||
asyncOptions={getOptions}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
className='addUserSelect'
|
|
||||||
/>
|
|
||||||
<button onClick={this.addUser} className='addUserSubmit btn-primary'>Invite</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={this.interceptClick} className='PlanetSettingModal modal'>
|
<div onClick={this.interceptClick} className='PlanetSettingModal modal'>
|
||||||
@@ -146,7 +72,6 @@ module.exports = React.createClass({
|
|||||||
<h1>Planet setting</h1>
|
<h1>Planet setting</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<button className={this.state.currentTab === 'planetProfile' ? 'active' : ''} onClick={this.activePlanetProfile}><i className='fa fa-globe fa-fw'/> Planet profile</button>
|
<button className={this.state.currentTab === 'planetProfile' ? 'active' : ''} onClick={this.activePlanetProfile}><i className='fa fa-globe fa-fw'/> Planet profile</button>
|
||||||
<button className={this.state.currentTab === 'members' ? 'active' : ''} onClick={this.activeMembers}><i className='fa fa-group fa-fw'/> Members</button>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
/* global localStorage */
|
/* global localStorage */
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
|
var ReactRouter = require('react-router')
|
||||||
|
var Navigation = ReactRouter.Navigation
|
||||||
var request = require('superagent')
|
var request = require('superagent')
|
||||||
|
|
||||||
var Catalyst = require('../Mixins/Catalyst')
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
|
||||||
var ProfileImage = require('./ProfileImage')
|
var ProfileImage = require('./ProfileImage')
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
var apiUrl = require('../../../config').apiUrl
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Catalyst.LinkedStateMixin],
|
mixins: [LinkedState, Navigation],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
close: React.PropTypes.func,
|
close: React.PropTypes.func,
|
||||||
currentUser: React.PropTypes.object
|
currentUser: React.PropTypes.object
|
||||||
@@ -32,10 +30,8 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
this.unsubscribe = AuthStore.listen(this.onListen)
|
|
||||||
},
|
},
|
||||||
componentWillUnmount: function () {
|
componentWillUnmount: function () {
|
||||||
this.unsubscribe()
|
|
||||||
},
|
},
|
||||||
onListen: function (res) {
|
onListen: function (res) {
|
||||||
console.log(res)
|
console.log(res)
|
||||||
@@ -70,17 +66,6 @@ module.exports = React.createClass({
|
|||||||
this.setState({currentTab: 'logout'})
|
this.setState({currentTab: 'logout'})
|
||||||
},
|
},
|
||||||
saveProfile: function () {
|
saveProfile: function () {
|
||||||
this.setState({
|
|
||||||
isUpdatingProfile: true,
|
|
||||||
isUpdatingProfileDone: false,
|
|
||||||
isUpdatingProfileFailed: false
|
|
||||||
}, function () {
|
|
||||||
AuthActions.updateProfile({
|
|
||||||
profileName: this.state.profileName,
|
|
||||||
name: this.state.userName,
|
|
||||||
email: this.state.email
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
savePassword: function () {
|
savePassword: function () {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -160,7 +145,8 @@ module.exports = React.createClass({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
logOut: function () {
|
logOut: function () {
|
||||||
AuthActions.logout()
|
localStorage.removeItem('currentUser')
|
||||||
|
localStorage.removeItem('token')
|
||||||
},
|
},
|
||||||
interceptClick: function (e) {
|
interceptClick: function (e) {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
var React = require('react')
|
|
||||||
var SnippetForm = require('./SnippetForm')
|
|
||||||
|
|
||||||
var SnippetEditModal = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
close: React.PropTypes.func,
|
|
||||||
snippet: React.PropTypes.object
|
|
||||||
},
|
|
||||||
stopPropagation: function (e) {
|
|
||||||
e.stopPropagation()
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<div onClick={this.stopPropagation} className='SnippetEditModal modal'>
|
|
||||||
<div className='modal-header'>
|
|
||||||
<h1>Edit Snippet</h1>
|
|
||||||
</div>
|
|
||||||
<SnippetForm snippet={this.props.snippet} close={this.props.close}/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = SnippetEditModal
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
var React = require('react/addons')
|
|
||||||
var ReactRouter = require('react-router')
|
|
||||||
var Link = ReactRouter.Link
|
|
||||||
|
|
||||||
var ModalBase = require('./ModalBase')
|
|
||||||
var PlanetCreateModal = require('./PlanetCreateModal')
|
|
||||||
var ProfileImage = require('./ProfileImage')
|
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
mixins: [ReactRouter.Navigation, ReactRouter.State],
|
|
||||||
propTypes: {
|
|
||||||
currentPlanet: React.PropTypes.object,
|
|
||||||
currentUser: React.PropTypes.object
|
|
||||||
},
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
isPlanetCreateModalOpen: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
componentDidMount: function () {
|
|
||||||
this.unsubscribe = AuthStore.listen(this.onLogout)
|
|
||||||
document.addEventListener('keydown', this.handleKeyDown)
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribe()
|
|
||||||
document.removeEventListener('keydown', this.handleKeyDown)
|
|
||||||
},
|
|
||||||
onLogout: function () {
|
|
||||||
this.transitionTo('login')
|
|
||||||
},
|
|
||||||
openPersonalSettingModal: function () {
|
|
||||||
this.setState({isPersonalSettingModalOpen: true})
|
|
||||||
},
|
|
||||||
closePersonalSettingModal: function () {
|
|
||||||
this.setState({isPersonalSettingModalOpen: false})
|
|
||||||
},
|
|
||||||
openPlanetCreateModal: function () {
|
|
||||||
this.setState({isPlanetCreateModalOpen: true})
|
|
||||||
},
|
|
||||||
closePlanetCreateModal: function () {
|
|
||||||
this.setState({isPlanetCreateModalOpen: false})
|
|
||||||
},
|
|
||||||
handleKeyDown: function (e) {
|
|
||||||
if (e.metaKey && e.keyCode > 48 && e.keyCode < 58) {
|
|
||||||
var planet = this.props.currentUser.Planets[e.keyCode - 49]
|
|
||||||
if (planet != null) {
|
|
||||||
this.transitionTo('planet', {userName: planet.userName, planetName: planet.name})
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
var planets = this.props.currentUser.Planets.map(function (planet, index) {
|
|
||||||
return (
|
|
||||||
<li key={planet.id} className={this.props.currentPlanet != null && this.props.currentPlanet.userName === planet.userName && this.props.currentPlanet.name === planet.name ? 'active' : ''}>
|
|
||||||
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>
|
|
||||||
{planet.name[0]}
|
|
||||||
<div className='planetTooltip'>{planet.userName}/{planet.name}</div>
|
|
||||||
</Link>
|
|
||||||
<div className='shortCut'>⌘{index + 1}</div>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}.bind(this))
|
|
||||||
if (this.props.currentUser == null) {
|
|
||||||
return (
|
|
||||||
<div className='UserNavigator'>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div tabIndex='2' className='UserNavigator'>
|
|
||||||
<Link to='userHome' params={{userName: this.props.currentUser.name}} className='userProfile'>
|
|
||||||
<ProfileImage size='55' email={this.props.currentUser.email}/>
|
|
||||||
</Link>
|
|
||||||
<ul className='planetList'>
|
|
||||||
{planets}
|
|
||||||
</ul>
|
|
||||||
<button onClick={this.openPlanetCreateModal} className='newPlanet'><i className='fa fa-plus'/></button>
|
|
||||||
|
|
||||||
<ModalBase isOpen={this.state.isPlanetCreateModalOpen} close={this.closePlanetCreateModal}>
|
|
||||||
<PlanetCreateModal close={this.closePlanetCreateModal}/>
|
|
||||||
</ModalBase>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
var React = require('react/addons')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<div className='DashboardContainer'>
|
|
||||||
<h1 className='jumbotron'>Codexen App <small>v0.2.0</small></h1>
|
|
||||||
|
|
||||||
<h2>About CodeXen</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
CodeXen is short code storage tool make coding more stressless. If you use CodeXen, then you will be disentangled from troublesome organizing a large number of snippets and googling same code many times.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>
|
|
||||||
<h3>Post your code</h3>
|
|
||||||
<p>
|
|
||||||
Post your commonly used code with description,category,and tags.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>Save on cloud</h3>
|
|
||||||
<p>
|
|
||||||
From short snippet to long complex code,CodeXen saves any code simply.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>
|
|
||||||
Use code like a magic
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
CodeXen call code you posted whereever you are.Type [shift+control+tab] simultaneously.
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<h3>
|
|
||||||
Code Elegantly
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
That's all!
|
|
||||||
You must be loved with CodeXen. Enjoy coding;)
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
<p>
|
|
||||||
© 2015 MAISIN&CO.,Inc.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
29
browser/main/Containers/HomeContainer.jsx
Normal file
29
browser/main/Containers/HomeContainer.jsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
|
var React = require('react/addons')
|
||||||
|
var ReactRouter = require('react-router')
|
||||||
|
var RouteHandler = ReactRouter.RouteHandler
|
||||||
|
var State = ReactRouter.State
|
||||||
|
var Navigation = ReactRouter.Navigation
|
||||||
|
|
||||||
|
var AuthFilter = require('../Mixins/AuthFilter')
|
||||||
|
|
||||||
|
var HomeNavigator = require('../Components/HomeNavigator')
|
||||||
|
|
||||||
|
module.exports = React.createClass({
|
||||||
|
mixins: [AuthFilter.OnlyUser, State, Navigation],
|
||||||
|
componentDidMount: function () {
|
||||||
|
if (this.isActive('homeEmpty')) {
|
||||||
|
var user = JSON.parse(localStorage.getItem('currentUser'))
|
||||||
|
this.transitionTo('userHome', {userName: user.name})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div className='HomeContainer'>
|
||||||
|
<HomeNavigator/>
|
||||||
|
<RouteHandler/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,30 +1,22 @@
|
|||||||
|
/* global localStorage */
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var Link = ReactRouter.Link
|
var Link = ReactRouter.Link
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
var AuthFilter = require('../Mixins/AuthFilter')
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var OnlyGuest = require('../Mixins/OnlyGuest')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [React.addons.LinkedStateMixin, ReactRouter.Navigation, OnlyGuest],
|
mixins: [LinkedState, ReactRouter.Navigation, AuthFilter.OnlyGuest],
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
email: '',
|
user: {},
|
||||||
password: '',
|
|
||||||
authenticationFailed: false,
|
authenticationFailed: false,
|
||||||
connectionFailed: false,
|
connectionFailed: false,
|
||||||
isSending: false
|
isSending: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
|
||||||
this.unsubscribe = AuthStore.listen(this.onListen)
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribe()
|
|
||||||
},
|
|
||||||
onListen: function (res) {
|
onListen: function (res) {
|
||||||
if (res.status === 'failedToLogIn') {
|
if (res.status === 'failedToLogIn') {
|
||||||
if (res.data.status === 401) {
|
if (res.data.status === 401) {
|
||||||
@@ -51,10 +43,28 @@ module.exports = React.createClass({
|
|||||||
connectionFailed: false,
|
connectionFailed: false,
|
||||||
isSending: true
|
isSending: true
|
||||||
}, function () {
|
}, function () {
|
||||||
AuthActions.login({
|
Hq.login(this.state.user)
|
||||||
email: this.state.email,
|
.then(function (res) {
|
||||||
password: this.state.password
|
localStorage.setItem('token', res.body.token)
|
||||||
})
|
localStorage.setItem('currentUser', JSON.stringify(res.body.user))
|
||||||
|
|
||||||
|
this.transitionTo('userHome', {userName: res.body.user.name})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
if (err.status === 401) {
|
||||||
|
this.setState({
|
||||||
|
authenticationFailed: true,
|
||||||
|
connectionFailed: false,
|
||||||
|
isSending: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
authenticationFailed: false,
|
||||||
|
connectionFailed: true,
|
||||||
|
isSending: false
|
||||||
|
})
|
||||||
|
}.bind(this))
|
||||||
})
|
})
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@@ -64,7 +74,7 @@ module.exports = React.createClass({
|
|||||||
<div className='LoginContainer'>
|
<div className='LoginContainer'>
|
||||||
<img className='logo' src='resources/favicon-230x230.png'/>
|
<img className='logo' src='resources/favicon-230x230.png'/>
|
||||||
|
|
||||||
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='register'>Sign Up</Link></nav>
|
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
||||||
|
|
||||||
<div className='socialControl'>
|
<div className='socialControl'>
|
||||||
<p>Connect with</p>
|
<p>Connect with</p>
|
||||||
@@ -79,10 +89,10 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
|
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('password')} onChange={this.handleChange} type='password' placeholder='Password'/>
|
<input className='stripInput' valueLink={this.linkState('user.password')} onChange={this.handleChange} type='password' placeholder='Password'/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.state.isSending ? (
|
{this.state.isSending ? (
|
||||||
|
|||||||
@@ -1,92 +1,64 @@
|
|||||||
/* global localStorage */
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var RouteHandler = ReactRouter.RouteHandler
|
var RouteHandler = ReactRouter.RouteHandler
|
||||||
var request = require('superagent')
|
var Navigation = ReactRouter.Navigation
|
||||||
|
var State = ReactRouter.State
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
var UserStore = require('../Stores/UserStore')
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
// function fetchPlanet (planet) {
|
||||||
|
// return Hq.fetchPlanet(planet.userName, planet.name)
|
||||||
function fetchPlanet (planet) {
|
// .then(function (res) {
|
||||||
request
|
// var _planet = res.body
|
||||||
.get(apiUrl + planet.userName + '/' + planet.name)
|
// _planet.userName = planet.userName
|
||||||
.send()
|
//
|
||||||
.end(function (err, res) {
|
// _planet.Snippets = _planet.Snippets.map(function (snippet) {
|
||||||
if (err) {
|
// snippet.type = 'snippet'
|
||||||
console.error(err)
|
// return snippet
|
||||||
return
|
// })
|
||||||
}
|
//
|
||||||
|
// _planet.Blueprints = _planet.Blueprints.map(function (blueprint) {
|
||||||
var _planet = res.body
|
// blueprint.type = 'blueprint'
|
||||||
_planet.userName = planet.userName
|
// return blueprint
|
||||||
|
// })
|
||||||
_planet.Snippets = _planet.Snippets.map(function (snippet) {
|
//
|
||||||
snippet.type = 'snippet'
|
// localStorage.setItem('planet-' + _planet.id, JSON.stringify(_planet))
|
||||||
return snippet
|
// console.log('planet-' + _planet.id + ' fetched')
|
||||||
})
|
// })
|
||||||
|
// .catch(function (err) {
|
||||||
_planet.Blueprints = _planet.Blueprints.map(function (blueprint) {
|
// console.error(err)
|
||||||
blueprint.type = 'blueprint'
|
// })
|
||||||
return blueprint
|
// }
|
||||||
})
|
|
||||||
|
|
||||||
localStorage.setItem('planet-' + _planet.id, JSON.stringify(_planet))
|
|
||||||
console.log('planet-' + _planet.id + ' fetched')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [ReactRouter.Navigation, ReactRouter.State],
|
mixins: [State, Navigation],
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
this.unsubscribe = AuthStore.listen(this.onListen)
|
if (this.isActive('root')) {
|
||||||
|
if (localStorage.getItem('currentUser') == null) {
|
||||||
var user = JSON.parse(localStorage.getItem('user'))
|
this.transitionTo('login')
|
||||||
if (user != null) {
|
} else {
|
||||||
AuthActions.refreshUser()
|
this.transitionTo('home')
|
||||||
return
|
|
||||||
}
|
|
||||||
this.transitionTo('login')
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribe()
|
|
||||||
},
|
|
||||||
onListen: function (res) {
|
|
||||||
if (res == null || res.status == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var user
|
|
||||||
if (res.status === 'loggedIn' || res.status === 'registered') {
|
|
||||||
user = res.data
|
|
||||||
var planet = user.Planets.length > 0 ? user.Planets[0] : null
|
|
||||||
if (planet == null) {
|
|
||||||
this.transitionTo('user', {userName: user.name})
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.status === 'loggedOut') {
|
Hq.getUser()
|
||||||
this.transitionTo('login')
|
.then(function (res) {
|
||||||
return
|
localStorage.setItem('currentUser', JSON.stringify(res.body))
|
||||||
}
|
UserStore.Actions.update(res.body)
|
||||||
|
})
|
||||||
if (res.status === 'userRefreshed') {
|
.catch(function (err) {
|
||||||
console.log('refreshed')
|
if (err.status === 401) {
|
||||||
user = res.data
|
localStorage.removeItem('currentUser')
|
||||||
user.Planets.forEach(fetchPlanet)
|
this.transitionTo('login')
|
||||||
return
|
}
|
||||||
}
|
console.error(err)
|
||||||
|
}.bind(this))
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
// Redirect Login state
|
|
||||||
if (this.getPath() === '/') {
|
|
||||||
this.transitionTo('/login')
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className='Main'>
|
<div className='Main'>
|
||||||
<RouteHandler/>
|
<RouteHandler/>
|
||||||
|
|||||||
@@ -1,143 +1,204 @@
|
|||||||
|
/* global localStorage*/
|
||||||
|
'strict'
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
var PlanetHeader = require('../Components/PlanetHeader')
|
var PlanetHeader = require('../Components/PlanetHeader')
|
||||||
var PlanetNavigator = require('../Components/PlanetNavigator')
|
var PlanetNavigator = require('../Components/PlanetNavigator')
|
||||||
var PlanetArticleList = require('../Components/PlanetArticleList')
|
var PlanetArticleList = require('../Components/PlanetArticleList')
|
||||||
var PlanetArticleDetail = require('../Components/PlanetArticleDetail')
|
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 PersonalSettingModal = require('../Components/PersonalSettingModal')
|
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
var Modal = require('../Mixins/Modal')
|
||||||
|
var ArticleFilter = require('../Mixins/ArticleFilter')
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
|
var UserStore = require('../Stores/UserStore')
|
||||||
var PlanetStore = require('../Stores/PlanetStore')
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
function basicFilter (keyword, articles) {
|
|
||||||
if (keyword === '' || keyword == null) return articles
|
|
||||||
var firstFiltered = articles.filter(function (article) {
|
|
||||||
|
|
||||||
var first = article.type === 'snippet' ? article.callSign : article.title
|
|
||||||
if (first.match(new RegExp(keyword, '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(keyword, 'i'))) return true
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
var thirdFiltered = articles.filter(function (article) {
|
|
||||||
if (article.type === 'snippet') {
|
|
||||||
if (article.content.match(new RegExp(keyword, 'i'))) return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
return firstFiltered.concat(secondFiltered, thirdFiltered).filter(function (value, index, self) {
|
|
||||||
return self.indexOf(value) === index
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function snippetFilter (articles) {
|
|
||||||
return articles.filter(function (article) {
|
|
||||||
return article.type === 'snippet'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function blueprintFilter (articles) {
|
|
||||||
return articles.filter(function (article) {
|
|
||||||
return article.type === 'blueprint'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function tagFilter (keyword, articles) {
|
|
||||||
return articles.filter(function (article) {
|
|
||||||
return article.Tags.some(function (tag) {
|
|
||||||
return tag.name.match(new RegExp('^' + keyword, 'i'))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchArticle (search, articles) {
|
|
||||||
var keywords = search.split(' ')
|
|
||||||
|
|
||||||
for (var keyword of keywords) {
|
|
||||||
if (keyword.match(/^\$s/, 'i')) {
|
|
||||||
articles = snippetFilter(articles)
|
|
||||||
continue
|
|
||||||
} else if (keyword.match(/^\$b/, 'i')) {
|
|
||||||
articles = blueprintFilter(articles)
|
|
||||||
continue
|
|
||||||
} else if (keyword.match(/^#[A-Za-z0-9]+/)) {
|
|
||||||
articles = tagFilter(keyword.substring(1, keyword.length), articles)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
articles = basicFilter(keyword, articles)
|
|
||||||
}
|
|
||||||
|
|
||||||
return articles
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [ReactRouter.Navigation, ReactRouter.State],
|
mixins: [ReactRouter.Navigation, ReactRouter.State, Modal, Reflux.listenTo(UserStore, 'onUserChange'), Reflux.listenTo(PlanetStore, 'onPlanetChange'), ArticleFilter],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
params: React.PropTypes.object,
|
params: React.PropTypes.object,
|
||||||
planetName: React.PropTypes.string
|
planetName: React.PropTypes.string
|
||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
currentUser: AuthStore.getUser(),
|
currentUser: JSON.parse(localStorage.getItem('currentUser')),
|
||||||
currentPlanet: null,
|
planet: null,
|
||||||
search: '',
|
search: ''
|
||||||
isFetched: false,
|
|
||||||
isLaunchModalOpen: false,
|
|
||||||
isEditModalOpen: false,
|
|
||||||
isDeleteModalOpen: false,
|
|
||||||
isAddUserModalOpen: false,
|
|
||||||
isSettingModalOpen: false,
|
|
||||||
isPersonalSettingModalOpen: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
this.unsubscribePlanet = PlanetStore.listen(this.onFetched)
|
this.fetchPlanet(this.props.params.userName, this.props.params.planetName)
|
||||||
this.unsubscribeAuth = AuthStore.listen(this.onListenAuth)
|
|
||||||
|
|
||||||
PlanetActions.fetchPlanet(this.props.params.userName, this.props.params.planetName)
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribePlanet()
|
|
||||||
this.unsubscribeAuth()
|
|
||||||
},
|
},
|
||||||
componentDidUpdate: function () {
|
componentDidUpdate: function () {
|
||||||
if (this.state.currentPlanet == null || this.state.currentPlanet.name !== this.props.params.planetName || this.state.currentPlanet.userName !== this.props.params.userName) {
|
if (this.isActive('planetHome') && this.refs.list != null && this.refs.list.props.articles.length > 0) {
|
||||||
PlanetActions.fetchPlanet(this.props.params.userName, this.props.params.planetName)
|
var article = this.refs.list.props.articles[0]
|
||||||
this.focus()
|
console.log(article)
|
||||||
|
var planet = this.state.planet
|
||||||
|
switch (article.type) {
|
||||||
|
case 'code':
|
||||||
|
this.transitionTo('codes', {userName: planet.userName, planetName: planet.name, localId: article.localId})
|
||||||
|
break
|
||||||
|
case 'note':
|
||||||
|
this.transitionTo('notes', {userName: planet.userName, 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.userName || nextProps.params.planetName !== this.state.planet.name) {
|
||||||
|
this.setState({
|
||||||
|
planet: null
|
||||||
|
}, function () {
|
||||||
|
this.fetchPlanet(nextProps.params.userName, nextProps.params.planetName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onPlanetChange: function (res) {
|
||||||
|
if (this.state.planet == null) return
|
||||||
|
|
||||||
|
var code, codes, note, notes, isNew, articleIndex, articlesCount
|
||||||
|
switch (res.status) {
|
||||||
|
case 'codeUpdated':
|
||||||
|
code = res.data
|
||||||
|
if (code.PlanetId === this.state.planet.id) {
|
||||||
|
codes = this.state.planet.Codes
|
||||||
|
isNew = !codes.some(function (_code, index) {
|
||||||
|
if (code.localId === _code.localId) {
|
||||||
|
codes.splice(index, 1, code)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
codes.unshift(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({planet: this.state.planet})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'noteUpdated':
|
||||||
|
note = res.data
|
||||||
|
if (note.PlanetId === this.state.planet.id) {
|
||||||
|
notes = this.state.planet.Notes
|
||||||
|
isNew = !notes.some(function (_note, index) {
|
||||||
|
if (note.localId === _note.localId) {
|
||||||
|
notes.splice(index, 1, note)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isNew) {
|
||||||
|
notes.unshift(note)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({planet: this.state.planet})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'codeDestroyed':
|
||||||
|
code = res.data
|
||||||
|
if (code.PlanetId === this.state.planet.id) {
|
||||||
|
codes = this.state.planet.Codes
|
||||||
|
codes.some(function (_code, index) {
|
||||||
|
if (code.localId === _code.localId) {
|
||||||
|
codes.splice(index, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'noteDestroyed':
|
||||||
|
note = res.data
|
||||||
|
if (note.PlanetId === this.state.planet.id) {
|
||||||
|
notes = this.state.planet.Notes
|
||||||
|
notes.some(function (_note, index) {
|
||||||
|
if (note.localId === _note.localId) {
|
||||||
|
notes.splice(index, 1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
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 () {
|
getFilteredIndexOfCurrentArticle: function () {
|
||||||
var params = this.props.params
|
var params = this.props.params
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
if (this.isActive('snippets')) {
|
if (this.isActive('codes')) {
|
||||||
this.refs.list.props.articles.some(function (_article, _index) {
|
this.refs.list.props.articles.some(function (_article, _index) {
|
||||||
if (_article.type === 'snippet' && _article.localId === parseInt(params.localId, 10)) {
|
if (_article.type === 'code' && _article.localId === parseInt(params.localId, 10)) {
|
||||||
index = _index
|
index = _index
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else if (this.isActive('blueprints')) {
|
} else if (this.isActive('notes')) {
|
||||||
this.refs.list.props.articles.some(function (_article, _index) {
|
this.refs.list.props.articles.some(function (_article, _index) {
|
||||||
if (_article.type === 'blueprint' && _article.localId === parseInt(params.localId, 10)) {
|
if (_article.type === 'note' && _article.localId === parseInt(params.localId, 10)) {
|
||||||
index = _index
|
index = _index
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -147,29 +208,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
return index
|
return index
|
||||||
},
|
},
|
||||||
getIndexOfCurrentArticle: function () {
|
selectArticleByListIndex: function (index) {
|
||||||
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 article = this.refs.list.props.articles[index]
|
||||||
var params = this.props.params
|
var params = this.props.params
|
||||||
|
|
||||||
@@ -178,411 +217,131 @@ module.exports = React.createClass({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (article.type === 'snippet') {
|
if (article.type === 'code') {
|
||||||
params.localId = article.localId
|
params.localId = article.localId
|
||||||
this.transitionTo('snippets', params)
|
this.transitionTo('codes', params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (article.type === 'blueprint') {
|
if (article.type === 'note') {
|
||||||
params.localId = article.localId
|
params.localId = article.localId
|
||||||
this.transitionTo('blueprints', params)
|
this.transitionTo('notes', params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectNextArticle: function () {
|
selectNextArticle: function () {
|
||||||
if (this.state.currentPlanet == null) return
|
if (this.state.planet == null) return
|
||||||
|
|
||||||
var index = this.getFilteredIndexOfCurrentArticle()
|
var index = this.getFilteredIndexOfCurrentArticle()
|
||||||
|
|
||||||
if (index < this.refs.list.props.articles.length - 1) {
|
if (index < this.refs.list.props.articles.length - 1) {
|
||||||
this.selectArticleByIndex(index + 1)
|
this.selectArticleByListIndex(index + 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectPriorArticle: function () {
|
selectPriorArticle: function () {
|
||||||
if (this.state.currentPlanet == null) {
|
if (this.state.planet == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var index = this.getFilteredIndexOfCurrentArticle()
|
var index = this.getFilteredIndexOfCurrentArticle()
|
||||||
|
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
this.selectArticleByIndex(index - 1)
|
this.selectArticleByListIndex(index - 1)
|
||||||
} else {
|
} else {
|
||||||
React.findDOMNode(this).querySelector('.PlanetHeader .searchInput input').focus()
|
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
|
|
||||||
|
|
||||||
var planet
|
|
||||||
if (res.status === 'planetFetched') {
|
|
||||||
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 === 'planetDeleted') {
|
|
||||||
planet = res.data
|
|
||||||
this.transitionTo('user', {
|
|
||||||
userName: this.props.params.userName
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var user
|
|
||||||
if (res.status === 'userAdded') {
|
|
||||||
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') {
|
|
||||||
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) {
|
handleSearchChange: function (e) {
|
||||||
this.setState({search: e.target.value}, function () {
|
this.setState({search: e.target.value}, function () {
|
||||||
this.selectArticleByIndex(0)
|
this.selectArticleByListIndex(0)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
showAll: function () {
|
showAll: function () {
|
||||||
this.setState({search: ''})
|
this.setState({search: ''})
|
||||||
},
|
},
|
||||||
toggleSnippetFilter: function () {
|
toggleCodeFilter: function () {
|
||||||
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
||||||
|
|
||||||
var usingSnippetFilter = false
|
var usingCodeFilter = false
|
||||||
var usingBlueprintFilter = false
|
var usingNoteFilter = false
|
||||||
keywords = keywords.filter(function (keyword) {
|
keywords = keywords.filter(function (keyword) {
|
||||||
if (keyword === '$b') {
|
if (keyword === '$n') {
|
||||||
usingBlueprintFilter = true
|
usingNoteFilter = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keyword === '$s') usingSnippetFilter = true
|
if (keyword === '$c') usingCodeFilter = true
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
if (usingSnippetFilter && !usingBlueprintFilter) {
|
if (usingCodeFilter && !usingNoteFilter) {
|
||||||
keywords = keywords.filter(function (keyword) {
|
keywords = keywords.filter(function (keyword) {
|
||||||
return keyword !== '$s'
|
return keyword !== '$c'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usingSnippetFilter) {
|
if (!usingCodeFilter) {
|
||||||
keywords.unshift('$s')
|
keywords.unshift('$c')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({search: keywords.join(' ')}, function () {
|
this.setState({search: keywords.join(' ')}, function () {
|
||||||
this.selectArticleByIndex(0)
|
this.selectArticleByIndex(0)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
toggleBlueprintFilter: function () {
|
toggleNoteFilter: function () {
|
||||||
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
var keywords = typeof this.state.search === 'string' ? this.state.search.split(' ') : []
|
||||||
|
|
||||||
var usingSnippetFilter = false
|
var usingCodeFilter = false
|
||||||
var usingBlueprintFilter = false
|
var usingNoteFilter = false
|
||||||
keywords = keywords.filter(function (keyword) {
|
keywords = keywords.filter(function (keyword) {
|
||||||
if (keyword === '$s') {
|
if (keyword === '$c') {
|
||||||
usingSnippetFilter = true
|
usingCodeFilter = true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keyword === '$b') usingBlueprintFilter = true
|
if (keyword === '$n') usingNoteFilter = true
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
if (usingBlueprintFilter && !usingSnippetFilter) {
|
if (usingNoteFilter && !usingCodeFilter) {
|
||||||
keywords = keywords.filter(function (keyword) {
|
keywords = keywords.filter(function (keyword) {
|
||||||
return keyword !== '$b'
|
return keyword !== '$n'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usingBlueprintFilter) {
|
if (!usingNoteFilter) {
|
||||||
keywords.unshift('$b')
|
keywords.unshift('$n')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({search: keywords.join(' ')}, function () {
|
this.setState({search: keywords.join(' ')}, function () {
|
||||||
this.selectArticleByIndex(0)
|
this.selectArticleByIndex(0)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
showOnlyWithTag: function (tag) {
|
applyTagFilter: function (tag) {
|
||||||
return function () {
|
return function () {
|
||||||
this.setState({search: '#' + tag})
|
this.setState({search: '#' + tag})
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
},
|
},
|
||||||
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()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
openPersonalSettingModal: function () {
|
|
||||||
this.setState({isPersonalSettingModalOpen: true})
|
|
||||||
},
|
|
||||||
closePersonalSettingModal: function () {
|
|
||||||
this.setState({isPersonalSettingModalOpen: false}, function () {
|
|
||||||
this.focus()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
focus: function () {
|
focus: function () {
|
||||||
React.findDOMNode(this).focus()
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.isPersonalSettingModalOpen) {
|
|
||||||
if (e.keyCode === 27) {
|
|
||||||
this.closePersonalSettingModal()
|
|
||||||
}
|
|
||||||
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 () {
|
render: function () {
|
||||||
if (this.state.currentUser == null) return (<div/>)
|
if (this.state.planet == null) return (<div/>)
|
||||||
if (this.state.currentPlanet == null) return (<div/>)
|
|
||||||
|
|
||||||
var localId = parseInt(this.props.params.localId, 10)
|
var localId = parseInt(this.props.params.localId, 10)
|
||||||
|
|
||||||
|
var codes = this.state.planet.Codes
|
||||||
|
var notes = this.state.planet.Notes
|
||||||
|
|
||||||
var article
|
var article
|
||||||
if (this.isActive('snippets')) {
|
if (this.isActive('codes')) {
|
||||||
this.state.currentPlanet.Articles.some(function (_article) {
|
codes.some(function (_article) {
|
||||||
if (_article.type === 'snippet' && localId === _article.localId) {
|
if (localId === _article.localId) {
|
||||||
article = _article
|
article = _article
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
} else if (this.isActive('blueprints')) {
|
} else if (this.isActive('notes')) {
|
||||||
this.state.currentPlanet.Articles.some(function (_article) {
|
notes.some(function (_article) {
|
||||||
if (_article.type === 'blueprint' && localId === _article.localId) {
|
if (localId === _article.localId) {
|
||||||
article = _article
|
article = _article
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -590,58 +349,34 @@ module.exports = React.createClass({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var filteredArticles = this.state.isFetched ? searchArticle(this.state.search, this.state.currentPlanet.Articles) : []
|
var articles = codes.concat(notes)
|
||||||
|
|
||||||
var editModal = article != null ? (article.type === 'snippet' ? (
|
var filteredArticles = this.searchArticle(this.state.search, articles)
|
||||||
<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 (
|
return (
|
||||||
<div tabIndex='1' onKeyDown={this.handleKeyDown} className='PlanetContainer'>
|
<div className='PlanetContainer'>
|
||||||
<ModalBase isOpen={this.state.isLaunchModalOpen} close={this.closeLaunchModal}>
|
<PlanetHeader
|
||||||
<LaunchModal close={this.closeLaunchModal}/>
|
search={this.state.search}
|
||||||
</ModalBase>
|
fetchPlanet={this.fetchPlanet}
|
||||||
|
onSearchChange={this.handleSearchChange}
|
||||||
|
currentPlanet={this.state.planet}
|
||||||
|
/>
|
||||||
|
|
||||||
<ModalBase isOpen={this.state.isEditModalOpen} close={this.closeEditModal}>
|
<PlanetNavigator
|
||||||
{editModal}
|
ref='navigator'
|
||||||
</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>
|
|
||||||
|
|
||||||
<ModalBase isOpen={this.state.isPersonalSettingModalOpen} close={this.closePersonalSettingModal}>
|
|
||||||
<PersonalSettingModal currentUser={this.state.currentUser} close={this.closePersonalSettingModal}/>
|
|
||||||
</ModalBase>
|
|
||||||
|
|
||||||
<PlanetHeader search={this.state.search}
|
|
||||||
openSettingModal={this.openSettingModal}
|
|
||||||
openPersonalSettingModal={this.openPersonalSettingModal} onSearchChange={this.handleSearchChange} currentPlanet={this.state.currentPlanet}/>
|
|
||||||
|
|
||||||
<PlanetNavigator openLaunchModal={this.openLaunchModal} openAddUserModal={this.openAddUserModal}
|
|
||||||
search={this.state.search}
|
search={this.state.search}
|
||||||
showAll={this.showAll}
|
showAll={this.showAll}
|
||||||
toggleSnippetFilter={this.toggleSnippetFilter} toggleBlueprintFilter={this.toggleBlueprintFilter} currentPlanet={this.state.currentPlanet}/>
|
toggleCodeFilter={this.toggleCodeFilter}
|
||||||
|
toggleNoteFilter={this.toggleNoteFilter}
|
||||||
|
planet={this.state.planet}/>
|
||||||
|
|
||||||
<PlanetArticleList showOnlyWithTag={this.showOnlyWithTag} ref='list' articles={filteredArticles}/>
|
<PlanetArticleList showOnlyWithTag={this.applyTagFilter} ref='list' articles={filteredArticles}/>
|
||||||
|
|
||||||
<PlanetArticleDetail ref='detail' article={article} onOpenEditModal={this.openEditModal} onOpenDeleteModal={this.openDeleteModal} showOnlyWithTag={this.showOnlyWithTag}/>
|
<PlanetArticleDetail
|
||||||
|
ref='detail'
|
||||||
|
article={article}
|
||||||
|
planet={this.state.planet}
|
||||||
|
showOnlyWithTag={this.applyTagFilter}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var Link = ReactRouter.Link
|
var Link = ReactRouter.Link
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
var AuthFilter = require('../Mixins/AuthFilter')
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var OnlyGuest = require('../Mixins/OnlyGuest')
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [React.addons.LinkedStateMixin, ReactRouter.Navigation, OnlyGuest],
|
mixins: [LinkedState, ReactRouter.Navigation, AuthFilter.OnlyGuest],
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
email: '',
|
user: {},
|
||||||
password: '',
|
|
||||||
name: '',
|
|
||||||
profileName: '',
|
|
||||||
connectionFailed: false,
|
connectionFailed: false,
|
||||||
emailConflicted: false,
|
emailConflicted: false,
|
||||||
nameConflicted: false,
|
nameConflicted: false,
|
||||||
@@ -23,52 +20,6 @@ module.exports = React.createClass({
|
|||||||
isSending: false
|
isSending: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
|
||||||
this.unsubscribe = AuthStore.listen(this.onListen)
|
|
||||||
},
|
|
||||||
componentWillUnmount: function () {
|
|
||||||
this.unsubscribe()
|
|
||||||
},
|
|
||||||
onListen: function (res) {
|
|
||||||
if (res.status === 'failedToRegister') {
|
|
||||||
if (res.data.status === 409) {
|
|
||||||
// Confliction
|
|
||||||
var emailConflicted = res.data.body.errors[0].path === 'email'
|
|
||||||
var nameConflicted = res.data.body.errors[0].path === 'name'
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
connectionFailed: false,
|
|
||||||
emailConflicted: emailConflicted,
|
|
||||||
nameConflicted: nameConflicted,
|
|
||||||
validationFailed: false,
|
|
||||||
isSending: false
|
|
||||||
})
|
|
||||||
return
|
|
||||||
} else if (res.data.status === 422) {
|
|
||||||
this.setState({
|
|
||||||
connectionFailed: false,
|
|
||||||
emailConflicted: false,
|
|
||||||
nameConflicted: false,
|
|
||||||
validationFailed: {
|
|
||||||
errors: res.data.body.errors.map(function (error) {
|
|
||||||
return error.path
|
|
||||||
})
|
|
||||||
},
|
|
||||||
isSending: false
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Connection Failed or Whatever
|
|
||||||
this.setState({
|
|
||||||
connectionFailed: true,
|
|
||||||
emailConflicted: false,
|
|
||||||
nameConflicted: false,
|
|
||||||
validationFailed: false,
|
|
||||||
isSending: false
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSubmit: function (e) {
|
handleSubmit: function (e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
connectionFailed: false,
|
connectionFailed: false,
|
||||||
@@ -77,22 +28,68 @@ module.exports = React.createClass({
|
|||||||
validationFailed: false,
|
validationFailed: false,
|
||||||
isSending: true
|
isSending: true
|
||||||
}, function () {
|
}, function () {
|
||||||
AuthActions.register({
|
Hq.signup(this.state.user)
|
||||||
email: this.state.email,
|
.then(function (res) {
|
||||||
password: this.state.password,
|
localStorage.setItem('token', res.body.token)
|
||||||
name: this.state.name,
|
localStorage.setItem('currentUser', JSON.stringify(res.body.user))
|
||||||
profileName: this.state.profileName
|
|
||||||
})
|
this.transitionTo('userHome', {userName: res.body.user.name})
|
||||||
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
var res = err.response
|
||||||
|
console.log(res)
|
||||||
|
console.log(err.status)
|
||||||
|
if (err.status === 409) {
|
||||||
|
// Confliction
|
||||||
|
var emailConflicted = res.body.errors[0].path === 'email'
|
||||||
|
var nameConflicted = res.body.errors[0].path === 'name'
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
connectionFailed: false,
|
||||||
|
emailConflicted: emailConflicted,
|
||||||
|
nameConflicted: nameConflicted,
|
||||||
|
validationFailed: false,
|
||||||
|
isSending: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err.status === 422) {
|
||||||
|
// Validation Failed
|
||||||
|
this.setState({
|
||||||
|
connectionFailed: false,
|
||||||
|
emailConflicted: false,
|
||||||
|
nameConflicted: false,
|
||||||
|
validationFailed: {
|
||||||
|
errors: res.body.errors.map(function (error) {
|
||||||
|
return error.path
|
||||||
|
})
|
||||||
|
},
|
||||||
|
isSending: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection Failed or Whatever
|
||||||
|
this.setState({
|
||||||
|
connectionFailed: true,
|
||||||
|
emailConflicted: false,
|
||||||
|
nameConflicted: false,
|
||||||
|
validationFailed: false,
|
||||||
|
isSending: false
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}.bind(this))
|
||||||
})
|
})
|
||||||
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
return (
|
return (
|
||||||
<div className='RegisterContainer'>
|
<div className='SignupContainer'>
|
||||||
<img className='logo' src='resources/favicon-230x230.png'/>
|
<img className='logo' src='resources/favicon-230x230.png'/>
|
||||||
|
|
||||||
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='register'>Sign Up</Link></nav>
|
<nav className='authNavigator text-center'><Link to='login'>Log In</Link> / <Link to='signup'>Sign Up</Link></nav>
|
||||||
|
|
||||||
<div className='socialControl'>
|
<div className='socialControl'>
|
||||||
<p>Connect with</p>
|
<p>Connect with</p>
|
||||||
@@ -107,16 +104,16 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
|
<input className='stripInput' valueLink={this.linkState('user.email')} type='text' placeholder='E-mail'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('password')} type='password' placeholder='Password'/>
|
<input className='stripInput' valueLink={this.linkState('user.password')} type='password' placeholder='Password'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('name')} type='text' placeholder='name'/>
|
<input className='stripInput' valueLink={this.linkState('user.name')} type='text' placeholder='name'/>
|
||||||
</div>
|
</div>
|
||||||
<div className='form-group'>
|
<div className='form-group'>
|
||||||
<input className='stripInput' valueLink={this.linkState('profileName')} type='text' placeholder='Profile name'/>
|
<input className='stripInput' valueLink={this.linkState('user.profileName')} type='text' placeholder='Profile name'/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{this.state.isSending ? (
|
{this.state.isSending ? (
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
/* global localStorage */
|
/* global localStorage */
|
||||||
|
|
||||||
var React = require('react/addons')
|
var React = require('react/addons')
|
||||||
var ReactRouter = require('react-router')
|
var ReactRouter = require('react-router')
|
||||||
var RouteHandler = ReactRouter.RouteHandler
|
var RouteHandler = ReactRouter.RouteHandler
|
||||||
var Link = ReactRouter.Link
|
var Link = ReactRouter.Link
|
||||||
var request = require('superagent')
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
|
var LinkedState = require('../Mixins/LinkedState')
|
||||||
|
var Modal = require('../Mixins/Modal')
|
||||||
|
|
||||||
|
var Hq = require('../Services/Hq')
|
||||||
|
|
||||||
var UserNavigator = require('../Components/UserNavigator')
|
|
||||||
var ProfileImage = require('../Components/ProfileImage')
|
var ProfileImage = require('../Components/ProfileImage')
|
||||||
|
var EditProfileModal = require('../Components/EditProfileModal')
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
var UserStore = require('../Stores/UserStore')
|
||||||
var PlanetStore = require('../Stores/PlanetStore')
|
var PlanetStore = require('../Stores/PlanetStore')
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [React.addons.LinkedStateMixin, ReactRouter.Navigation, ReactRouter.State],
|
mixins: [LinkedState, ReactRouter.State, Modal, Reflux.listenTo(UserStore, 'onUserChange')],
|
||||||
propTypes: {
|
propTypes: {
|
||||||
params: React.PropTypes.shape({
|
params: React.PropTypes.shape({
|
||||||
userName: React.PropTypes.string,
|
userName: React.PropTypes.string,
|
||||||
@@ -23,42 +27,50 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
currentUser: AuthStore.getUser(),
|
|
||||||
isUserFetched: false,
|
|
||||||
user: null
|
user: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function () {
|
componentDidMount: function () {
|
||||||
this.unsubscribePlanet = PlanetStore.listen(this.onListen)
|
this.fetchUser()
|
||||||
this.unsubscribeAuth = AuthStore.listen(this.onListen)
|
},
|
||||||
|
componentWillReceiveProps: function (nextProps) {
|
||||||
|
if (this.state.user == null) {
|
||||||
|
this.fetchUser(nextProps.params.userName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isActive('userHome')) {
|
if (nextProps.params.userName !== this.state.user.name) {
|
||||||
this.fetchUser(this.props.params.userName)
|
this.setState({
|
||||||
|
user: null
|
||||||
|
}, function () {
|
||||||
|
this.fetchUser(nextProps.params.userName)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentWillUnmount: function () {
|
onUserChange: function (res) {
|
||||||
this.unsubscribePlanet()
|
if (this.state.user == null) return
|
||||||
this.unsubscribeAuth()
|
|
||||||
},
|
switch (res.status) {
|
||||||
componentDidUpdate: function () {
|
case 'userUpdated':
|
||||||
if (this.isActive('userHome') && (this.state.user == null || this.state.user.name !== this.props.params.userName)) {
|
if (this.state.user.id === res.data.id) {
|
||||||
this.fetchUser(this.props.params.userName)
|
this.setState({user: res.data})
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchUser: function (userName) {
|
fetchUser: function (userName) {
|
||||||
request
|
if (userName == null) userName = this.props.params.userName
|
||||||
.get(apiUrl + userName)
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({user: res.body, isUserFetched: true})
|
Hq.fetchUser(userName)
|
||||||
|
.then(function (res) {
|
||||||
|
this.setState({user: res.body})
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
.catch(function (err) {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onListen: function (res) {
|
onListen: function (res) {
|
||||||
|
console.log('on Listen')
|
||||||
if (res == null || res.status == null) return
|
if (res == null || res.status == null) return
|
||||||
|
|
||||||
var currentUser = this.state.currentUser
|
var currentUser = this.state.currentUser
|
||||||
@@ -66,7 +78,7 @@ module.exports = React.createClass({
|
|||||||
if (res.status === 'planetCreated') {
|
if (res.status === 'planetCreated') {
|
||||||
currentUser.Planets.push(res.data)
|
currentUser.Planets.push(res.data)
|
||||||
|
|
||||||
localStorage.setItem('user', JSON.stringify(currentUser))
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
this.setState({currentUser: currentUser})
|
this.setState({currentUser: currentUser})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -80,81 +92,75 @@ module.exports = React.createClass({
|
|||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
localStorage.setItem('user', JSON.stringify(currentUser))
|
localStorage.setItem('currentUser', JSON.stringify(currentUser))
|
||||||
this.setState({currentUser: currentUser})
|
this.setState({currentUser: currentUser})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
},
|
||||||
if (res.status === 'nameChanged') {
|
openEditProfileModal: function () {
|
||||||
this.setState({currentUser: AuthStore.getUser()})
|
this.openModal(EditProfileModal, {targetUser: this.state.user})
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.status === 'userProfileUpdated') {
|
|
||||||
this.setState({currentUser: AuthStore.getUser()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
var currentUser = this.state.currentUser
|
|
||||||
var user = this.state.user
|
var user = this.state.user
|
||||||
|
|
||||||
// user must be logged in
|
|
||||||
if (currentUser == null) return (<div></div>)
|
|
||||||
|
|
||||||
var currentPlanet = null
|
|
||||||
currentUser.Planets.some(function (planet) {
|
|
||||||
if (planet.userName === this.props.params.userName && planet.name === this.props.params.planetName) {
|
|
||||||
currentPlanet = planet
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}.bind(this))
|
|
||||||
|
|
||||||
var content
|
|
||||||
if (this.isActive('userHome')) {
|
if (this.isActive('userHome')) {
|
||||||
if (this.state.isUserFetched === false) {
|
if (user == null) {
|
||||||
content = (
|
return (
|
||||||
<div className='UserHome'>
|
<div className='UserContainer'>
|
||||||
User Loading...
|
User Loading...
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
var planets = user.Planets.map(function (planet) {
|
var userPlanets = user.Planets.map(function (planet) {
|
||||||
return (
|
return (
|
||||||
<li key={'planet-' + planet.id}>
|
<li key={'planet-' + planet.id}>
|
||||||
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>{planet.userName}/{planet.name}</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
content = (
|
|
||||||
<div className='UserHome'>
|
var teams = user.Teams == null ? [] : user.Teams.map(function (team) {
|
||||||
<h1>User Profile</h1>
|
return (
|
||||||
|
<li>
|
||||||
|
Some team
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<div className='UserContainer'>
|
||||||
<div className='userProfile'>
|
<div className='userProfile'>
|
||||||
<ProfileImage className='userPhoto' size='150' email={user.email}/>
|
<ProfileImage className='userPhoto' size='75' email={user.email}/>
|
||||||
<div className='userIntro'>
|
<div className='userInfo'>
|
||||||
<div className='userProfileName'>{user.profileName}</div>
|
<div className='userProfileName'>{user.profileName}</div>
|
||||||
<Link className='userName' to='user' params={{userName: user.name}}>{user.name}</Link>
|
<div className='userName'>{user.name}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onClick={this.openEditProfileModal} className='editProfileButton'>Edit profile</button>
|
||||||
|
</div>
|
||||||
|
<div className='teamList'>
|
||||||
|
<div className='teamLabel'>{teams.length} {teams.length > 0 ? 'Teams' : 'Team'}</div>
|
||||||
|
<ul className='teams'>
|
||||||
|
{teams}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className='planetList'>
|
||||||
|
<div className='planetLabel'>{userPlanets.length} {userPlanets.length > 0 ? 'Planets' : 'Planet'}</div>
|
||||||
|
<div className='planetGroup'>
|
||||||
|
<div className='planetGroupLabel'>{user.profileName}</div>
|
||||||
|
<ul className='planets'>
|
||||||
|
{userPlanets}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2>Planets</h2>
|
|
||||||
<ul className='userPlanetList'>
|
|
||||||
{planets}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
content = (
|
return (
|
||||||
<RouteHandler/>
|
<div className='UserContainer'>
|
||||||
|
<RouteHandler/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='UserContainer'>
|
|
||||||
<UserNavigator currentPlanet={currentPlanet} currentUser={currentUser}/>
|
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
var React = require('react/addons')
|
|
||||||
var ReactRouter = require('react-router')
|
|
||||||
|
|
||||||
var ModalBase = require('../Components/ModalBase')
|
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
|
||||||
|
|
||||||
var AuthStore = require('../Stores/AuthStore')
|
|
||||||
|
|
||||||
var LogOutModal = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
close: React.PropTypes.func
|
|
||||||
},
|
|
||||||
componentDidMount: function () {
|
|
||||||
React.findDOMNode(this.refs.cancel).focus()
|
|
||||||
},
|
|
||||||
submit: function () {
|
|
||||||
AuthActions.logout()
|
|
||||||
},
|
|
||||||
handleKeyDown: function (e) {
|
|
||||||
if (e.keyCode === 13 && e.metaKey) {
|
|
||||||
this.submit()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (e.keyCode === 27) {
|
|
||||||
this.props.close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<div onKeyDown={this.handleKeyDown} className='logOutModal modal'>
|
|
||||||
<div className='modal-header'>
|
|
||||||
<h1>Logout</h1>
|
|
||||||
</div>
|
|
||||||
<div className='modal-body'>
|
|
||||||
<p>Are you sure to log out?</p>
|
|
||||||
</div>
|
|
||||||
<div className='modal-footer'>
|
|
||||||
<div className='modal-control'>
|
|
||||||
<button ref='cancel' onClick={this.props.close} className='btn-default'>Cancel</button>
|
|
||||||
<button onClick={this.submit} className='btn-primary'>Logout</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var UserSettingNavigation = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
currentUser: React.PropTypes.shape({
|
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
current: React.PropTypes.string,
|
|
||||||
changeCurrent: React.PropTypes.func
|
|
||||||
},
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
isLogOutModalOpen: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeFactory: function (current) {
|
|
||||||
return function () {
|
|
||||||
this.props.changeCurrent(current)
|
|
||||||
}.bind(this)
|
|
||||||
},
|
|
||||||
openLogOutModal: function () {
|
|
||||||
this.setState({isLogOutModalOpen: true})
|
|
||||||
},
|
|
||||||
closeLogOutModal: function () {
|
|
||||||
this.setState({isLogOutModalOpen: false})
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
return (
|
|
||||||
<div className='UserSettingNavigation'>
|
|
||||||
<div className='userName'>{this.props.currentUser.name}</div>
|
|
||||||
<nav>
|
|
||||||
<a className={this.props.current === 'profile' ? 'active' : ''} onClick={this.changeFactory('profile')}><i className='fa fa-user fa-fw'/> Profile</a>
|
|
||||||
<a className={this.props.current === 'setting' ? 'active' : ''} onClick={this.changeFactory('setting')}><i className='fa fa-gears fa-fw'/> Setting</a>
|
|
||||||
<a className={this.props.current === 'integration' ? 'active' : ''} onClick={this.changeFactory('integration')}><i className='fa fa-share-alt fa-fw'/> Integration</a>
|
|
||||||
<a className={this.props.current === 'help' ? 'active' : ''} onClick={this.changeFactory('help')}><i className='fa fa-info-circle fa-fw'/> Help</a>
|
|
||||||
<a onClick={this.openLogOutModal}><i className='fa fa-sign-out fa-fw'/> Logout</a>
|
|
||||||
</nav>
|
|
||||||
<ModalBase close={this.closeLogOutModal} isOpen={this.state.isLogOutModalOpen}>
|
|
||||||
<LogOutModal close={this.closeLogOutModal}/>
|
|
||||||
</ModalBase>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var UserSettingMain = React.createClass({
|
|
||||||
propTypes: {
|
|
||||||
currentUser: React.PropTypes.shape({
|
|
||||||
name: React.PropTypes.string
|
|
||||||
}),
|
|
||||||
current: React.PropTypes.string
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
var view
|
|
||||||
|
|
||||||
switch (this.props.current) {
|
|
||||||
case 'profile':
|
|
||||||
view = (
|
|
||||||
<div>
|
|
||||||
<h1>User Info</h1>
|
|
||||||
<form>
|
|
||||||
<div>
|
|
||||||
<label>Name</label> <input className='inline-input'/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Mail</label> <input className='inline-input'/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button className='btn-primary'>Save</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<hr/>
|
|
||||||
<h1>Password Reset</h1>
|
|
||||||
<form>
|
|
||||||
<div>
|
|
||||||
<label>Name</label> <input className='inline-input'/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Mail</label> <input className='inline-input'/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button className='btn-primary'>Save</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
view = (
|
|
||||||
<div>
|
|
||||||
Missing...
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className='UserSettingMain'>
|
|
||||||
{view}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
module.exports = React.createClass({
|
|
||||||
mixins: [React.addons.LinkedStateMixin, ReactRouter.Navigation],
|
|
||||||
getInitialState: function () {
|
|
||||||
return {
|
|
||||||
current: 'profile'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeCurrent: function (current) {
|
|
||||||
this.setState({
|
|
||||||
current: current
|
|
||||||
})
|
|
||||||
},
|
|
||||||
render: function () {
|
|
||||||
var currentUser = AuthStore.getUser()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='UserSettingContainer'>
|
|
||||||
<UserSettingNavigation currentUser={currentUser} current={this.state.current} changeCurrent={this.changeCurrent}/>
|
|
||||||
<UserSettingMain currentUser={currentUser} current={this.state.current}/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
67
browser/main/Mixins/ArticleFilter.js
Normal file
67
browser/main/Mixins/ArticleFilter.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
function basicFilter (keyword, articles) {
|
||||||
|
if (keyword === '' || keyword == null) return articles
|
||||||
|
var firstFiltered = articles.filter(function (article) {
|
||||||
|
|
||||||
|
var first = article.type === 'code' ? article.description : article.title
|
||||||
|
if (first.match(new RegExp(keyword, 'i'))) return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
var secondFiltered = articles.filter(function (article) {
|
||||||
|
var second = article.type === 'code' ? article.content : article.content
|
||||||
|
if (second.match(new RegExp(keyword, 'i'))) return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
return firstFiltered.concat(secondFiltered).filter(function (value, index, self) {
|
||||||
|
return self.indexOf(value) === index
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function codeFilter (articles) {
|
||||||
|
return articles.filter(function (article) {
|
||||||
|
return article.type === 'code'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function noteFilter (articles) {
|
||||||
|
return articles.filter(function (article) {
|
||||||
|
return article.type === 'note'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function tagFilter (keyword, articles) {
|
||||||
|
return articles.filter(function (article) {
|
||||||
|
return article.Tags.some(function (tag) {
|
||||||
|
return tag.name.match(new RegExp('^' + keyword, 'i'))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchArticle (search, articles) {
|
||||||
|
var keywords = search.split(' ')
|
||||||
|
|
||||||
|
for (var keyword of keywords) {
|
||||||
|
if (keyword.match(/^\$c/, 'i')) {
|
||||||
|
articles = codeFilter(articles)
|
||||||
|
continue
|
||||||
|
} else if (keyword.match(/^\$n/, 'i')) {
|
||||||
|
articles = noteFilter(articles)
|
||||||
|
continue
|
||||||
|
} else if (keyword.match(/^#[A-Za-z0-9]+/)) {
|
||||||
|
articles = tagFilter(keyword.substring(1, keyword.length), articles)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
articles = basicFilter(keyword, articles)
|
||||||
|
}
|
||||||
|
|
||||||
|
return articles.sort(function (a, b) {
|
||||||
|
return new Date(b.updatedAt) - new Date(a.updatedAt)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
searchArticle: searchArticle
|
||||||
|
}
|
||||||
27
browser/main/Mixins/AuthFilter.js
Normal file
27
browser/main/Mixins/AuthFilter.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/* global localStorage*/
|
||||||
|
|
||||||
|
var mixin = {}
|
||||||
|
|
||||||
|
mixin.OnlyGuest = {
|
||||||
|
componentDidMount: function () {
|
||||||
|
var currentUser = localStorage.getItem('currentUser')
|
||||||
|
|
||||||
|
if (currentUser == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.transitionTo('userHome', {userName: currentUser.name})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin.OnlyUser = {
|
||||||
|
componentDidMount: function () {
|
||||||
|
var currentUser = localStorage.getItem('currentUser')
|
||||||
|
|
||||||
|
if (currentUser == null) {
|
||||||
|
this.transitionTo('login')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = mixin
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
(function (root, factory) {
|
|
||||||
module.exports = factory()
|
|
||||||
}(this, function () {
|
|
||||||
function getIn (object, path) {
|
|
||||||
var stack = path.split('.')
|
|
||||||
while (stack.length > 1) {
|
|
||||||
object = object[stack.shift()]
|
|
||||||
}
|
|
||||||
return object[stack.shift()]
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateIn (object, path, value) {
|
|
||||||
var current = object
|
|
||||||
var stack = path.split('.')
|
|
||||||
while (stack.length > 1) {
|
|
||||||
current = current[stack.shift()]
|
|
||||||
}
|
|
||||||
current[stack.shift()] = value
|
|
||||||
return object
|
|
||||||
}
|
|
||||||
|
|
||||||
function setPartialState (component, path, value) {
|
|
||||||
component.setState(
|
|
||||||
updateIn(component.state, path, value))
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
LinkedStateMixin: {
|
|
||||||
linkState: function (path) {
|
|
||||||
return {
|
|
||||||
value: getIn(this.state, path),
|
|
||||||
requestChange: setPartialState.bind(null, this, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}))
|
|
||||||
31
browser/main/Mixins/LinkedState.js
Normal file
31
browser/main/Mixins/LinkedState.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
function getIn (object, path) {
|
||||||
|
var stack = path.split('.')
|
||||||
|
while (stack.length > 1) {
|
||||||
|
object = object[stack.shift()]
|
||||||
|
}
|
||||||
|
return object[stack.shift()]
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateIn (object, path, value) {
|
||||||
|
var current = object
|
||||||
|
var stack = path.split('.')
|
||||||
|
while (stack.length > 1) {
|
||||||
|
current = current[stack.shift()]
|
||||||
|
}
|
||||||
|
current[stack.shift()] = value
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPartialState (component, path, value) {
|
||||||
|
component.setState(
|
||||||
|
updateIn(component.state, path, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
linkState: function (path) {
|
||||||
|
return {
|
||||||
|
value: getIn(this.state, path),
|
||||||
|
requestChange: setPartialState.bind(null, this, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
browser/main/Mixins/Modal.jsx
Normal file
42
browser/main/Mixins/Modal.jsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
var React = require('react/addons')
|
||||||
|
var ModalBase = React.createClass({
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
component: null,
|
||||||
|
componentProps: {},
|
||||||
|
isHidden: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.setState({component: null, componentProps: null, isHidden: true})
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
var componentProps = this.state.componentProps
|
||||||
|
return (
|
||||||
|
<div className={'ModalBase' + (this.state.isHidden ? ' hide' : '')}>
|
||||||
|
<div onClick={this.close} className='modalBack'/>
|
||||||
|
{this.state.component == null ? null : (
|
||||||
|
<this.state.component {...componentProps} close={this.close}/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var modalBase = null
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
componentDidMount: function () {
|
||||||
|
if (modalBase == null) {
|
||||||
|
var el = document.createElement('div')
|
||||||
|
document.body.appendChild(el)
|
||||||
|
modalBase = React.render(<ModalBase/>, el)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openModal: function (component, props) {
|
||||||
|
modalBase.setState({component: component, componentProps: props, isHidden: false})
|
||||||
|
},
|
||||||
|
closeModal: function () {
|
||||||
|
modalBase.setState({isHidden: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
var AuthStore = require('../Stores/AuthStore')
|
|
||||||
|
|
||||||
var OnlyGuest = {
|
|
||||||
componentDidMount: function () {
|
|
||||||
if (AuthStore.check()) {
|
|
||||||
var user = AuthStore.getUser()
|
|
||||||
if (user == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var planet = user.Planets.length > 0 ? user.Planets[0] : null
|
|
||||||
if (planet == null) {
|
|
||||||
this.transitionTo('user', {userName: user.name})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = OnlyGuest
|
|
||||||
112
browser/main/Services/Hq.js
Normal file
112
browser/main/Services/Hq.js
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/* global localStorage */
|
||||||
|
|
||||||
|
var request = require('superagent-promise')(require('superagent'), Promise)
|
||||||
|
var apiUrl = require('../../../config').apiUrl
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Auth
|
||||||
|
login: function (input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'auth')
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
signup: function (input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'auth/signup')
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
getUser: function () {
|
||||||
|
return request
|
||||||
|
.get(apiUrl + 'auth/user')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
changePassword: function (input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'auth/password')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
fetchUser: function (userName) {
|
||||||
|
return request
|
||||||
|
.get(apiUrl + 'resources/' + userName)
|
||||||
|
},
|
||||||
|
updateUser: function (userName, input) {
|
||||||
|
return request
|
||||||
|
.put(apiUrl + 'resources/' + userName)
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
createPlanet: function (userName, input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'resources/' + userName + '/planets')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
fetchPlanet: function (userName, planetName) {
|
||||||
|
return request
|
||||||
|
.get(apiUrl + 'resources/' + userName + '/planets/' + planetName)
|
||||||
|
},
|
||||||
|
createCode: function (userName, planetName, input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/codes')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
updateCode: function (userName, planetName, localId, input) {
|
||||||
|
return request
|
||||||
|
.put(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/codes/' + localId)
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
destroyCode: function (userName, planetName, localId) {
|
||||||
|
return request
|
||||||
|
.del(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/codes/' + localId)
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
createNote: function (userName, planetName, input) {
|
||||||
|
return request
|
||||||
|
.post(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/notes')
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
updateNote: function (userName, planetName, localId, input) {
|
||||||
|
return request
|
||||||
|
.put(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/notes/' + localId)
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
.send(input)
|
||||||
|
},
|
||||||
|
destroyNote: function (userName, planetName, localId) {
|
||||||
|
return request
|
||||||
|
.del(apiUrl + 'resources/' + userName + '/planets/' + planetName + '/notes/' + localId)
|
||||||
|
.set({
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('token')
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// Search
|
||||||
|
searchTag: function (tagName) {
|
||||||
|
return request
|
||||||
|
.get(apiUrl + 'search/tags')
|
||||||
|
.query({name: tagName})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,17 +2,10 @@
|
|||||||
var Reflux = require('reflux')
|
var Reflux = require('reflux')
|
||||||
var request = require('superagent')
|
var request = require('superagent')
|
||||||
|
|
||||||
var AuthActions = require('../Actions/AuthActions')
|
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
var apiUrl = require('../../../config').apiUrl
|
||||||
|
|
||||||
var AuthStore = Reflux.createStore({
|
var AuthStore = Reflux.createStore({
|
||||||
init: function () {
|
init: function () {
|
||||||
this.listenTo(AuthActions.login, this.login)
|
|
||||||
this.listenTo(AuthActions.register, this.register)
|
|
||||||
this.listenTo(AuthActions.logout, this.logout)
|
|
||||||
this.listenTo(AuthActions.updateProfile, this.updateProfile)
|
|
||||||
this.listenTo(AuthActions.refreshUser, this.refreshUser)
|
|
||||||
},
|
},
|
||||||
// Reflux Store
|
// Reflux Store
|
||||||
login: function (input) {
|
login: function (input) {
|
||||||
@@ -91,7 +84,7 @@ var AuthStore = Reflux.createStore({
|
|||||||
},
|
},
|
||||||
logout: function () {
|
logout: function () {
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
localStorage.removeItem('user')
|
localStorage.removeItem('currentUser')
|
||||||
|
|
||||||
this.trigger({
|
this.trigger({
|
||||||
status: 'loggedOut'
|
status: 'loggedOut'
|
||||||
@@ -129,7 +122,7 @@ var AuthStore = Reflux.createStore({
|
|||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
getUser: function () {
|
getUser: function () {
|
||||||
var userJSON = localStorage.getItem('user')
|
var userJSON = localStorage.getItem('currentUser')
|
||||||
if (userJSON == null) return null
|
if (userJSON == null) return null
|
||||||
return JSON.parse(userJSON)
|
return JSON.parse(userJSON)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,359 +1,104 @@
|
|||||||
/* global localStorage */
|
/* global localStorage */
|
||||||
|
|
||||||
var Reflux = require('reflux')
|
var Reflux = require('reflux')
|
||||||
var request = require('superagent')
|
|
||||||
|
|
||||||
var PlanetActions = require('../Actions/PlanetActions')
|
var actions = Reflux.createActions([
|
||||||
|
'updatePlanet',
|
||||||
|
'destroyPlanet',
|
||||||
|
'updateCode',
|
||||||
|
'destroyCode',
|
||||||
|
'updateNote',
|
||||||
|
'destroyNote'
|
||||||
|
])
|
||||||
|
|
||||||
var apiUrl = require('../../../config').apiUrl
|
module.exports = Reflux.createStore({
|
||||||
|
listenables: [actions],
|
||||||
|
Actions: actions,
|
||||||
|
onUpdatePlanet: function (planet) {
|
||||||
|
|
||||||
var PlanetStore = Reflux.createStore({
|
|
||||||
init: function () {
|
|
||||||
this.listenTo(PlanetActions.createPlanet, this.createPlanet)
|
|
||||||
this.listenTo(PlanetActions.fetchPlanet, this.fetchPlanet)
|
|
||||||
this.listenTo(PlanetActions.deletePlanet, this.deletePlanet)
|
|
||||||
this.listenTo(PlanetActions.changeName, this.changeName)
|
|
||||||
this.listenTo(PlanetActions.addUser, this.addUser)
|
|
||||||
this.listenTo(PlanetActions.removeUser, this.removeUser)
|
|
||||||
this.listenTo(PlanetActions.createSnippet, this.createSnippet)
|
|
||||||
this.listenTo(PlanetActions.updateSnippet, this.updateSnippet)
|
|
||||||
this.listenTo(PlanetActions.deleteSnippet, this.deleteSnippet)
|
|
||||||
this.listenTo(PlanetActions.createBlueprint, this.createBlueprint)
|
|
||||||
this.listenTo(PlanetActions.updateBlueprint, this.updateBlueprint)
|
|
||||||
this.listenTo(PlanetActions.deleteBlueprint, this.deleteBlueprint)
|
|
||||||
},
|
},
|
||||||
createPlanet: function (input) {
|
onUpdateCode: function (code) {
|
||||||
request
|
code.type = 'code'
|
||||||
.post(apiUrl + 'planets/create')
|
|
||||||
.set({
|
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
if (planet != null) {
|
||||||
})
|
var isNew = !planet.Codes.some(function (_code, index) {
|
||||||
.send(input)
|
if (code.id === _code.id) {
|
||||||
.end(function (err, res) {
|
planet.Codes.splice(index, 1, code)
|
||||||
if (err) {
|
return true
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
var planet = res.body
|
|
||||||
planet.Snippets = []
|
|
||||||
planet.Blueprints = []
|
|
||||||
planet.Articles = []
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'planetCreated',
|
|
||||||
data: planet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
fetchPlanet: function (userName, planetName) {
|
|
||||||
request
|
|
||||||
.get(apiUrl + userName + '/' + planetName)
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var planet = res.body
|
|
||||||
planet.userName = userName
|
|
||||||
|
|
||||||
planet.Snippets = planet.Snippets.map(function (snippet) {
|
|
||||||
snippet.type = 'snippet'
|
|
||||||
return snippet
|
|
||||||
})
|
|
||||||
|
|
||||||
planet.Blueprints = planet.Blueprints.map(function (blueprint) {
|
|
||||||
blueprint.type = 'blueprint'
|
|
||||||
return blueprint
|
|
||||||
})
|
|
||||||
|
|
||||||
localStorage.setItem('planet-' + planet.id, JSON.stringify(planet))
|
|
||||||
|
|
||||||
planet.Articles = planet.Snippets.concat(planet.Blueprints).sort(function (a, b) {
|
|
||||||
a = new Date(a.updatedAt)
|
|
||||||
b = new Date(b.updatedAt)
|
|
||||||
return a < b ? 1 : a > b ? -1 : 0
|
|
||||||
})
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'planetFetched',
|
|
||||||
data: planet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
deletePlanet: function (userName, planetName) {
|
|
||||||
request
|
|
||||||
.del(apiUrl + userName + '/' + planetName)
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var planet = res.body
|
|
||||||
localStorage.removeItem('planet-' + planet.id)
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'planetDeleted',
|
|
||||||
data: planet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
changeName: function (userName, planetName, name) {
|
|
||||||
request
|
|
||||||
.put(apiUrl + userName + '/' + planetName)
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
})
|
||||||
.send({name: name})
|
|
||||||
.end(function (err, res) {
|
if (isNew) planet.Codes.unshift(code)
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
||||||
this.trigger(null)
|
}
|
||||||
return
|
|
||||||
|
this.trigger({
|
||||||
|
status: 'codeUpdated',
|
||||||
|
data: code
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDestroyCode: function (code) {
|
||||||
|
var planet = JSON.parse(localStorage.getItem('planet-' + code.PlanetId))
|
||||||
|
if (planet != null) {
|
||||||
|
planet.Codes.some(function (_code, index) {
|
||||||
|
if (code.id === _code.id) {
|
||||||
|
planet.Codes.splice(index, 1)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
var planet = res.body
|
|
||||||
|
|
||||||
var user = JSON.parse(localStorage.getItem('user'))
|
|
||||||
user.Planets.some(function (_planet, index) {
|
|
||||||
if (planet.id === _planet.id) {
|
|
||||||
user.Planets[index].name = planet.name
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
localStorage.setItem('user', JSON.stringify(user))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'nameChanged',
|
|
||||||
data: planet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
addUser: function (planetName, userName) {
|
|
||||||
request
|
|
||||||
.post(apiUrl + planetName + '/users')
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
})
|
||||||
.send({name: userName})
|
|
||||||
.end(function (err, res) {
|
localStorage.setItem('planet-' + code.PlanetId, JSON.stringify(planet))
|
||||||
if (err) {
|
}
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
this.trigger({
|
||||||
return
|
status: 'codeDestroyed',
|
||||||
|
data: code
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onUpdateNote: function (note) {
|
||||||
|
note.type = 'note'
|
||||||
|
|
||||||
|
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
||||||
|
if (planet != null) {
|
||||||
|
var isNew = !planet.Notes.some(function (_note, index) {
|
||||||
|
if (note.id === _note.id) {
|
||||||
|
planet.Notes.splice(index, 1, note)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
var user = res.body
|
return false
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'userAdded',
|
|
||||||
data: user
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
removeUser: function (planetName, userName) {
|
|
||||||
request
|
|
||||||
.del(apiUrl + planetName + '/users')
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
})
|
||||||
.send({name: userName})
|
|
||||||
.end(function (err, res) {
|
if (isNew) planet.Codes.unshift(note)
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
||||||
this.trigger(null)
|
}
|
||||||
return
|
|
||||||
|
this.trigger({
|
||||||
|
status: 'noteUpdated',
|
||||||
|
data: note
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDestroyNote: function (note) {
|
||||||
|
var planet = JSON.parse(localStorage.getItem('planet-' + note.PlanetId))
|
||||||
|
if (planet != null) {
|
||||||
|
planet.Notes.some(function (_note, index) {
|
||||||
|
if (note.id === _note.id) {
|
||||||
|
planet.Notes.splice(index, 1)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
var user = res.body
|
return false
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'userRemoved',
|
|
||||||
data: user
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
createSnippet: function (planetName, input) {
|
|
||||||
input.description = input.description.substring(0, 255)
|
|
||||||
request
|
|
||||||
.post(apiUrl + planetName + '/snippets')
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
})
|
||||||
.send(input)
|
|
||||||
.end(function (req, res) {
|
|
||||||
var snippet = res.body
|
|
||||||
snippet.type = 'snippet'
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
|
localStorage.setItem('planet-' + note.PlanetId, JSON.stringify(planet))
|
||||||
planet.Snippets.unshift(snippet)
|
}
|
||||||
localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
|
|
||||||
|
|
||||||
this.trigger({
|
this.trigger({
|
||||||
status: 'articleCreated',
|
status: 'noteDestroyed',
|
||||||
data: snippet
|
data: note
|
||||||
})
|
})
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
updateSnippet: function (id, input) {
|
|
||||||
input.description = input.description.substring(0, 255)
|
|
||||||
request
|
|
||||||
.put(apiUrl + 'snippets/id/' + id)
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
|
||||||
.send(input)
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var snippet = res.body
|
|
||||||
snippet.type = 'snippet'
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
|
|
||||||
planet.Snippets.some(function (_snippet, index) {
|
|
||||||
if (snippet.id === _snippet) {
|
|
||||||
planet.Snippets[index] = snippet
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'articleUpdated',
|
|
||||||
data: snippet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
deleteSnippet: function (id) {
|
|
||||||
request
|
|
||||||
.del(apiUrl + 'snippets/id/' + id)
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var snippet = res.body
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
|
|
||||||
planet.Snippets.some(function (_snippet, index) {
|
|
||||||
if (snippet.id === _snippet) {
|
|
||||||
planet.splice(index, 1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'articleDeleted',
|
|
||||||
data: snippet
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
createBlueprint: function (planetName, input) {
|
|
||||||
input.title = input.title.substring(0, 255)
|
|
||||||
request
|
|
||||||
.post(apiUrl + planetName + '/blueprints')
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
|
||||||
.send(input)
|
|
||||||
.end(function (req, res) {
|
|
||||||
var blueprint = res.body
|
|
||||||
blueprint.type = 'blueprint'
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
|
|
||||||
planet.Blueprints.unshift(blueprint)
|
|
||||||
localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(planet))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'articleCreated',
|
|
||||||
data: blueprint
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
updateBlueprint: function (id, input) {
|
|
||||||
input.title = input.title.substring(0, 255)
|
|
||||||
request
|
|
||||||
.put(apiUrl + 'blueprints/id/' + id)
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
|
||||||
.send(input)
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var blueprint = res.body
|
|
||||||
blueprint.type = 'blueprint'
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
|
|
||||||
planet.Blueprints.some(function (_blueprint, index) {
|
|
||||||
if (blueprint.id === _blueprint) {
|
|
||||||
planet.Blueprints[index] = blueprint
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(blueprint))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'articleUpdated',
|
|
||||||
data: blueprint
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
},
|
|
||||||
deleteBlueprint: function (id) {
|
|
||||||
request
|
|
||||||
.del(apiUrl + 'blueprints/id/' + id)
|
|
||||||
.set({
|
|
||||||
Authorization: 'Bearer ' + localStorage.getItem('token')
|
|
||||||
})
|
|
||||||
.send()
|
|
||||||
.end(function (err, res) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err)
|
|
||||||
this.trigger(null)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var blueprint = res.body
|
|
||||||
|
|
||||||
var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
|
|
||||||
planet.Blueprints.some(function (_blueprint, index) {
|
|
||||||
if (blueprint.id === _blueprint) {
|
|
||||||
planet.splice(index, 1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(planet))
|
|
||||||
|
|
||||||
this.trigger({
|
|
||||||
status: 'articleDeleted',
|
|
||||||
data: blueprint
|
|
||||||
})
|
|
||||||
}.bind(this))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = PlanetStore
|
|
||||||
|
|||||||
23
browser/main/Stores/UserStore.js
Normal file
23
browser/main/Stores/UserStore.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
var Reflux = require('reflux')
|
||||||
|
|
||||||
|
var actions = Reflux.createActions([
|
||||||
|
'update',
|
||||||
|
'destroy'
|
||||||
|
])
|
||||||
|
|
||||||
|
module.exports = Reflux.createStore({
|
||||||
|
listenables: [actions],
|
||||||
|
onUpdate: function (user) {
|
||||||
|
this.trigger({
|
||||||
|
status: 'userUpdated',
|
||||||
|
data: user
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDestroy: function (user) {
|
||||||
|
this.trigger({
|
||||||
|
status: 'userDestroyed',
|
||||||
|
data: user
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Actions: actions
|
||||||
|
})
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>CodeXen v0.2.0</title>
|
<title>CodeXen v0.2.1</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
||||||
|
|
||||||
@@ -9,12 +9,6 @@
|
|||||||
<link rel="shortcut icon" href="favicon.ico">
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('mousewheel', function(e) {
|
|
||||||
if(e.deltaY % 1 !== 0) {
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!Object.assign) {
|
if (!Object.assign) {
|
||||||
Object.defineProperty(Object, 'assign', {
|
Object.defineProperty(Object, 'assign', {
|
||||||
enumerable: false,
|
enumerable: false,
|
||||||
|
|||||||
@@ -4,26 +4,32 @@ var ReactRouter = require('react-router')
|
|||||||
var Route = ReactRouter.Route
|
var Route = ReactRouter.Route
|
||||||
var DefaultRoute = ReactRouter.DefaultRoute
|
var DefaultRoute = ReactRouter.DefaultRoute
|
||||||
|
|
||||||
var MainContainer = require('./Containers/MainContainer.jsx')
|
var MainContainer = require('./Containers/MainContainer')
|
||||||
|
|
||||||
var LoginContainer = require('./Containers/LoginContainer.jsx')
|
var LoginContainer = require('./Containers/LoginContainer')
|
||||||
var RegisterContainer = require('./Containers/RegisterContainer.jsx')
|
var SignupContainer = require('./Containers/SignupContainer')
|
||||||
|
|
||||||
var UserContainer = require('./Containers/UserContainer.jsx')
|
var HomeContainer = require('./Containers/HomeContainer')
|
||||||
|
var UserContainer = require('./Containers/UserContainer')
|
||||||
|
|
||||||
var PlanetContainer = require('./Containers/PlanetContainer.jsx')
|
var PlanetContainer = require('./Containers/PlanetContainer')
|
||||||
|
|
||||||
var routes = (
|
var routes = (
|
||||||
<Route path='/' handler={MainContainer}>
|
<Route path='/' handler={MainContainer}>
|
||||||
<Route name='login' path='login' handler={LoginContainer}/>
|
<DefaultRoute name='root'/>
|
||||||
<Route name='register' path='register' handler={RegisterContainer}/>
|
|
||||||
|
|
||||||
<Route name='user' path=':userName' handler={UserContainer}>
|
<Route name='login' path='login' handler={LoginContainer}/>
|
||||||
<DefaultRoute name='userHome'/>
|
<Route name='signup' path='signup' handler={SignupContainer}/>
|
||||||
<Route name='planet' path=':planetName' handler={PlanetContainer}>
|
|
||||||
<DefaultRoute name='planetHome'/>
|
<Route name='home' path='home' handler={HomeContainer}>
|
||||||
<Route name='snippets' path='snippets/:localId'/>
|
<DefaultRoute name='homeEmpty'/>
|
||||||
<Route name='blueprints' path='blueprints/:localId'/>
|
<Route name='user' path=':userName' handler={UserContainer}>
|
||||||
|
<DefaultRoute name='userHome'/>
|
||||||
|
<Route name='planet' path=':planetName' handler={PlanetContainer}>
|
||||||
|
<DefaultRoute name='planetHome'/>
|
||||||
|
<Route name='codes' path='codes/:localId'/>
|
||||||
|
<Route name='notes' path='notes/:localId'/>
|
||||||
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.LoginContainer, .RegisterContainer
|
.LoginContainer, .SignupContainer
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
padding 25px 15px
|
padding 25px 15px
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
@@ -58,6 +58,9 @@
|
|||||||
margin-top 15px
|
margin-top 15px
|
||||||
margin-bottom 15px
|
margin-bottom 15px
|
||||||
height 44px
|
height 44px
|
||||||
|
padding 5px
|
||||||
|
border-radius 10px
|
||||||
|
line-height 44px
|
||||||
text-align center
|
text-align center
|
||||||
.alertInfo
|
.alertInfo
|
||||||
alertInfo()
|
alertInfo()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
navigationWidth= 200px
|
||||||
|
articleListWidth= 275px
|
||||||
|
|
||||||
.PlanetContainer
|
.PlanetContainer
|
||||||
absolute top bottom right
|
absolute top bottom right left
|
||||||
left 55px
|
|
||||||
.tags
|
.tags
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
margin 0 2px
|
margin 0 2px
|
||||||
text-decoration underline
|
text-decoration underline
|
||||||
cursor pointer
|
cursor pointer
|
||||||
|
font-size 0.9em
|
||||||
&.noTag
|
&.noTag
|
||||||
color inactiveTextColor
|
color inactiveTextColor
|
||||||
font-size 0.8em
|
font-size 0.8em
|
||||||
@@ -26,7 +29,7 @@
|
|||||||
absolute top left bottom
|
absolute top left bottom
|
||||||
overflow hidden
|
overflow hidden
|
||||||
display inline-block
|
display inline-block
|
||||||
width 200px
|
width navigationWidth
|
||||||
.userName
|
.userName
|
||||||
position absolute
|
position absolute
|
||||||
left 15px
|
left 15px
|
||||||
@@ -67,7 +70,7 @@
|
|||||||
.headerControl
|
.headerControl
|
||||||
noSelect()
|
noSelect()
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
left 200px
|
left navigationWidth
|
||||||
.searchInput
|
.searchInput
|
||||||
display block
|
display block
|
||||||
position absolute
|
position absolute
|
||||||
@@ -81,32 +84,36 @@
|
|||||||
top 8px
|
top 8px
|
||||||
left 12px
|
left 12px
|
||||||
color inactiveTextColor
|
color inactiveTextColor
|
||||||
.refreshButton, .settingButton
|
.refreshButton
|
||||||
display block
|
display block
|
||||||
position absolute
|
position absolute
|
||||||
top 12px
|
top 12px
|
||||||
font-size em
|
right 55px
|
||||||
btnDefault()
|
|
||||||
box-sizing border-box
|
|
||||||
circle()
|
|
||||||
width 28px
|
width 28px
|
||||||
height 28px
|
height 28px
|
||||||
|
btnDefault()
|
||||||
|
circle()
|
||||||
text-align center
|
text-align center
|
||||||
cursor pointer
|
cursor pointer
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
&:focus, &.focus
|
&:focus, &.focus
|
||||||
outline none
|
outline none
|
||||||
.refreshButton
|
.logo
|
||||||
right 45px
|
display block
|
||||||
.settingButton
|
position absolute
|
||||||
|
top 4px
|
||||||
right 10px
|
right 10px
|
||||||
|
cursor pointer
|
||||||
|
transition 0.1s
|
||||||
|
opacity 0.9
|
||||||
|
&:hover, &.hover
|
||||||
|
opacity 1
|
||||||
|
|
||||||
.PlanetNavigator
|
.PlanetNavigator
|
||||||
absolute bottom left
|
absolute bottom left
|
||||||
noSelect()
|
noSelect()
|
||||||
top 55px
|
top 55px
|
||||||
width 200px
|
width navigationWidth
|
||||||
border-right solid 1px highlightenBorderColor
|
border-right solid 1px highlightenBorderColor
|
||||||
padding 10px
|
padding 10px
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
@@ -127,44 +134,12 @@
|
|||||||
transition 0.1s
|
transition 0.1s
|
||||||
btnDefault()
|
btnDefault()
|
||||||
border none
|
border none
|
||||||
.usersLabel
|
|
||||||
margin-top 35px
|
|
||||||
margin-bottom 5px
|
|
||||||
.users
|
|
||||||
li
|
|
||||||
width 44px
|
|
||||||
height 44px
|
|
||||||
float left
|
|
||||||
margin 3px
|
|
||||||
line-height 44px
|
|
||||||
.userPhoto
|
|
||||||
circle()
|
|
||||||
width 44px
|
|
||||||
height 44px
|
|
||||||
box-shadow 1px 1px 4px 0px #C5C5C5
|
|
||||||
.userTooltip
|
|
||||||
position absolute
|
|
||||||
z-index 500
|
|
||||||
background-color transparentify(invBackgroundColor, 80%)
|
|
||||||
color invTextColor
|
|
||||||
padding 10px
|
|
||||||
line-height 1em
|
|
||||||
border-radius 5px
|
|
||||||
margin-top -15px
|
|
||||||
opacity 0
|
|
||||||
transition 0.1s
|
|
||||||
pointer-events none
|
|
||||||
&:hover .userTooltip
|
|
||||||
opacity 1
|
|
||||||
&.addUserButton
|
|
||||||
circle()
|
|
||||||
|
|
||||||
|
|
||||||
.PlanetArticleList
|
.PlanetArticleList
|
||||||
absolute bottom right
|
absolute bottom right
|
||||||
left 200px
|
left navigationWidth
|
||||||
top 55px
|
top 55px
|
||||||
width 250px
|
width articleListWidth
|
||||||
border-right solid 1px highlightenBorderColor
|
border-right solid 1px highlightenBorderColor
|
||||||
|
|
||||||
&>ul
|
&>ul
|
||||||
@@ -177,22 +152,28 @@
|
|||||||
padding 10px
|
padding 10px
|
||||||
cursor pointer
|
cursor pointer
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
.itemHeader
|
clearfix()
|
||||||
clearfix()
|
.itemLeft
|
||||||
margin-bottom 15px
|
|
||||||
.callSign, .title
|
|
||||||
float left
|
float left
|
||||||
font-weight 600
|
width 25px
|
||||||
font-size 1.1em
|
text-align center
|
||||||
line-height 140%
|
.profileImage
|
||||||
.updatedAt
|
margin-bottom 5px
|
||||||
float right
|
.fa
|
||||||
line-height 16px
|
line-height 25px
|
||||||
color lighten(textColor, 25%)
|
.itemRight
|
||||||
font-size 0.8em
|
float left
|
||||||
.description
|
width 225px
|
||||||
line-height 120%
|
overflow-x hidden
|
||||||
margin-bottom 15px
|
padding-left 10px
|
||||||
|
.updatedAt
|
||||||
|
margin-bottom 10px
|
||||||
|
color lighten(textColor, 25%)
|
||||||
|
font-size 0.7em
|
||||||
|
.description
|
||||||
|
line-height 120%
|
||||||
|
margin-bottom 15px
|
||||||
|
font-size 1em
|
||||||
&:hover, &.hover
|
&:hover, &.hover
|
||||||
background-color hoverBackgroundColor
|
background-color hoverBackgroundColor
|
||||||
&:active, &.active
|
&:active, &.active
|
||||||
@@ -205,7 +186,7 @@
|
|||||||
.PlanetArticleDetail
|
.PlanetArticleDetail
|
||||||
absolute right bottom
|
absolute right bottom
|
||||||
top 55px
|
top 55px
|
||||||
left 450px
|
left navigationWidth + articleListWidth
|
||||||
&>.viewer-header
|
&>.viewer-header
|
||||||
height 44px
|
height 44px
|
||||||
line-height 44px
|
line-height 44px
|
||||||
@@ -223,7 +204,7 @@
|
|||||||
absolute bottom right
|
absolute bottom right
|
||||||
left 1px
|
left 1px
|
||||||
top 44px
|
top 44px
|
||||||
&.snippetDetail>.viewer-body
|
&.codeDetail>.viewer-body
|
||||||
.viewer-detail
|
.viewer-detail
|
||||||
border-bottom solid 1px borderColor
|
border-bottom solid 1px borderColor
|
||||||
height 150px
|
height 150px
|
||||||
@@ -243,7 +224,7 @@
|
|||||||
absolute left right
|
absolute left right
|
||||||
top 155px
|
top 155px
|
||||||
bottom 5px
|
bottom 5px
|
||||||
&.blueprintDetail>.viewer-body
|
&.noteDetail>.viewer-body
|
||||||
.tags
|
.tags
|
||||||
absolute top
|
absolute top
|
||||||
left 15px
|
left 15px
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
.UserContainer
|
.HomeContainer
|
||||||
.UserNavigator
|
.HomeNavigator
|
||||||
background-color planetNavBgColor
|
background-color planetNavBgColor
|
||||||
absolute left top bottom
|
absolute left top bottom
|
||||||
width 55px
|
width 55px
|
||||||
text-align center
|
text-align center
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
border-right solid 1px borderColor
|
border-right solid 1px borderColor
|
||||||
.userProfile
|
.profileButton
|
||||||
display block
|
display block
|
||||||
width 55px
|
width 55px
|
||||||
height 55px
|
height 55px
|
||||||
@@ -17,12 +17,87 @@
|
|||||||
padding 0
|
padding 0
|
||||||
cursor pointer
|
cursor pointer
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
|
border none
|
||||||
img
|
img
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
opacity 0.9
|
opacity 0.9
|
||||||
&.vivid.active, &.focus, &:focus, &.hover, &:hover
|
&.vivid.active, &.focus, &:focus, &.hover, &:hover
|
||||||
img
|
img
|
||||||
opacity 1
|
opacity 1
|
||||||
|
.profilePopup
|
||||||
|
position fixed
|
||||||
|
left 35px
|
||||||
|
top 35px
|
||||||
|
z-index popupZIndex
|
||||||
|
width 200px
|
||||||
|
background-color backgroundColor
|
||||||
|
box-shadow popupShadow
|
||||||
|
border-radius 10px
|
||||||
|
padding 10px 0 0px
|
||||||
|
&.close
|
||||||
|
display none
|
||||||
|
.profileGroup
|
||||||
|
margin-bottom 10px
|
||||||
|
.profileGroupLabel
|
||||||
|
text-align left
|
||||||
|
height 1em
|
||||||
|
padding 0 15px
|
||||||
|
span
|
||||||
|
position absolute
|
||||||
|
z-index 2
|
||||||
|
background-color backgroundColor
|
||||||
|
padding-right 5px
|
||||||
|
color inactiveTextColor
|
||||||
|
font-size 0.8em
|
||||||
|
&::before
|
||||||
|
content ''
|
||||||
|
position absolute
|
||||||
|
display block
|
||||||
|
z-index 1
|
||||||
|
height 0.5em
|
||||||
|
width 175px
|
||||||
|
border-bottom solid 1px borderColor
|
||||||
|
.profileGroupList
|
||||||
|
li
|
||||||
|
clearfix()
|
||||||
|
&:hover
|
||||||
|
background-color hoverBackgroundColor
|
||||||
|
.userName
|
||||||
|
float left
|
||||||
|
width 155px
|
||||||
|
padding 10px 15px
|
||||||
|
text-align left
|
||||||
|
display block
|
||||||
|
text-decoration none
|
||||||
|
cursor pointer
|
||||||
|
.userSetting
|
||||||
|
float right
|
||||||
|
display block
|
||||||
|
padding 10px 0
|
||||||
|
width 45px
|
||||||
|
cursor pointer
|
||||||
|
.createNewTeam
|
||||||
|
btnStripDefault()
|
||||||
|
width 100%
|
||||||
|
padding 10px 20px
|
||||||
|
font-size 1em
|
||||||
|
cursor pointer
|
||||||
|
text-align left
|
||||||
|
.controlGroup
|
||||||
|
list-style none
|
||||||
|
border-top solid 1px borderColor
|
||||||
|
padding 10px 0
|
||||||
|
li
|
||||||
|
&:hover
|
||||||
|
background-color hoverBackgroundColor
|
||||||
|
button
|
||||||
|
btnStripDefault()
|
||||||
|
width 100%
|
||||||
|
padding 10px 20px
|
||||||
|
font-size 1em
|
||||||
|
cursor pointer
|
||||||
|
text-align left
|
||||||
|
|
||||||
ul.planetList>li
|
ul.planetList>li
|
||||||
margin 15px 0
|
margin 15px 0
|
||||||
.shortCut
|
.shortCut
|
||||||
@@ -91,29 +166,57 @@
|
|||||||
border-color darken(brandBorderColor, 10%)
|
border-color darken(brandBorderColor, 10%)
|
||||||
background-color brandColor
|
background-color brandColor
|
||||||
color white
|
color white
|
||||||
.UserHome
|
.UserContainer
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
left 55px
|
left 55px
|
||||||
box-sizing border-box
|
|
||||||
padding 15px
|
|
||||||
h1
|
|
||||||
margin 15px 0
|
|
||||||
.userProfile
|
.userProfile
|
||||||
|
absolute top left right
|
||||||
|
padding 15px
|
||||||
|
border-bottom solid 1px borderColor
|
||||||
|
height 125px
|
||||||
clearfix()
|
clearfix()
|
||||||
.userPhoto
|
.userPhoto
|
||||||
circle()
|
circle()
|
||||||
float left
|
float left
|
||||||
margin 25px
|
margin 5px 15px 15px
|
||||||
.userIntro
|
.userInfo
|
||||||
float left
|
float left
|
||||||
margin-top 25px
|
margin-top 15px
|
||||||
.userProfileName
|
.userProfileName
|
||||||
font-size 2em
|
|
||||||
margin-bottom 15px
|
|
||||||
.userName
|
|
||||||
font-size 1.5em
|
font-size 1.5em
|
||||||
.userPlanetList
|
color brandColor
|
||||||
padding-left 20px
|
margin-bottom 10px
|
||||||
li
|
.userName
|
||||||
font-size 1.3em
|
font-size 1.1em
|
||||||
margin 10px
|
.editProfileButton
|
||||||
|
float right
|
||||||
|
btnDefault()
|
||||||
|
margin-top 25px
|
||||||
|
padding 10px 15px
|
||||||
|
border-radius 5px
|
||||||
|
.teamList
|
||||||
|
absolute left bottom
|
||||||
|
top 125px
|
||||||
|
width 200px
|
||||||
|
padding 15px
|
||||||
|
border-right solid 1px borderColor
|
||||||
|
overflow-y auto
|
||||||
|
.teamLabel
|
||||||
|
font-size 1.2em
|
||||||
|
margin-bottom 15px
|
||||||
|
.planetList
|
||||||
|
absolute right bottom
|
||||||
|
top 125px
|
||||||
|
left 200px
|
||||||
|
padding 15px
|
||||||
|
overflow-y auto
|
||||||
|
.planetLabel
|
||||||
|
font-size 1.2em
|
||||||
|
margin-bottom 25px
|
||||||
|
.planetGroup
|
||||||
|
margin-left 15px
|
||||||
|
.planetGroupLabel
|
||||||
|
font-size 1.1em
|
||||||
|
margin-bottom 15px
|
||||||
|
.planets
|
||||||
|
margin-left 15px
|
||||||
|
|||||||
@@ -6,10 +6,19 @@ global-reset()
|
|||||||
@import './components/*'
|
@import './components/*'
|
||||||
@import './containers/*'
|
@import './containers/*'
|
||||||
|
|
||||||
|
html, body
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
overflow hidden
|
||||||
|
|
||||||
body
|
body
|
||||||
font-family "Lato"
|
font-family "Lato"
|
||||||
color textColor
|
color textColor
|
||||||
font-size fontSize
|
font-size fontSize
|
||||||
|
font-weight 400
|
||||||
|
|
||||||
|
div, span, a, button, input
|
||||||
|
box-sizing border-box
|
||||||
|
|
||||||
h1
|
h1
|
||||||
font-size 2em
|
font-size 2em
|
||||||
@@ -33,9 +42,11 @@ a
|
|||||||
hr
|
hr
|
||||||
border-top none
|
border-top none
|
||||||
border-bottom solid 1px borderColor
|
border-bottom solid 1px borderColor
|
||||||
margin 25px 0
|
margin 15px 0
|
||||||
|
|
||||||
button
|
button
|
||||||
|
font-weight 400
|
||||||
|
cursor pointer
|
||||||
&:focus, &.focus
|
&:focus, &.focus
|
||||||
outline none
|
outline none
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
alert()
|
|
||||||
line-height 44px
|
|
||||||
border-radius 5px
|
|
||||||
|
|
||||||
alertSuccess()
|
alertSuccess()
|
||||||
alert()
|
|
||||||
background-color successBackgroundColor
|
background-color successBackgroundColor
|
||||||
color successTextColor
|
color successTextColor
|
||||||
|
|
||||||
alertError()
|
alertError()
|
||||||
alert()
|
|
||||||
background-color errorBackgroundColor
|
background-color errorBackgroundColor
|
||||||
color errorTextColor
|
color errorTextColor
|
||||||
|
|
||||||
alertInfo()
|
alertInfo()
|
||||||
alert()
|
|
||||||
background-color infoBackgroundColor
|
background-color infoBackgroundColor
|
||||||
color infoTextColor
|
color infoTextColor
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ btnDefault()
|
|||||||
border-color darken(brandBorderColor, 10%)
|
border-color darken(brandBorderColor, 10%)
|
||||||
background-color brandColor
|
background-color brandColor
|
||||||
color white
|
color white
|
||||||
|
&:disabled, &.disabled
|
||||||
|
opacity 0.6
|
||||||
|
|
||||||
btnPrimary()
|
btnPrimary()
|
||||||
border-style solid
|
border-style solid
|
||||||
@@ -25,3 +27,14 @@ btnPrimary()
|
|||||||
&:active, &.active
|
&:active, &.active
|
||||||
background-color brandColor
|
background-color brandColor
|
||||||
color white
|
color white
|
||||||
|
&:disabled, &.disabled
|
||||||
|
opacity 0.6
|
||||||
|
|
||||||
|
btnStripDefault()
|
||||||
|
border none
|
||||||
|
background-color transparent
|
||||||
|
color lightButtonColor
|
||||||
|
&:hover, &.hover, &:focus, &.focus
|
||||||
|
color darken(lightButtonColor, 50%)
|
||||||
|
&:active, &.active
|
||||||
|
color brandColor
|
||||||
|
|||||||
@@ -2,8 +2,15 @@ stripInput()
|
|||||||
border none
|
border none
|
||||||
border-bottom 1px solid borderColor
|
border-bottom 1px solid borderColor
|
||||||
padding 5px 15px
|
padding 5px 15px
|
||||||
box-sizing border-box
|
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
&:focus, &.focus
|
&:focus, &.focus
|
||||||
border-bottom 1px solid brandBorderColor
|
border-bottom 1px solid brandBorderColor
|
||||||
outline none
|
outline none
|
||||||
|
|
||||||
|
borderInput()
|
||||||
|
border solid 1px borderColor
|
||||||
|
padding 5px 15px
|
||||||
|
transition 0.1s
|
||||||
|
&:focus, &.focus
|
||||||
|
border-color brandBorderColor
|
||||||
|
outline none
|
||||||
|
|||||||
@@ -5,24 +5,24 @@ marked()
|
|||||||
margin 15px 0
|
margin 15px 0
|
||||||
h1
|
h1
|
||||||
font-size 2em
|
font-size 2em
|
||||||
margin 0.67em auto
|
margin 0 auto 0.67em
|
||||||
h2
|
h2
|
||||||
font-size 1.5em
|
font-size 1.5em
|
||||||
margin 0.83em auto
|
margin 0 auto 0.83em
|
||||||
h3
|
h3
|
||||||
font-size 1.17em
|
font-size 1.17em
|
||||||
margin 1em auto
|
margin 0 auto 1em
|
||||||
h4
|
h4
|
||||||
font-size 1em
|
font-size 1em
|
||||||
margin 1.33em auto
|
margin 0 auto 1.33em
|
||||||
h5
|
h5
|
||||||
font-size 0.83em
|
font-size 0.83em
|
||||||
margin 1.67em auto
|
margin 0 auto 1.67em
|
||||||
h6
|
h6
|
||||||
font-size 0.67em
|
font-size 0.67em
|
||||||
margin 2.33em auto
|
margin 2.33em auto
|
||||||
h1, h2, h3, h4, h5, h6
|
h1, h2, h3, h4, h5, h6
|
||||||
font-weight bold
|
font-weight font-weight 400
|
||||||
line-height 1.2em
|
line-height 1.2em
|
||||||
p
|
p
|
||||||
line-height 1.2em
|
line-height 1.2em
|
||||||
|
|||||||
@@ -1,40 +1,114 @@
|
|||||||
.ModalBase
|
.ModalBase
|
||||||
fixed top left right bottom
|
fixed top left bottom right
|
||||||
z-index 1000
|
z-index modalZIndex
|
||||||
overflow-y auto
|
|
||||||
overflow-x auto
|
|
||||||
background-color modalBaseColor
|
|
||||||
line-height 100%
|
|
||||||
&.hide
|
&.hide
|
||||||
display none
|
display none
|
||||||
|
.modalBack
|
||||||
|
absolute top left bottom right
|
||||||
|
background-color modalBackColor
|
||||||
|
z-index modalZIndex + 1
|
||||||
.modal
|
.modal
|
||||||
width 600px
|
position relative
|
||||||
|
width 650px
|
||||||
margin 50px auto 0
|
margin 50px auto 0
|
||||||
absolute top left right
|
z-index modalZIndex + 2
|
||||||
|
box-shadow popupShadow
|
||||||
background-color white
|
background-color white
|
||||||
border-radius 10px
|
border-radius 10px
|
||||||
padding 15px
|
padding 15px
|
||||||
box-shadow popupShadow
|
|
||||||
.modal-header
|
.modal-header
|
||||||
border-bottom solid 1px borderColor
|
border-bottom solid 1px borderColor
|
||||||
margin-bottom 15px
|
margin-bottom 10px
|
||||||
h1
|
h1
|
||||||
padding: 10px 0 15px;
|
padding 10px 0 15px
|
||||||
font-size: 1.5em;
|
font-size 1.5em
|
||||||
.modal-body
|
.modal-body
|
||||||
p
|
p
|
||||||
margin-bottom 15px
|
margin-bottom 10px
|
||||||
.modal-footer
|
.modal-footer
|
||||||
clearfix()
|
clearfix()
|
||||||
border-top solid 1px borderColor
|
border-top solid 1px borderColor
|
||||||
padding-top 15px
|
padding-top 10px
|
||||||
.modal-control
|
.modal-control
|
||||||
float right
|
float right
|
||||||
|
|
||||||
|
.EditProfileModal
|
||||||
|
height 500px
|
||||||
|
.leftPane
|
||||||
|
absolute top bottom left
|
||||||
|
width 175px
|
||||||
|
padding 20px
|
||||||
|
border-right solid 1px borderColor
|
||||||
|
.tabLabel
|
||||||
|
font-size 1.5em
|
||||||
|
margin-top 25px
|
||||||
|
margin-bottom 35px
|
||||||
|
color brandColor
|
||||||
|
.tabList button
|
||||||
|
btnStripDefault()
|
||||||
|
display block
|
||||||
|
width 100%
|
||||||
|
font-size 1.1em
|
||||||
|
padding 10px 5px
|
||||||
|
margin-bottom 15px
|
||||||
|
text-align left
|
||||||
|
.rightPane
|
||||||
|
absolute top bottom right
|
||||||
|
left 175px
|
||||||
|
padding 15px
|
||||||
|
.userInfoTab, .paswordTab
|
||||||
|
padding-top 45px
|
||||||
|
.formField
|
||||||
|
position relative
|
||||||
|
clearfix()
|
||||||
|
margin-bottom 15px
|
||||||
|
label
|
||||||
|
width 30%
|
||||||
|
display block
|
||||||
|
line-height 33px
|
||||||
|
float left
|
||||||
|
input
|
||||||
|
width 70%
|
||||||
|
display block
|
||||||
|
borderInput()
|
||||||
|
height 33px
|
||||||
|
font-size 1em
|
||||||
|
border-radius 10px
|
||||||
|
float left
|
||||||
|
.formConfirm
|
||||||
|
position relative
|
||||||
|
clearfix()
|
||||||
|
margin-bottom 15px
|
||||||
|
button
|
||||||
|
float right
|
||||||
|
btnDefault()
|
||||||
|
padding 10px 15px
|
||||||
|
border-radius 5px
|
||||||
|
font-size 1em
|
||||||
|
margin-left 5px
|
||||||
|
.alertInfo, .alertSuccess, .alertError
|
||||||
|
float right
|
||||||
|
padding 12px 10px
|
||||||
|
border-radius 5px
|
||||||
|
width 200px
|
||||||
|
font-size 1em
|
||||||
|
overflow-x hidden
|
||||||
|
white-space nowrap
|
||||||
|
transition 0.1s
|
||||||
|
&.hide
|
||||||
|
width 0
|
||||||
|
padding 12px 0
|
||||||
|
.alertInfo
|
||||||
|
alertInfo()
|
||||||
|
.alertSuccess
|
||||||
|
alertSuccess()
|
||||||
|
.alertError
|
||||||
|
alertError()
|
||||||
|
|
||||||
.LaunchModal
|
.LaunchModal
|
||||||
.modal-tab
|
.modal-tab
|
||||||
text-align center
|
text-align center
|
||||||
margin-bottom 15px
|
margin-bottom 10px
|
||||||
.btn-primary, .btn-default
|
.btn-primary, .btn-default
|
||||||
margin 0
|
margin 0
|
||||||
border-radius 0
|
border-radius 0
|
||||||
@@ -49,9 +123,6 @@
|
|||||||
border-left none
|
border-left none
|
||||||
border-top-right-radius 5px
|
border-top-right-radius 5px
|
||||||
border-bottom-right-radius 5px
|
border-bottom-right-radius 5px
|
||||||
textarea.snippetDescription
|
|
||||||
height 75px
|
|
||||||
font-size 0.9em
|
|
||||||
.Select
|
.Select
|
||||||
.Select-control
|
.Select-control
|
||||||
border-color borderColor
|
border-color borderColor
|
||||||
@@ -63,23 +134,30 @@
|
|||||||
.ace_editor
|
.ace_editor
|
||||||
border-radius 5px
|
border-radius 5px
|
||||||
border solid 1px borderColor
|
border solid 1px borderColor
|
||||||
.SnippetForm
|
.CodeForm, .NoteForm
|
||||||
|
.form-group
|
||||||
|
margin-bottom 10px
|
||||||
|
.CodeForm
|
||||||
|
textarea.codeDescription
|
||||||
|
height 75px
|
||||||
|
font-size 0.9em
|
||||||
|
margin-bottom 10px
|
||||||
.modeSelect.Select
|
.modeSelect.Select
|
||||||
display inline-block
|
display inline-block
|
||||||
width 200px
|
width 200px
|
||||||
margin-top -15px
|
|
||||||
top 14px
|
|
||||||
height 37px
|
height 37px
|
||||||
|
.Select-control
|
||||||
|
height 37px
|
||||||
.ace_editor
|
.ace_editor
|
||||||
height 258px
|
height 258px
|
||||||
.BlueprintForm
|
.NoteForm
|
||||||
.ace_editor
|
.ace_editor
|
||||||
height 358px
|
height 358px
|
||||||
.previewMode
|
.previewMode
|
||||||
absolute top right
|
absolute top right
|
||||||
font-size 0.8em
|
font-size 0.8em
|
||||||
line-height 24px
|
line-height 24px
|
||||||
padding 0 10px
|
padding 5 15px
|
||||||
background-color transparentify(invBackgroundColor, 0.2)
|
background-color transparentify(invBackgroundColor, 0.2)
|
||||||
color invTextColor
|
color invTextColor
|
||||||
border-top-right-radius 5px
|
border-top-right-radius 5px
|
||||||
@@ -98,13 +176,25 @@
|
|||||||
.nameInput
|
.nameInput
|
||||||
width 80%
|
width 80%
|
||||||
font-size 1.3em
|
font-size 1.3em
|
||||||
margin 35px auto
|
margin 25px auto 15px
|
||||||
text-align center
|
text-align center
|
||||||
.userNameSelect
|
.userNameSelect
|
||||||
width 80%
|
width 80%
|
||||||
font-size 1.3em
|
font-size 1.3em
|
||||||
margin 35px auto
|
margin 35px auto
|
||||||
text-align center
|
text-align center
|
||||||
|
.formField
|
||||||
|
text-align center
|
||||||
|
margin 0 auto 25px
|
||||||
|
select
|
||||||
|
display inline-block
|
||||||
|
width 150px
|
||||||
|
height 33px
|
||||||
|
border solid 1px borderColor
|
||||||
|
background-color white
|
||||||
|
padding 0 10px
|
||||||
|
margin 0 15px
|
||||||
|
|
||||||
.submitButton
|
.submitButton
|
||||||
display block
|
display block
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
@@ -150,7 +240,7 @@
|
|||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
left 200px
|
left 200px
|
||||||
padding 15px
|
padding 15px
|
||||||
.PersonalSettingModal.modal
|
.PreferencesModal.modal
|
||||||
.settingBody
|
.settingBody
|
||||||
.profile
|
.profile
|
||||||
height 500px
|
height 500px
|
||||||
@@ -272,48 +362,3 @@
|
|||||||
margin-right 0
|
margin-right 0
|
||||||
.deleteButton
|
.deleteButton
|
||||||
float left
|
float left
|
||||||
.members
|
|
||||||
height 500px
|
|
||||||
box-sizing border-box
|
|
||||||
padding-top 50px
|
|
||||||
.userList
|
|
||||||
height 275px
|
|
||||||
box-sizing border-box
|
|
||||||
border-bottom solid 1px borderColor
|
|
||||||
li
|
|
||||||
clearfix()
|
|
||||||
margin-bottom 10px
|
|
||||||
img.userPhoto
|
|
||||||
float left
|
|
||||||
width 44px
|
|
||||||
height 44px
|
|
||||||
circle()
|
|
||||||
box-shadow 1px 1px 4px 0px #C5C5C5
|
|
||||||
.userName
|
|
||||||
float left
|
|
||||||
height 44px
|
|
||||||
font-size 1.3em
|
|
||||||
line-height 44px
|
|
||||||
margin-left 15px
|
|
||||||
.userControl
|
|
||||||
float right
|
|
||||||
height 44px
|
|
||||||
.ownerLabel
|
|
||||||
height 44px
|
|
||||||
padding 0 15px
|
|
||||||
line-height 44px
|
|
||||||
.addUserForm
|
|
||||||
height 225px
|
|
||||||
.addUserLabel
|
|
||||||
margin-top 15px
|
|
||||||
font-size 1.3em
|
|
||||||
.addUserControl
|
|
||||||
clearfix()
|
|
||||||
margin-top 15px
|
|
||||||
.addUserSelect
|
|
||||||
float left
|
|
||||||
height 44px
|
|
||||||
width 350px
|
|
||||||
margin-top 5px
|
|
||||||
.addUserSubmit
|
|
||||||
float right
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ buttonBorderColor = #4C4C4C
|
|||||||
|
|
||||||
lightButtonColor = #898989
|
lightButtonColor = #898989
|
||||||
|
|
||||||
hoverBackgroundColor= transparentify(#444, 3%)
|
hoverBackgroundColor= transparentify(#444, 4%)
|
||||||
|
|
||||||
// v0.2.0
|
|
||||||
inactiveTextColor = #888
|
inactiveTextColor = #888
|
||||||
textColor = #4D4D4D
|
textColor = #4D4D4D
|
||||||
backgroundColor= white
|
backgroundColor= white
|
||||||
@@ -32,7 +31,7 @@ planetAnchorActiveColor = textColor
|
|||||||
planetAnchorActiveBgColor = white
|
planetAnchorActiveBgColor = white
|
||||||
|
|
||||||
popupShadow = 0 0 5px 0 #888
|
popupShadow = 0 0 5px 0 #888
|
||||||
modalBaseColor = transparentify(white, 65%)
|
modalBackColor = transparentify(white, 65%)
|
||||||
|
|
||||||
tableHeadBgColor = white
|
tableHeadBgColor = white
|
||||||
tableOddBgColor = #F9F9F9
|
tableOddBgColor = #F9F9F9
|
||||||
@@ -47,3 +46,6 @@ errorBackgroundColor= #F2DEDE
|
|||||||
errorTextColor= #A64444
|
errorTextColor= #A64444
|
||||||
infoBackgroundColor= #D9EDF7
|
infoBackgroundColor= #D9EDF7
|
||||||
infoTextColor= #34708E
|
infoTextColor= #34708E
|
||||||
|
|
||||||
|
modalZIndex= 1000
|
||||||
|
popupZIndex= 500
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
apiUrl: 'http://codexen-server-dex2-ezebi636yb.elasticbeanstalk.com/'
|
// apiUrl: 'http://codexen-server-dex2-ezebi636yb.elasticbeanstalk.com/'
|
||||||
// apiUrl: 'http://localhost:8000/'
|
apiUrl: 'http://localhost:8000/'
|
||||||
}
|
}
|
||||||
|
|||||||
21
main.js
21
main.js
@@ -17,44 +17,43 @@ var update = null
|
|||||||
// if (process.platform !== 'darwin') app.quit()
|
// if (process.platform !== 'darwin') app.quit()
|
||||||
// })
|
// })
|
||||||
|
|
||||||
var version = '0.2.0'
|
var version = app.getVersion()
|
||||||
var nn = require('node-notifier')
|
var nn = require('node-notifier')
|
||||||
var autoUpdater = require('auto-updater')
|
var autoUpdater = require('auto-updater')
|
||||||
|
|
||||||
autoUpdater
|
autoUpdater
|
||||||
.on('error', function (err, message) {
|
.on('error', function (err, message) {
|
||||||
nn.notify({
|
nn.notify({
|
||||||
title: 'Boost Update Center Ver. ' + version,
|
title: 'Error! Ver.' + version,
|
||||||
message: message
|
message: message
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('checking-for-update', function () {
|
.on('checking-for-update', function () {
|
||||||
nn.notify({
|
nn.notify({
|
||||||
title: 'Boost Update Center Ver. ' + version,
|
title: 'Boost launched!! Ver. ' + version,
|
||||||
message: 'Hello from Main processor, Mr. User!'
|
message: 'Checking update is available....'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('update-available', function () {
|
.on('update-available', function () {
|
||||||
nn.notify({
|
nn.notify({
|
||||||
title: 'Boost Update Center Ver. ' + version,
|
title: 'Update is available!! Ver. ' + version,
|
||||||
message: 'Update is available. Starting download latest build...'
|
message: 'Download started.. wait for the update ready.'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('update-not-available', function () {
|
.on('update-not-available', function () {
|
||||||
nn.notify({
|
nn.notify({
|
||||||
title: 'Boost Update Center Ver. ' + version,
|
title: 'Latest Build!! Ver. ' + version,
|
||||||
message: 'Latest Build :D'
|
message: 'Hope you to enjoy our app :D'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
|
.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
|
||||||
nn.notify({
|
nn.notify({
|
||||||
title: 'Boost Update Center Ver. ' + version,
|
title: 'Ready to Update!! v' + version,
|
||||||
message: 'Ready to Update: ' + releaseName
|
message: 'Click tray icon to update app: ' + releaseName
|
||||||
})
|
})
|
||||||
update = quitAndUpdate
|
update = quitAndUpdate
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
app.on('ready', function () {
|
app.on('ready', function () {
|
||||||
console.log('Version ' + version)
|
console.log('Version ' + version)
|
||||||
autoUpdater.setFeedUrl('http://localhost:8000/testcat/test/latest?version=' + version)
|
autoUpdater.setFeedUrl('http://localhost:8000/testcat/test/latest?version=' + version)
|
||||||
|
|||||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "codexen-app",
|
"name": "boost",
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"description": "CodeXen App",
|
"description": "Boost App",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "electron ./main.js",
|
"start": "electron ./main.js",
|
||||||
@@ -14,13 +14,12 @@
|
|||||||
"url": "git+https://github.com/Rokt33r/codexen-app.git"
|
"url": "git+https://github.com/Rokt33r/codexen-app.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"codexen",
|
"boost",
|
||||||
|
"b00st",
|
||||||
"snippet",
|
"snippet",
|
||||||
"template",
|
"template",
|
||||||
"task",
|
"task",
|
||||||
"runner",
|
"runner",
|
||||||
"remote",
|
|
||||||
"automator",
|
|
||||||
"code",
|
"code",
|
||||||
"storage",
|
"storage",
|
||||||
"short code"
|
"short code"
|
||||||
@@ -32,7 +31,6 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/Rokt33r/codexen-app#readme",
|
"homepage": "https://github.com/Rokt33r/codexen-app#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv": "^1.1.0",
|
|
||||||
"electron-stylus": "^0.1.0",
|
"electron-stylus": "^0.1.0",
|
||||||
"font-awesome": "^4.3.0",
|
"font-awesome": "^4.3.0",
|
||||||
"markdown-it": "^4.3.1",
|
"markdown-it": "^4.3.1",
|
||||||
@@ -45,7 +43,8 @@
|
|||||||
"react-router": "^0.13.3",
|
"react-router": "^0.13.3",
|
||||||
"react-select": "^0.5.4",
|
"react-select": "^0.5.4",
|
||||||
"reflux": "^0.2.8",
|
"reflux": "^0.2.8",
|
||||||
"superagent": "^1.2.0"
|
"superagent": "^1.2.0",
|
||||||
|
"superagent-promise": "^1.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"css-loader": "^0.15.1",
|
"css-loader": "^0.15.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user