1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 17:56:25 +00:00

restructure DONE

This commit is contained in:
Rokt33r
2015-10-13 18:07:33 +09:00
parent e5e8032ba1
commit 9a5e4b3f54
72 changed files with 79 additions and 7117 deletions

View File

@@ -1,3 +0,0 @@
{
"directory": "browser/vendor/"
}

7
.gitignore vendored
View File

@@ -1,7 +1,4 @@
build/
node_modules/
electron_build/
.env .env
dist/ node_modules/*
vendor/ !node_modules/boost
Boost-darwin-x64/ Boost-darwin-x64/

View File

@@ -1,4 +1,5 @@
var BrowserWindow = require('browser-window') var BrowserWindow = require('browser-window')
var path = require('path')
var mainWindow = new BrowserWindow({ var mainWindow = new BrowserWindow({
width: 1080, width: 1080,
@@ -10,7 +11,9 @@ var mainWindow = new BrowserWindow({
'standard-window': false 'standard-window': false
}) })
mainWindow.loadUrl('file://' + __dirname + '/browser/main/index.html') var url = path.resolve(__dirname, '../browser/main/index.html')
mainWindow.loadUrl('file://' + url)
mainWindow.setVisibleOnAllWorkspaces(true) mainWindow.setVisibleOnAllWorkspaces(true)

View File

@@ -1,11 +0,0 @@
{
"name": "codexen-app",
"dependencies": {
"react": "~0.13.3",
"fontawesome": "~4.3.0",
"react-router": "~0.13.3",
"reflux": "~0.2.8",
"moment": "~2.10.3",
"markdown-it": "~4.3.1"
}
}

View File

@@ -1,38 +0,0 @@
var React = require('react')
var ExternalLink = require('../Mixins/ExternalLink')
var KeyCaster = require('../Mixins/KeyCaster')
module.exports = React.createClass({
mixins: [ExternalLink, KeyCaster('aboutModal')],
propTypes: {
close: React.PropTypes.func
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
}
},
render: function () {
var version = global.version
return (
<div className='PreferencesModal sideNavModal modal'>
<div className='about1'>
<img className='logo' src='resources/favicon-230x230.png'/>
<div className='appInfo'>Boost {version == null || version.length === 0 ? 'DEV version' : 'v' + version}</div>
</div>
<div className='about2'>
<div className='externalLabel'>External links</div>
<ul className='externalList'>
<li><a onClick={this.openExternal} href='http://b00st.io'>Boost Homepage <i className='fa fa-external-link'/></a></li>
<li><a>Regulation <i className='fa fa-external-link'/></a></li>
<li><a>Private policy <i className='fa fa-external-link'/></a></li>
</ul>
</div>
</div>
)
}
})

View File

@@ -1,99 +0,0 @@
var React = require('react')
var Select = require('react-select')
var LinkedState = require('../Mixins/LinkedState')
var Hq = require('../Services/Hq')
var KeyCaster = require('../Mixins/KeyCaster')
var getOptions = function (input, callback) {
Hq.searchUser(input)
.then(function (res) {
callback(null, {
options: res.body.map(function (user) {
return {
label: user.name,
value: user.name
}
}),
complete: false
})
})
.catch(function (err) {
console.error(err)
})
}
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('addMemberModal')],
propTypes: {
team: React.PropTypes.object,
close: React.PropTypes.func
},
getInitialState: function () {
return {
userName: '',
role: 'member'
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
case 'submitAddMemberModal':
this.handleSubmit()
break
}
},
handleSubmit: function () {
this.setState({errorMessage: null}, function () {
Hq
.addMember(this.props.team.name, {
userName: this.state.userName,
role: this.state.role
})
.then(function (res) {
console.log(res.body)
this.props.close()
}.bind(this))
.catch(function (err) {
console.error(err)
if (err.status === 403) {
this.setState({errorMessage: err.response.body.message})
}
}.bind(this))
})
},
handleChange: function (value) {
this.setState({userName: value})
},
render: function () {
return (
<div className='AddMemberModal modal'>
<Select
name='userName'
value={this.state.userName}
placeholder='Username to add'
asyncOptions={getOptions}
onChange={this.handleChange}
className='userNameSelect'
/>
<div className='formField'>
Add member as
<select valueLink={this.linkState('role')}>
<option value={'member'}>Member</option>
<option value={'owner'}>Owner</option>
</select>
role
</div>
{this.state.errorMessage != null ? (<p className='errorAlert'>{this.state.errorMessage}</p>) : null}
<button onClick={this.handleSubmit} className='submitButton'><i className='fa fa-check'/></button>
</div>
)
}
})

View File

@@ -1,209 +0,0 @@
var React = require('react')
var moment = require('moment')
var _ = require('lodash')
var CodeEditor = require('./CodeEditor')
var MarkdownPreview = require('./MarkdownPreview')
var ModeIcon = require('./ModeIcon')
var Select = require('react-select')
var Modal = require('../Mixins/Modal')
var ForceUpdate = require('../Mixins/ForceUpdate')
var LinkedState = require('../Mixins/LinkedState')
var aceModes = require('../../../modules/ace-modes')
var modeOptions = aceModes.map(function (mode) {
return {
label: mode,
value: mode
}
})
module.exports = React.createClass({
mixins: [ForceUpdate(60000), Modal, LinkedState],
propTypes: {
currentArticle: React.PropTypes.object,
showOnlyWithTag: React.PropTypes.func,
planet: React.PropTypes.object,
switchDetailMode: React.PropTypes.func,
user: React.PropTypes.shape({
id: React.PropTypes.number,
name: React.PropTypes.string,
Folders: React.PropTypes.array
}),
article: React.PropTypes.object,
saveCurrentArticle: React.PropTypes.func,
detailMode: React.PropTypes.string
},
getInitialState: function () {
var article = this.props.currentArticle != null ? {
id: this.props.currentArticle.id,
title: this.props.currentArticle.title,
content: this.props.currentArticle.CurrentRevision.title,
tags: this.props.currentArticle.Tags.map(function (tag) {
return tag.name
}),
mode: this.props.currentArticle.mode,
status: this.props.currentArticle.status
} : null
// console.log('init staet')
// console.log(article)
return {
isEditModalOpen: false,
article: article
}
},
componentWillReceiveProps: function (nextProps) {
if (nextProps.detailMode === 'edit') {
var article = {
id: nextProps.currentArticle.id,
title: nextProps.currentArticle.title,
content: nextProps.currentArticle.CurrentRevision.content,
tags: nextProps.currentArticle.Tags.map(function (tag) {
return tag.name
}),
mode: nextProps.currentArticle.mode,
FolderId: nextProps.currentArticle.FolderId,
status: nextProps.currentArticle.status
}
this.setState({article: article})
}
},
openDeleteModal: function () {
if (this.props.article == null) return
},
handleFolderIdChange: function (FolderId) {
this.state.article.FolderId = FolderId
this.setState({article: this.state.article})
},
handleTagsChange: function (tag, tags) {
tags = _.uniq(tags, function (tag) {
return tag.value
})
this.state.article.tags = tags.map(function (tag) {
return tag.value
})
this.setState({article: this.state.article})
},
handleModeChange: function (mode) {
this.state.article.mode = mode
this.setState({article: this.state.article})
},
handleContentChange: function (e, value) {
var article = this.state.article
article.content = value
this.setState({article: article})
},
saveArticle: function () {
if (this.state.article.mode === '') {
return this.refs.mode.focus()
}
if (this.state.article.FolderId === '') {
return this.refs.folder.focus()
}
this.props.saveCurrentArticle(this.state.article)
},
render: function () {
if (this.props.currentArticle == null) {
return (
<div className='ArticleDetail'>
Nothing selected
</div>
)
}
if (this.props.detailMode === 'show') {
return this.renderViewer()
}
if (this.state.article == null) {
return (
<div className='ArticleDetail'>
Nothing selected
</div>
)
}
return this.renderEditor()
},
renderEditor: function () {
var article = this.state.article
var folderOptions = this.props.user.Folders.map(function (folder) {
return {
label: folder.name,
value: folder.id
}
})
return (
<div className='ArticleDetail edit'>
<div className='detailInfo'>
<div className='left'>
<Select ref='folder' onChange={this.handleFolderIdChange} clearable={false} options={folderOptions} placeholder='select folder...' value={article.FolderId} className='folder'/>
<Select onChange={this.handleTagsChange} clearable={false} multi={true} placeholder='add some tags...' allowCreate={true} value={article.tags} className='tags'/>
</div>
<div className='right'>
<button onClick={this.props.switchDetailMode('show')}>Cancel</button>
<button onClick={this.saveArticle} className='primary'>Save</button>
</div>
</div>
<div className='detailBody'>
<div className='detailPanel'>
<div className='header'>
<div className='title'>
<input ref='title' valueLink={this.linkState('article.title')}/>
</div>
<Select ref='mode' onChange={this.handleModeChange} clearable={false} options={modeOptions}placeholder='select mode...' value={article.mode} className='mode'/>
</div>
<CodeEditor onChange={this.handleContentChange} mode={article.mode} code={article.content}/>
</div>
</div>
</div>
)
},
renderViewer: function () {
var article = this.props.currentArticle
var tags = article.Tags.length > 0 ? article.Tags.map(function (tag) {
return (
<a key={tag.id}>{tag.name}</a>
)
}) : (
<span className='noTags'>Not tagged yet</span>
)
var folder = _.findWhere(this.props.user.Folders, {id: article.FolderId})
var folderName = folder != null ? folder.name : null
return (
<div className='ArticleDetail show'>
<div className='detailInfo'>
<div className='left'>
<div className='info'>
<i className='fa fa-fw fa-square'/> {folderName}&nbsp;
by {article.User.profileName}&nbsp;
Created {moment(article.createdAt).format('YYYY/MM/DD')}&nbsp;
Updated {moment(article.updatedAt).format('YYYY/MM/DD')}
</div>
<div className='tags'><i className='fa fa-fw fa-tags'/>{tags}</div>
</div>
<div className='right'>
<button onClick={this.props.switchDetailMode('edit')}><i className='fa fa-fw fa-edit'/></button>
<button><i className='fa fa-fw fa-trash'/></button>
<button><i className='fa fa-fw fa-share-alt'/></button>
</div>
</div>
<div className='detailBody'>
<div className='detailPanel'>
<div className='header'>
<ModeIcon className='mode' mode={article.mode}/>
<div className='title'>{article.title}</div>
</div>
{article.mode === 'markdown' ? <MarkdownPreview content={article.CurrentRevision.content}/> : <CodeEditor readOnly={true} onChange={this.handleContentChange} mode={article.mode} code={article.CurrentRevision.content}/>}
</div>
</div>
</div>
)
}
})

View File

@@ -1,63 +0,0 @@
var React = require('react')
var ReactRouter = require('react-router')
var moment = require('moment')
var _ = require('lodash')
var ForceUpdate = require('../Mixins/ForceUpdate')
var Markdown = require('../Mixins/Markdown')
var ProfileImage = require('../Components/ProfileImage')
var ModeIcon = require('../Components/ModeIcon')
module.exports = React.createClass({
mixins: [ReactRouter.Navigation, ReactRouter.State, ForceUpdate(60000), Markdown],
propTypes: {
articles: React.PropTypes.array
},
handleArticleClick: function (article) {
return function () {
this.props.selectArticle(article.id)
}.bind(this)
},
render: function () {
var articles = this.props.articles.map(function (article) {
if (article == null) return null
var tags = _.isArray(article.Tags) && article.Tags.length > 0 ? article.Tags.map(function (tag) {
return (
<a key={tag.id}>#{tag.name}</a>
)
}.bind(this)) : (
<span>Not tagged yet</span>
)
var params = this.getParams()
var isActive = this.props.currentArticle.id === article.id
return (
<li key={'article-' + article.id}>
<div onClick={this.handleArticleClick(article)} className={'articleItem' + (isActive ? ' active' : '')}>
<div className='top'>
<i className='fa fa-fw fa-square'/>
by <ProfileImage className='profileImage' size='20' email={article.User.email}/> {article.User.profileName}
<span className='updatedAt'>{article.status != null ? article.status : moment(article.updatedAt).fromNow()}</span>
</div>
<div className='middle'>
<ModeIcon className='mode' mode={article.mode}/> <div className='title'>{article.status !== 'new' ? article.title : '(New article)'}</div>
</div>
<div className='bottom'>
<div className='tags'><i className='fa fa-fw fa-tags'/>{tags}</div>
</div>
</div>
<div className='divider'></div>
</li>
)
}.bind(this))
return (
<div className='ArticleList'>
<ul ref='articles'>
{articles}
</ul>
</div>
)
}
})

View File

@@ -1,55 +0,0 @@
var React = require('react')
var Hq = require('../Services/Hq')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
module.exports = React.createClass({
mixins: [KeyCaster('codeDeleteModal')],
propTypes: {
planet: React.PropTypes.object,
code: React.PropTypes.object,
close: React.PropTypes.func
},
onKeyCast: function (e) {
switch (e.status) {
case 'submitCodeDeleteModal':
this.submit()
break
case 'closeModal':
this.props.close()
break
}
},
submit: function () {
var planet = this.props.planet
Hq.destroyCode(planet.Owner.name, 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 () {
return (
<div className='CodeDeleteModal modal'>
<div className='modal-header'>
<h1>Delete Code</h1>
</div>
<div className='modal-body'>
<p>Are you sure to delete it?</p>
</div>
<div className='modal-footer'>
<div className='modal-control'>
<button onClick={this.props.close} className='btn-default'>Cancel</button>
<button ref='submit' onClick={this.submit} className='btn-primary'>Delete</button>
</div>
</div>
</div>
)
}
})

View File

@@ -1,26 +0,0 @@
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
},
componentDidMount: function () {
// TODO: Hacked!! should fix later
setTimeout(function () {
React.findDOMNode(this.refs.form.refs.description).focus()
}.bind(this), 1)
},
render: function () {
return (
<div className='CodeEditModal modal'>
<div className='modal-header'>
<h1>Edit Code</h1>
</div>
<CodeForm ref='form' code={this.props.code} planet={this.props.planet} close={this.props.close}/>
</div>
)
}
})

View File

@@ -1,162 +0,0 @@
var React = require('react')
var CodeEditor = require('./CodeEditor')
var Select = require('react-select')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
var aceModes = require('../../../modules/ace-modes')
var getOptions = function (input, callback) {
Hq.searchTag(input)
.then(function (res) {
callback(null, {
options: res.body.map(function (tag) {
return {
label: tag.name,
value: tag.name
}
}),
complete: false
})
})
.catch(function (err) {
console.log(err)
})
}
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('codeForm')],
propTypes: {
planet: React.PropTypes.object,
close: React.PropTypes.func,
transitionTo: React.PropTypes.func,
code: React.PropTypes.object
},
getInitialState: function () {
var code = Object.assign({
description: '',
mode: '',
content: '',
Tags: []
}, this.props.code)
code.Tags = code.Tags.map(function (tag) {
return {
label: tag.name,
value: tag.name
}
})
return {
code: code
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'submitCodeForm':
this.submit()
break
case 'closeModal':
this.props.close()
break
}
},
handleModeChange: function (selected) {
var code = this.state.code
code.mode = selected
this.setState({code: code})
},
handleTagsChange: function (selected, all) {
var code = this.state.code
code.Tags = all
this.setState({code: code})
},
handleContentChange: function (e, value) {
var code = this.state.code
code.content = value
this.setState({code: code})
},
submit: function () {
var planet = this.props.planet
var code = this.state.code
code.Tags = code.Tags.map(function (tag) {
return tag.value
})
if (this.props.code == null) {
Hq.createCode(planet.Owner.name, planet.name, this.state.code)
.then(function (res) {
var code = res.body
PlanetStore.Actions.updateCode(code)
this.props.close()
this.props.transitionTo('codes', {userName: planet.Owner.name, planetName: planet.name, localId: code.localId})
}.bind(this))
.catch(function (err) {
console.error(err)
})
} else {
Hq.updateCode(planet.Owner.name, planet.name, this.props.code.localId, this.state.code)
.then(function (res) {
var code = res.body
PlanetStore.Actions.updateCode(code)
this.props.close()
}.bind(this))
}
},
handleKeyDown: function (e) {
if (e.keyCode === 13 && e.metaKey) {
this.submit()
e.stopPropagation()
}
},
render: function () {
var modeOptions = aceModes.map(function (mode) {
return {
label: mode,
value: mode
}
})
return (
<div className='CodeForm'>
<div className='modal-body'>
<div className='form-group'>
<textarea ref='description' className='codeDescription block-input' valueLink={this.linkState('code.description')} placeholder='Description'/>
</div>
<div className='form-group'>
<Select
name='mode'
className='modeSelect'
value={this.state.code.mode}
placeholder='Select Language'
options={modeOptions}
onChange={this.handleModeChange}/>
</div>
<div className='form-group'>
<CodeEditor onChange={this.handleContentChange} code={this.state.code.content} mode={this.state.code.mode}/>
</div>
<div className='form-group'>
<Select
name='Tags'
multi={true}
allowCreate={true}
value={this.state.code.Tags}
placeholder='Tags...'
asyncOptions={getOptions}
onChange={this.handleTagsChange}
/>
</div>
</div>
<div className='modal-footer'>
<div className='modal-control'>
<button onClick={this.props.close} className='btn-default'>Cancel</button>
<button onClick={this.submit} className='btn-primary'>{this.props.code == null ? 'Launch' : 'Relaunch'}</button>
</div>
</div>
</div>
)
}
})

View File

@@ -1,53 +0,0 @@
var React = require('react')
var ace = window.ace
module.exports = React.createClass({
propTypes: {
code: React.PropTypes.string,
mode: React.PropTypes.string,
className: React.PropTypes.string
},
componentDidMount: function () {
var el = React.findDOMNode(this.refs.target)
var editor = ace.edit(el)
editor.$blockScrolling = Infinity
editor.setValue(this.props.code)
editor.renderer.setShowGutter(false)
editor.setReadOnly(true)
editor.setTheme('ace/theme/xcode')
editor.setHighlightActiveLine(false)
editor.clearSelection()
var session = editor.getSession()
if (this.props.mode != null && this.props.mode.length > 0) {
session.setMode('ace/mode/' + this.props.mode)
} else {
session.setMode('ace/mode/text')
}
session.setUseSoftTabs(true)
session.setOption('useWorker', false)
session.setUseWrapMode(true)
this.setState({editor: editor})
},
componentDidUpdate: function (prevProps) {
if (this.state.editor.getValue() !== this.props.code) {
this.state.editor.setValue(this.props.code)
this.state.editor.clearSelection()
}
if (prevProps.mode !== this.props.mode) {
var session = this.state.editor.getSession()
if (this.props.mode != null && this.props.mode.length > 0) {
session.setMode('ace/mode/' + this.props.mode)
} else {
session.setMode('ace/mode/text')
}
}
},
render: function () {
return (
<div ref='target' className={this.props.className}></div>
)
}
})

View File

@@ -1,168 +0,0 @@
var React = require('react')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var KeyCaster = require('../Mixins/KeyCaster')
var UserStore = require('../Stores/UserStore')
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('editProfileModal')],
propTypes: {
user: React.PropTypes.shape({
name: React.PropTypes.string,
profileName: React.PropTypes.string,
email: React.PropTypes.string
}),
close: React.PropTypes.func
},
getInitialState: function () {
var user = this.props.user
return {
currentTab: 'userInfo',
user: {
profileName: user.profileName,
email: user.email
},
userSubmitStatus: null,
password: {
currentPassword: '',
newPassword: '',
passwordConfirmation: ''
},
passwordSubmitStatus: null
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
}
},
selectTab: function (tabName) {
return function () {
this.setState({currentTab: tabName})
}.bind(this)
},
saveUserInfo: function () {
this.setState({
userSubmitStatus: 'sending'
}, function () {
Hq.updateUser(this.props.user.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 () {
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 sideNavModal modal'>
<div className='leftPane'>
<div className='modalLabel'>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 tab'>
<div className='formField'>
<label>Profile Name</label>
<input valueLink={this.linkState('user.profileName')}/>
</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='passwordTab tab'>
<div className='formField'>
<label>Current password</label>
<input type='password' valueLink={this.linkState('password.currentPassword')}/>
</div>
<div className='formField'>
<label>New password</label>
<input type='password' valueLink={this.linkState('password.newPassword')}/>
</div>
<div className='formField'>
<label>Confirmation</label>
<input type='password' 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>
)
}
})

View File

@@ -1,109 +0,0 @@
var React = require('react')
var ReactRouter = require('react-router')
var Navigation = ReactRouter.Navigation
var State = ReactRouter.State
var Link = ReactRouter.Link
var Reflux = require('reflux')
var _ = require('lodash')
var Modal = require('../Mixins/Modal')
var UserStore = require('../Stores/UserStore')
var PreferencesModal = require('./PreferencesModal')
var PlanetCreateModal = require('./PlanetCreateModal')
var TeamCreateModal = require('./TeamCreateModal')
var LogoutModal = require('./LogoutModal')
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':
var user = res.data
var currentUser = this.state.currentUser
if (currentUser.id === user.id) {
this.setState({currentUser: user})
return
}
if (user.userType === 'team') {
var isMyTeam = user.Members.some(function (member) {
if (currentUser.id === member.id) {
return true
}
return false
})
if (isMyTeam) {
var isNew = !currentUser.Teams.some(function (team, index) {
if (user.id === team.id) {
currentUser.Teams.splice(index, 1, user)
return true
}
return false
})
if (isNew) {
currentUser.Teams.push(user)
}
this.setState({currentUser: currentUser})
}
}
break
}
},
openTeamCreateModal: function () {
this.openModal(TeamCreateModal, {user: this.state.currentUser, transitionTo: this.transitionTo})
},
handleLogoutClick: function () {
this.openModal(LogoutModal, {transitionTo: this.transitionTo})
},
switchUserByIndex: function (index) {
var userProp = this.refs.users.props.children[index - 1].props
this.transitionTo('user', {userId: userProp.id})
},
render: function () {
var params = this.getParams()
if (this.state.currentUser == null) {
return null
}
console.log(this.state.currentUser.Teams)
var users = [this.state.currentUser]
if (_.isArray(this.state.currentUser.Teams)) users = users.concat(this.state.currentUser.Teams)
var userButtons = users.map(function (user, index) {
return (
<li key={'user-' + user.id}>
<Link to='user' params={{userId: user.id}}>
{user.userType === 'person' ? (<ProfileImage email={user.email} size='44'/>): user.name[0]}
<div className='userTooltip'>{user.name}</div>
</Link>
{index < 9 ? (<div className='shortCut'>{index + 1}</div>) : null}
</li>
)
})
return (
<div className='HomeNavigator'>
<ul ref='users' className='userList'>
{userButtons}
</ul>
<button onClick={this.openTeamCreateModal} className='newTeamButton'>
<i className='fa fa-plus'/>
<div className='tooltip'>Create new team</div>
</button>
</div>
)
}
})

View File

@@ -1,79 +0,0 @@
var React = require('react')
var CodeForm = require('./CodeForm')
var NoteForm = require('./NoteForm')
module.exports = React.createClass({
propTypes: {
planet: React.PropTypes.object,
transitionTo: React.PropTypes.func,
close: React.PropTypes.func
},
getInitialState: function () {
return {
currentTab: 'code'
}
},
componentDidMount: function () {
var codeButton = React.findDOMNode(this.refs.codeButton)
codeButton.addEventListener('keydown', this.handleKeyDown)
React.findDOMNode(this.refs.noteButton).addEventListener('keydown', this.handleKeyDown)
codeButton.focus()
},
componentWillUnmount: function () {
React.findDOMNode(this.refs.codeButton).removeEventListener('keydown', this.handleKeyDown)
React.findDOMNode(this.refs.noteButton).removeEventListener('keydown', this.handleKeyDown)
},
handleKeyDown: function (e) {
if (e.keyCode === 37 && e.metaKey) {
this.selectCodeTab()
e.stopPropagation()
return
}
if (e.keyCode === 39 && e.metaKey) {
this.selectNoteTab()
e.stopPropagation()
return
}
if (e.keyCode === 9) {
if (this.state.currentTab === 'code') React.findDOMNode(this.refs.form.refs.description).focus()
else React.findDOMNode(this.refs.form.refs.title).focus()
e.preventDefault()
}
},
selectCodeTab: function () {
this.setState({currentTab: 'code'}, function () {
React.findDOMNode(this.refs.codeButton).focus()
})
},
selectNoteTab: function () {
this.setState({currentTab: 'note'}, function () {
React.findDOMNode(this.refs.noteButton).focus()
})
},
render: function () {
var modalBody
if (this.state.currentTab === 'code') {
modalBody = (
<CodeForm ref='form' planet={this.props.planet} transitionTo={this.props.transitionTo} close={this.props.close}/>
)
} else {
modalBody = (
<NoteForm ref='form' planet={this.props.planet} transitionTo={this.props.transitionTo} close={this.props.close}/>
)
}
return (
<div className='LaunchModal modal'>
<div className='modal-header'>
<div className='modal-tab'>
<button ref='codeButton' className={this.state.currentTab === 'code' ? 'btn-primary active' : 'btn-default'} onClick={this.selectCodeTab}>Code</button>
<button ref='noteButton' className={this.state.currentTab === 'note' ? 'btn-primary active' : 'btn-default'} onClick={this.selectNoteTab}>Note</button>
</div>
</div>
{modalBody}
</div>
)
}
})

View File

@@ -1,42 +0,0 @@
var React = require('react')
var socket = require('../Services/socket')
var KeyCaster = require('../Mixins/KeyCaster')
module.exports = React.createClass({
mixins: [KeyCaster('logoutModal')],
propTypes: {
transitionTo: React.PropTypes.func,
close: React.PropTypes.func
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
case 'submitLogoutModal':
this.logout()
break
}
},
logout: function () {
localStorage.removeItem('currentUser')
localStorage.removeItem('token')
socket.reconnect()
this.props.transitionTo('login')
this.props.close()
},
render: function () {
return (
<div className='LogoutModal modal'>
<div className='messageLabel'>Are you sure to log out?</div>
<div className='formControl'>
<button onClick={this.props.close}>Cancel</button>
<button className='logoutButton' onClick={this.logout}>Log out</button>
</div>
</div>
)
}
})

View File

@@ -1,55 +0,0 @@
var React = require('react')
var Hq = require('../Services/Hq')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
module.exports = React.createClass({
mixins: [KeyCaster('noteDeleteModal')],
propTypes: {
planet: React.PropTypes.object,
note: React.PropTypes.object,
close: React.PropTypes.func
},
onKeyCast: function (e) {
switch (e.status) {
case 'submitNoteDeleteModal':
this.submit()
break
case 'closeModal':
this.props.close()
break
}
},
submit: function () {
var planet = this.props.planet
Hq.destroyNote(planet.Owner.name, 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 () {
return (
<div className='NoteDeleteModal modal'>
<div className='modal-header'>
<h1>Delete Note</h1>
</div>
<div className='modal-body'>
<p>Are you sure to delete it?</p>
</div>
<div className='modal-footer'>
<div className='modal-control'>
<button onClick={this.props.close} className='btn-default'>Cancel</button>
<button ref='submit' onClick={this.submit} className='btn-primary'>Delete</button>
</div>
</div>
</div>
)
}
})

View File

@@ -1,27 +0,0 @@
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
},
componentDidMount: function () {
// TODO: Hacked!! should fix later
setTimeout(function () {
React.findDOMNode(this.refs.form.refs.title).focus()
}.bind(this), 1)
},
render: function () {
return (
<div className='NoteEditModal modal'>
<div className='modal-header'>
<h1>Edit Note</h1>
</div>
<NoteForm ref='form' note={this.props.note} planet={this.props.planet} close={this.props.close}/>
</div>
)
}
})

View File

@@ -1,153 +0,0 @@
var React = require('react')
var Select = require('react-select')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var Markdown = require('../Mixins/Markdown')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
var CodeEditor = require('./CodeEditor')
var MarkdownPreview = require('./MarkdownPreview')
var getOptions = function (input, callback) {
Hq.searchTag(input)
.then(function (res) {
callback(null, {
options: res.body.map(function (tag) {
return {
label: tag.name,
value: tag.name
}
}),
complete: false
})
})
.catch(function (err) {
console.log(err)
})
}
var EDIT_MODE = 0
var PREVIEW_MODE = 1
module.exports = React.createClass({
mixins: [LinkedState, Markdown, KeyCaster('noteForm')],
propTypes: {
planet: React.PropTypes.object,
close: React.PropTypes.func,
transitionTo: React.PropTypes.func,
note: React.PropTypes.object
},
getInitialState: function () {
var note = Object.assign({
title: '',
content: '',
Tags: []
}, this.props.note)
note.Tags = note.Tags.map(function (tag) {
return {
label: tag.name,
value: tag.name
}
})
return {
note: note,
mode: EDIT_MODE
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'submitNoteForm':
this.submit()
break
case 'closeModal':
this.props.close()
break
}
},
handleTagsChange: function (selected, all) {
var note = this.state.note
note.Tags = all
this.setState({note: note})
},
handleContentChange: function (e, value) {
var note = this.state.note
note.content = value
this.setState({note: note})
},
togglePreview: function () {
this.setState({mode: this.state.mode === EDIT_MODE ? PREVIEW_MODE : EDIT_MODE})
},
submit: function () {
var planet = this.props.planet
var note = this.state.note
note.Tags = note.Tags.map(function (tag) {
return tag.value
})
if (this.props.note == null) {
Hq.createNote(planet.Owner.name, 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.Owner.name, planetName: planet.name, localId: note.localId})
}.bind(this))
.catch(function (err) {
console.error(err)
})
} else {
Hq.updateNote(planet.Owner.name, planet.name, this.props.note.localId, this.state.note)
.then(function (res) {
var note = res.body
PlanetStore.Actions.updateNote(note)
this.props.close()
}.bind(this))
}
},
render: function () {
var content = this.state.mode === EDIT_MODE ? (
<div className='form-group'>
<CodeEditor onChange={this.handleContentChange} code={this.state.note.content} mode={'markdown'}/>
</div>
) : (
<div className='form-group relative'>
<div className='previewMode'>Preview mode</div>
<MarkdownPreview className='marked' content={this.state.note.content}/>
</div>
)
return (
<div className='NoteForm'>
<div className='modal-body'>
<div className='form-group'>
<input ref='title' className='block-input' valueLink={this.linkState('note.title')} placeholder='Title'/>
</div>
{content}
<div className='form-group'>
<Select
name='Tags'
multi={true}
allowCreate={true}
value={this.state.note.Tags}
placeholder='Tags...'
asyncOptions={getOptions}
onChange={this.handleTagsChange}
/>
</div>
</div>
<div className='modal-footer'>
<button onClick={this.togglePreview} className={'btn-default' + (this.state.mode === PREVIEW_MODE ? ' active' : '')}>Preview mode</button>
<div className='modal-control'>
<button onClick={this.props.close} className='btn-default'>Cancel</button>
<button onClick={this.submit} className='btn-primary'>Launch</button>
</div>
</div>
</div>
)
}
})

View File

@@ -1,111 +0,0 @@
/* global localStorage */
var React = require('react')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('planetCreateModal')],
propTypes: {
ownerName: React.PropTypes.string,
transitionTo: React.PropTypes.func,
close: React.PropTypes.func
},
getInitialState: function () {
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
var ownerName = this.props.ownerName != null ? this.props.ownerName : currentUser.name
return {
user: currentUser,
planet: {
name: '',
public: true
},
ownerName: ownerName,
error: null
}
},
componentDidMount: function () {
React.findDOMNode(this.refs.name).focus()
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
case 'submitPlanetCreateModal':
this.handleSubmit()
break
}
},
handleSubmit: function () {
this.setState({error: null}, function () {
Hq.createPlanet(this.state.ownerName, this.state.planet)
.then(function (res) {
var planet = res.body
PlanetStore.Actions.update(planet)
if (this.props.transitionTo != null) {
this.props.transitionTo('planetHome', {userName: planet.Owner.name, planetName: planet.name})
}
this.props.close()
}.bind(this))
.catch(function (err) {
console.error(err)
if (err.status == null) return this.setState({error: {message: 'Check your network connection'}})
switch (err.status) {
case 403:
this.setState({error: err.response.body})
break
case 422:
this.setState({error: {message: 'Planet name should be Alphanumeric with _, -'}})
break
case 409:
this.setState({error: {message: 'The entered name already in use'}})
break
default:
this.setState({error: {message: 'Unexpected error occured! please try again'}})
}
}.bind(this))
})
},
render: function () {
var teamOptions = this.state.user.Teams.map(function (team) {
return (
<option key={'user-' + team.id} value={team.name}>{team.profileName} ({team.name})</option>
)
})
return (
<div className='PlanetCreateModal modal'>
<input ref='name' valueLink={this.linkState('planet.name')} className='nameInput stripInput' placeholder='Crate new Planet'/>
<div className='formField'>
of
<select valueLink={this.linkState('ownerName')}>
<option value={this.state.user.name}>Me({this.state.user.name})</option>
{teamOptions}
</select>
as
<select valueLink={this.linkState('planet.public')}>
<option value={true}>Public</option>
<option value={false}>Private</option>
</select>
</div>
{this.state.error != null ? (<p className='errorAlert'>{this.state.error.message != null ? this.state.error.message : 'Error message undefined'}</p>) : null}
<button onClick={this.handleSubmit} className='submitButton'>
<i className='fa fa-check'/>
</button>
</div>
)
}
})

View File

@@ -1,86 +0,0 @@
var React = require('react')
var ReactRouter = require('react-router')
var Link = ReactRouter.Link
var Modal = require('../Mixins/Modal')
var ExternalLink = require('../Mixins/ExternalLink')
var PlanetSettingModal = require('./PlanetSettingModal')
module.exports = React.createClass({
mixins: [ReactRouter.State, Modal, ExternalLink],
propTypes: {
search: React.PropTypes.string,
fetchPlanet: React.PropTypes.func,
onSearchChange: React.PropTypes.func,
currentPlanet: React.PropTypes.object
},
getInitialState: function () {
return {
search: ''
}
},
componentDidMount: function () {
var search = React.findDOMNode(this.refs.search)
search.addEventListener('keydown', this.handleSearchKeyDown)
},
componentWillUnmount: function () {
var search = React.findDOMNode(this.refs.search)
search.removeEventListener('keydown', this.handleSearchKeyDown)
},
handleSearchKeyDown: function (e) {
if (e.keyCode === 38 || e.keyCode === 40) {
var search = React.findDOMNode(this.refs.search)
search.blur()
e.preventDefault()
}
if (e.keyCode !== 27 && (e.keyCode !== 13 || !e.metaKey)) {
e.stopPropagation()
}
},
openPlanetSettingModal: function () {
this.openModal(PlanetSettingModal, {planet: this.props.currentPlanet})
},
refresh: function () {
this.props.fetchPlanet()
},
render: function () {
var currentPlanetName = this.props.currentPlanet.name
var currentUserName = this.props.currentPlanet.Owner.name
return (
<div className='PlanetHeader'>
<div className='headerLabel'>
<Link to='userHome' params={{userName: currentUserName}} className='userName'>{currentUserName}</Link>
<span className='planetName'>{currentPlanetName}</span>
{this.props.currentPlanet.public ? null : (
<div className='private'>
<i className='fa fa-lock'/>
<div className='tooltip'>Private planet</div>
</div>
)}
<button onClick={this.openPlanetSettingModal} className='planetSettingButton'>
<i className='fa fa-chevron-down'></i>
<div className='tooltip'>Planet setting</div>
</button>
</div>
<div className='headerControl'>
<div className='searchInput'>
<i className='fa fa-search'/>
<input onChange={this.props.onSearchChange} value={this.props.search} ref='search' type='text' className='inline-input circleInput' placeholder='Search...'/>
</div>
<button onClick={this.refresh} className='refreshButton'>
<i className='fa fa-refresh'/>
<div className='tooltip'>Refresh planet</div>
</button>
<a onClick={this.openExternal} href='http://b00st.io' className='logo'>
<img width='44' height='44' src='resources/favicon-230x230.png'/>
<div className='tooltip'>Boost official page</div>
</a>
</div>
</div>
)
}
})

View File

@@ -1,76 +0,0 @@
var React = require('react')
var ReactRouter = require('react-router')
var Navigation = ReactRouter.Navigation
var Modal = require('../Mixins/Modal')
var LaunchModal = require('../Components/LaunchModal')
module.exports = React.createClass({
mixins: [Modal, Navigation],
propTypes: {
planet: React.PropTypes.shape({
name: React.PropTypes.string,
Owner: React.PropTypes.shape({
id: React.PropTypes.number,
userType: React.PropTypes.string
})
}),
search: React.PropTypes.string,
toggleCodeFilter: React.PropTypes.func,
toggleNoteFilter: React.PropTypes.func,
currentUser: React.PropTypes.shape({
id: React.PropTypes.number,
userType: React.PropTypes.string,
Teams: React.PropTypes.array
})
},
getInitialState: function () {
return {
isLaunchModalOpen: false
}
},
openLaunchModal: function () {
this.openModal(LaunchModal, {planet: this.props.planet, transitionTo: this.transitionTo})
},
isMyPlanet: function () {
if (this.props.currentUser == null) return false
if (this.props.planet.Owner.userType === 'person' && this.props.planet.Owner.id !== this.props.currentUser.id) return false
if (this.props.planet.Owner.userType === 'team' && !this.props.currentUser.Teams.some(function (team) {
if (team.id === this.props.planet.Owner.id) return true
return false
}.bind(this))) return false
return true
},
render: function () {
var keywords = this.props.search.split(' ')
var usingCodeFilter = keywords.some(function (keyword) {
if (keyword === '$c') return true
return false
})
var usingNoteFilter = keywords.some(function (keyword) {
if (keyword === '$n') return true
return false
})
return (
<div className='PlanetNavigator'>
{this.isMyPlanet() ? (
<button onClick={this.openLaunchModal} className='launchButton btn-primary btn-block'>
<i className='fa fa-rocket fa-fw'/> Launch
</button>
) : null}
<nav className='articleFilters'>
<a className={usingCodeFilter && !usingNoteFilter ? 'active' : ''} onClick={this.props.toggleCodeFilter}>
<i className='fa fa-code fa-fw'/> Codes
</a>
<a className={!usingCodeFilter && usingNoteFilter ? 'active' : ''} onClick={this.props.toggleNoteFilter}>
<i className='fa fa-file-text-o fa-fw'/> Notes
</a>
</nav>
</div>
)
}
})

View File

@@ -1,190 +0,0 @@
var React = require('react')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var KeyCaster = require('../Mixins/KeyCaster')
var PlanetStore = require('../Stores/PlanetStore')
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('planetSettingModal')],
propTypes: {
close: React.PropTypes.func,
planet: React.PropTypes.shape({
name: React.PropTypes.string,
public: React.PropTypes.bool,
Owner: React.PropTypes.shape({
name: React.PropTypes.string
})
})
},
getInitialState: function () {
var deleteTextCandidates = [
'Confirm',
'Exterminatus',
'Avada Kedavra'
]
var random = Math.round(Math.random() * 10) % 10
var randomDeleteText = random > 1 ? deleteTextCandidates[0] : random === 1 ? deleteTextCandidates[1] : deleteTextCandidates[2]
return {
currentTab: 'profile',
planet: {
name: this.props.planet.name,
public: this.props.planet.public
},
randomDeleteText: randomDeleteText,
deleteConfirmation: ''
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
}
},
activePlanetProfile: function () {
this.setState({currentTab: 'profile'})
},
activePlanetDelete: function () {
this.setState({currentTab: 'delete'})
},
handlePublicChange: function (value) {
return function () {
this.state.planet.public = value
this.setState({planet: this.state.planet})
}.bind(this)
},
handleSavePlanetProfile: function (e) {
var planet = this.props.planet
this.setState({profileFormStatus: 'sending', profileFormError: null}, function () {
Hq.updatePlanet(planet.Owner.name, planet.name, this.state.planet)
.then(function (res) {
var planet = res.body
console.log(planet)
this.setState({profileFormStatus: 'done'})
PlanetStore.Actions.update(planet)
this.props.close()
}.bind(this))
.catch(function (err) {
console.error(err)
var newState = {
profileFormStatus: 'error'
}
if (err.status == null) {
newState.profileFormError = {message: 'Check your network connection'}
return this.setState(newState)
}
switch (err.status) {
case 403:
newState.profileFormError = err.response.body
this.setState(newState)
break
case 422:
newState.profileFormError = {message: 'Planet name should be Alphanumeric with _, -'}
this.setState(newState)
break
case 409:
newState.profileFormError = {message: 'The entered name already in use'}
this.setState(newState)
break
default:
newState.profileFormError = {message: 'Undefined error please try again'}
this.setState(newState)
}
}.bind(this))
})
},
handleDeletePlanetClick: function () {
var planet = this.props.planet
this.setState({deleteSubmitStatus: 'sending'}, function () {
Hq.destroyPlanet(planet.Owner.name, planet.name)
.then(function (res) {
var planet = res.body
PlanetStore.Actions.destroy(planet)
this.setState({deleteSubmitStatus: 'done'}, function () {
this.props.close()
})
}.bind(this))
.catch(function (err) {
this.setState({deleteSubmitStatus: 'error'})
console.error(err)
}.bind(this))
})
},
render: function () {
var content
content = this.state.currentTab === 'profile' ? this.renderPlanetProfileTab() : this.renderPlanetDeleteTab()
return (
<div className='PlanetSettingModal sideNavModal modal'>
<div className='leftPane'>
<h1 className='modalLabel'>Planet setting</h1>
<nav className='tabList'>
<button onClick={this.activePlanetProfile} className={this.state.currentTab === 'profile' ? 'active' : ''}><i className='fa fa-globe fa-fw'/> Planet profile</button>
<button onClick={this.activePlanetDelete} className={this.state.currentTab === 'delete' ? 'active' : ''}><i className='fa fa-trash fa-fw'/> Delete Planet</button>
</nav>
</div>
<div className='rightPane'>
{content}
</div>
</div>
)
},
renderPlanetProfileTab: function () {
return (
<div className='planetProfileTab tab'>
<div className='formField'>
<label>Planet name </label>
<input valueLink={this.linkState('planet.name')}/>
</div>
<div className='formRadioField'>
<input id='publicOption' checked={this.state.planet.public} onChange={this.handlePublicChange(true)} name='public' type='radio'/> <label htmlFor='publicOption'>Public</label>
<input id='privateOption' checked={!this.state.planet.public} onChange={this.handlePublicChange(false)} name='public' type='radio'/> <label htmlFor='privateOption'>Private</label>
</div>
<div className='formConfirm'>
<button onClick={this.handleSavePlanetProfile} className='saveButton btn-primary'>Save</button>
<div className={'alertInfo' + (this.state.profileFormStatus === 'sending' ? '' : ' hide')}>on Sending...</div>
<div className={'alertError' + (this.state.profileFormStatus === 'error' ? '' : ' hide')}>{this.state.profileFormError != null ? this.state.profileFormError.message : 'Unexpected error occured! please try again'}</div>
<div className={'alertSuccess' + (this.state.profileFormStatus === 'done' ? '' : ' hide')}>Successfully done!!</div>
</div>
</div>
)
},
renderPlanetDeleteTab: function () {
var disabled = !this.state.deleteConfirmation.match(new RegExp('^' + this.props.planet.Owner.name + '/' + this.props.planet.name + '$'))
return (
<div className='planetDeleteTab tab'>
<p>Are you sure to destroy <strong>'{this.props.planet.Owner.name + '/' + this.props.planet.name}'</strong>?</p>
<p>If you are sure, write <strong>'{this.props.planet.Owner.name + '/' + this.props.planet.name}'</strong> to input below and click <strong>'{this.state.randomDeleteText}'</strong> button.</p>
<input valueLink={this.linkState('deleteConfirmation')} placeholder='userName/planetName'/>
<div className='formConfirm'>
<button disabled={disabled} onClick={this.handleDeletePlanetClick}>{this.state.randomDeleteText}</button>
<div className={'alertInfo' + (this.state.deleteSubmitStatus === 'sending' ? '' : ' hide')}>on Sending...</div>
<div className={'alertError' + (this.state.deleteSubmitStatus === 'error' ? '' : ' hide')}>Connection failed.. Try again.</div>
<div className={'alertSuccess' + (this.state.deleteSubmitStatus === 'done' ? '' : ' hide')}>Successfully done!!</div>
</div>
</div>
)
}
})

View File

@@ -1,112 +0,0 @@
var ipc = require('ipc')
var remote = require('remote')
var React = require('react')
var LinkedState = require('../Mixins/LinkedState')
var ExternalLink = require('../Mixins/ExternalLink')
var KeyCaster = require('../Mixins/KeyCaster')
module.exports = React.createClass({
mixins: [LinkedState, ExternalLink, KeyCaster('aboutModal')],
propTypes: {
close: React.PropTypes.func
},
getInitialState: function () {
var keymap = remote.getGlobal('keymap')
console.log(keymap)
return {
currentTab: 'settings',
keymap: keymap
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
}
},
activeSettings: function () {
this.setState({currentTab: 'settings'})
},
activeAbout: function () {
this.setState({currentTab: 'about'})
},
saveKeymap: function () {
ipc.send('hotkeyUpdated', JSON.stringify(this.state.keymap))
},
render: function () {
var content = this.state.currentTab === 'settings' ? this.renderSettingsTab() : this.renderAboutTab()
return (
<div className='PreferencesModal sideNavModal modal'>
<div className='leftPane'>
<h1 className='modalLabel'>Preferences</h1>
<nav className='tabList'>
<button onClick={this.activeSettings} className={this.state.currentTab === 'settings' ? 'active' : ''}><i className='fa fa-gear fa-fw'/> Settings</button>
<button onClick={this.activeAbout} className={this.state.currentTab === 'about' ? 'active' : ''}><i className='fa fa-info-circle fa-fw'/> About this app</button>
</nav>
</div>
<div className='rightPane'>
{content}
</div>
</div>
)
},
renderSettingsTab: function () {
return (
<div className='settingsTab tab'>
<div className='categoryLabel'>Hotkey</div>
<div className='formField'>
<label>Toggle finder</label>
<input valueLink={this.linkState('keymap.toggleFinder')}/>
</div>
<div className='formConfirm'>
<button onClick={this.saveKeymap}>Save</button>
</div>
<div className='example'>
<h3>Example</h3>
<ul>
<li><code>0</code> to <code>9</code></li>
<li><code>A</code> to <code>Z</code></li>
<li><code>F1</code> to <code>F24</code></li>
<li>Punctuations like <code>~</code>, <code>!</code>, <code>@</code>, <code>#</code>, <code>$</code>, etc.</li>
<li><code>Plus</code></li>
<li><code>Space</code></li>
<li><code>Backspace</code></li>
<li><code>Delete</code></li>
<li><code>Insert</code></li>
<li><code>Return</code> (or <code>Enter</code> as alias)</li>
<li><code>Up</code>, <code>Down</code>, <code>Left</code> and <code>Right</code></li>
<li><code>Home</code> and <code>End</code></li>
<li><code>PageUp</code> and <code>PageDown</code></li>
<li><code>Escape</code> (or <code>Esc</code> for short)</li>
<li><code>VolumeUp</code>, <code>VolumeDown</code> and <code>VolumeMute</code></li>
<li><code>MediaNextTrack</code>, <code>MediaPreviousTrack</code>, <code>MediaStop</code> and <code>MediaPlayPause</code></li>
</ul>
</div>
</div>
)
},
renderAboutTab: function () {
var version = global.version
return (
<div className='aboutTab tab'>
<div className='about1'>
<img className='logo' src='resources/favicon-230x230.png'/>
<div className='appInfo'>Boost {version == null || version.length === 0 ? 'DEV version' : 'v' + version}</div>
</div>
<div className='about2'>
<div className='externalLabel'>External links</div>
<ul className='externalList'>
<li><a onClick={this.openExternal} href='http://b00st.io'>Boost Homepage <i className='fa fa-external-link'/></a></li>
<li><a onClick={this.openExternal} href='http://boostio.github.io/regulations.html'>Regulation <i className='fa fa-external-link'/></a></li>
<li><a onClick={this.openExternal} href='http://boostio.github.io/privacypolicies.html'>Private policy <i className='fa fa-external-link'/></a></li>
</ul>
</div>
</div>
)
}
})

View File

@@ -1,89 +0,0 @@
/* global localStorage */
var React = require('react')
var Hq = require('../Services/Hq')
var socket = require('../Services/socket')
var LinkedState = require('../Mixins/LinkedState')
var KeyCaster = require('../Mixins/KeyCaster')
var UserStore = require('../Stores/UserStore')
module.exports = React.createClass({
mixins: [LinkedState, KeyCaster('teamCreateModal')],
propTypes: {
user: React.PropTypes.shape({
name: React.PropTypes.string
}),
transitionTo: React.PropTypes.func,
close: React.PropTypes.func
},
getInitialState: function () {
return {
team: {
name: ''
},
error: null
}
},
componentDidMount: function () {
React.findDOMNode(this.refs.teamName).focus()
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
case 'submitTeamCreateModal':
this.handleSubmit()
break
}
},
handleSubmit: function () {
this.setState({error: null}, function () {
Hq.createTeam(this.props.user.name, this.state.team)
.then(function (res) {
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
var team = res.body
currentUser.Teams.push(team)
localStorage.setItem('currentUser', JSON.stringify(currentUser))
socket.reconnect(currentUser)
UserStore.Actions.update(currentUser)
if (this.props.transitionTo != null) {
this.props.transitionTo('userHome', {userName: team.name})
}
this.props.close()
}.bind(this))
.catch(function (err) {
console.error(err)
if (err.status == null) return this.setState({error: {message: 'Check your network connection'}})
switch (err.status) {
case 422:
this.setState({error: {message: 'Team name should be Alphanumeric with _, -'}})
break
case 409:
this.setState({error: {message: 'The entered name already in use'}})
break
default:
this.setState({error: {message: 'Error message undefined'}})
}
}.bind(this))
})
},
render: function () {
return (
<div className='TeamCreateModal modal'>
<input ref='teamName' valueLink={this.linkState('team.name')} className='nameInput stripInput' placeholder='Create new team'/>
{this.state.error != null ? (<p className='errorAlert'>{this.state.error.message != null ? this.state.error.message : 'Unintended error occured'}</p>) : null}
<button onClick={this.handleSubmit} className='submitButton'>
<i className='fa fa-check'/>
</button>
</div>
)
}
})

View File

@@ -1,269 +0,0 @@
/* global localStorage */
var React = require('react')
var Reflux = require('reflux')
var Select = require('react-select')
var Hq = require('../Services/Hq')
var LinkedState = require('../Mixins/LinkedState')
var Helper = require('../Mixins/Helper')
var KeyCaster = require('../Mixins/KeyCaster')
var UserStore = require('../Stores/UserStore')
var getOptions = function (input, callback) {
Hq.searchUser(input)
.then(function (res) {
callback(null, {
options: res.body.map(function (user) {
return {
label: user.name,
value: user.name
}
}),
complete: false
})
})
.catch(function (err) {
console.error(err)
})
}
module.exports = React.createClass({
mixins: [LinkedState, Reflux.listenTo(UserStore, 'onUserChange'), Helper, KeyCaster('teamSettingsModal')],
propTypes: {
team: React.PropTypes.shape({
id: React.PropTypes.number,
name: React.PropTypes.string,
profileName: React.PropTypes.string,
email: React.PropTypes.string,
Members: React.PropTypes.array
}),
close: React.PropTypes.func
},
getInitialState: function () {
return {
currentTab: 'teamInfo',
team: this.props.team,
userSubmitStatus: null,
member: {
name: '',
role: 'member'
},
updatingMember: false
}
},
onKeyCast: function (e) {
switch (e.status) {
case 'closeModal':
this.props.close()
break
}
},
onUserChange: function (res) {
switch (res.status) {
case 'userUpdated':
var user = res.data
if (user.id === this.props.team.id) {
this.forceUpdate()
}
break
}
},
selectTab: function (tabName) {
return function () {
this.setState({currentTab: tabName})
}.bind(this)
},
saveUserInfo: function () {
this.setState({
userSubmitStatus: 'sending'
}, function () {
Hq.updateUser(this.props.team.name, this.state.team)
.then(function (res) {
this.setState({userSubmitStatus: 'done'}, function () {
UserStore.Actions.update(res.body)
this.forceUpdate()
})
}.bind(this))
.catch(function (err) {
console.error(err)
this.setState({userSubmitStatus: 'error'})
}.bind(this))
})
},
handleMemberNameChange: function (value) {
var member = this.state.member
member.name = value
this.setState({member: member})
},
addMember: function () {
this.setState({updatingMember: true}, function () {
Hq
.addMember(this.props.team.name, {
userName: this.state.member.name,
role: this.state.member.role
})
.then(function (res) {
this.setState({updatingMember: false, team: res.body})
}.bind(this))
.catch(function (err) {
console.error(err)
this.setState({updatingMember: false})
}.bind(this))
})
},
roleChange: function (memberName) {
return function (e) {
var role = e.target.value
this.setState({updatingMember: true}, function () {
Hq
.addMember(this.props.team.name, {
userName: memberName,
role: role
})
.then(function (res) {
this.setState({updatingMember: false, team: res.body})
}.bind(this))
.catch(function (err) {
console.error(err)
this.setState({updatingMember: false})
}.bind(this))
})
}.bind(this)
},
removeMember: function (memberName) {
return function () {
this.setState({updatingMember: true}, function () {
Hq
.removeMember(this.props.team.name, {
userName: memberName
})
.then(function (res) {
this.setState({updatingMember: false, team: res.body})
}.bind(this))
.catch(function (err) {
console.error(err)
this.setState({updatingMember: false})
}.bind(this))
})
}.bind(this)
},
render: function () {
var content
switch (this.state.currentTab) {
case 'teamInfo':
content = this.renderTeamInfoTab()
break
case 'members':
content = this.renderMembersTab()
break
}
return (
<div className='TeamSettingsModal sideNavModal modal'>
<div className='leftPane'>
<div className='modalLabel'>Team settings</div>
<div className='tabList'>
<button className={this.state.currentTab === 'teamInfo' ? 'active' : ''} onClick={this.selectTab('teamInfo')}><i className='fa fa-info-circle fa-fw'/> Team Info</button>
<button className={this.state.currentTab === 'members' ? 'active' : ''} onClick={this.selectTab('members')}><i className='fa fa-users fa-fw'/> Members</button>
</div>
</div>
<div className='rightPane'>
{content}
</div>
</div>
)
},
renderTeamInfoTab: function () {
return (
<div className='userInfoTab tab'>
<div className='formField'>
<label>Profile Name</label>
<input valueLink={this.linkState('team.profileName')}/>
</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>
)
},
renderMembersTab: function () {
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
var members = this.state.team.Members.map(function (member) {
var isCurrentUser = currentUser.id === member.id
return (
<tr>
<td>{member.profileName}({member.name})</td>
<td>
{isCurrentUser ? (
'Owner'
) : (
<select disabled={this.state.updatingMember} onChange={this.roleChange(member.name)} className='roleSelect' value={member.TeamMember.role}>
<option value='owner'>Owner</option>
<option value='member'>Member</option>
</select>
)}
</td>
<td>
{isCurrentUser ? '-' : (
<button disabled={this.state.updatingMember} onClick={this.removeMember(member.name)}><i className='fa fa-close fa-fw'/></button>
)}
</td>
</tr>
)
}.bind(this))
var belowLimit = members.length < 5
return (
<div className='membersTab tab'>
<table className='memberTable'>
<thead>
<tr>
<th>Username</th>
<th>Role</th>
<th>Control</th>
</tr>
</thead>
<tbody>
{members}
</tbody>
</table>
{belowLimit ? (
<div className='addMemberForm'>
<div className='formLabel'>Add Member</div>
<div className='formGroup'>
<Select
name='userName'
value={this.state.member.name}
placeholder='Username to add'
asyncOptions={getOptions}
onChange={this.handleMemberNameChange}
className='userNameSelect'
/>
<select valueLink={this.linkState('member.role')} className='roleSelect'>
<option value={'member'}>Member</option>
<option value={'owner'}>Owner</option>
</select>
<button disabled={this.state.updatingMember} onClick={this.addMember} className='confirmButton'>Add Member</button>
</div>
</div>
) : (
<div>
Maximum number of members is 5 on Beta version. Please contact us if you want futher use.
</div>
)}
</div>
)
}
})

View File

@@ -1,30 +0,0 @@
var React = require('react')
var ExternalLink = require('../Mixins/ExternalLink')
module.exports = React.createClass({
mixins: [ExternalLink],
propTypes: {
search: React.PropTypes.string,
changeSearch: React.PropTypes.func
},
render: function () {
return (
<div className='TopBar'>
<div className='left'>
<div className='search'>
<i className='fa fa-search'/>
<input value={this.props.search} onChange={this.props.changeSearch} className='searchInput' placeholder='Search...'/>
</div>
</div>
<div className='right'>
<a onClick={this.openExternal} href='http://b00st.io' className='logo'>
<img width='44' height='44' src='resources/favicon-230x230.png'/>
<div className='tooltip'>Boost official page</div>
</a>
</div>
</div>
)
}
})

View File

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

View File

@@ -1,11 +1,11 @@
import React, { PropTypes} from 'react' import React, { PropTypes} from 'react'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { switchUser } from './actions' import { switchUser } from './actions'
import UserNavigator from './Components/UserNavigator' import UserNavigator from './HomePage/UserNavigator'
import ArticleNavigator from './Components/ArticleNavigator' import ArticleNavigator from './HomePage/ArticleNavigator'
import ArticleTopBar from './Components/ArticleTopBar' import ArticleTopBar from './HomePage/ArticleTopBar'
import ArticleList from './Components/ArticleList' import ArticleList from './HomePage/ArticleList'
import ArticleDetail from './Components/ArticleDetail' import ArticleDetail from './HomePage/ArticleDetail'
import { findWhere } from 'lodash' import { findWhere } from 'lodash'
// var AuthFilter = require('../Mixins/AuthFilter') // var AuthFilter = require('../Mixins/AuthFilter')

View File

@@ -1,9 +1,9 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import moment from 'moment' import moment from 'moment'
import { findWhere } from 'lodash' import { findWhere } from 'lodash'
import ModeIcon from '../../Components/ModeIcon' import ModeIcon from 'boost/components/ModeIcon'
import MarkdownPreview from '../../Components/MarkdownPreview' import MarkdownPreview from 'boost/components/MarkdownPreview'
import CodeEditor from '../../Components/CodeEditor' import CodeEditor from 'boost/components/CodeEditor'
export default class ArticleDetail extends React.Component { export default class ArticleDetail extends React.Component {
render () { render () {

View File

@@ -1,6 +1,6 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ProfileImage from '../../components/ProfileImage' import ProfileImage from 'boost/components/ProfileImage'
import ModeIcon from '../../Components/ModeIcon' import ModeIcon from 'boost/components/ModeIcon'
import moment from 'moment' import moment from 'moment'
import { IDLE_MODE, CREATE_MODE, EDIT_MODE } from '../actions' import { IDLE_MODE, CREATE_MODE, EDIT_MODE } from '../actions'

View File

@@ -1,5 +1,5 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ProfileImage from '../../components/ProfileImage' import ProfileImage from 'boost/components/ProfileImage'
import { findWhere } from 'lodash' import { findWhere } from 'lodash'
export default class ArticleNavigator extends React.Component { export default class ArticleNavigator extends React.Component {

View File

@@ -1,5 +1,5 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ExternalLink from '../../components/ExternalLink' import ExternalLink from 'boost/components/ExternalLink'
const ArticleTopBar = React.createClass({ const ArticleTopBar = React.createClass({
render () { render () {

View File

@@ -1,8 +1,8 @@
import React, { Component, PropTypes } from 'react' import React, { Component, PropTypes } from 'react'
import { Link } from 'react-router' import { Link } from 'react-router'
import ProfileImage from '../../components/ProfileImage' import ProfileImage from 'boost/components/ProfileImage'
import { openModal } from '../lib/modal' import { openModal } from 'boost/modal'
import CreateNewTeam from '../lib/modal/CreateNewTeam' import CreateNewTeam from 'boost/components/modal/CreateNewTeam'
export default class UserNavigator extends Component { export default class UserNavigator extends Component {
handleClick (e) { handleClick (e) {

View File

@@ -1,9 +1,7 @@
var Hq = require('../Services/Hq')
var socket = require('../Services/socket')
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import { Link } from 'react-router' import { Link } from 'react-router'
import linkState from '../helpers/linkState' import linkState from 'boost/linkState'
import { login } from 'boost/api'
export default class LoginPage extends React.Component { export default class LoginPage extends React.Component {
constructor (props) { constructor (props) {
@@ -23,15 +21,14 @@ export default class LoginPage extends React.Component {
isSending: true, isSending: true,
error: null error: null
}, function () { }, function () {
console.log(this.state.user) login(this.state.user)
Hq.login(this.state.user)
.then(function (res) { .then(function (res) {
localStorage.setItem('token', res.body.token) localStorage.setItem('token', res.body.token)
localStorage.setItem('currentUser', JSON.stringify(res.body.user)) localStorage.setItem('currentUser', JSON.stringify(res.body.user))
try { try {
this.props.history.pushState('home') this.props.history.pushState('home')
} catch(e) { } catch (e) {
console.error(e) console.error(e)
} }
}.bind(this)) }.bind(this))

View File

@@ -1,10 +1,9 @@
var ipc = require('ipc') import ipc from 'ipc'
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
var ContactModal = require('../Components/ContactModal') var ContactModal = require('boost/components/modal/ContactModal')
export default class MainContainer extends React.Component { export default class MainContainer extends React.Component {
// mixins: [Modal],
constructor (props) { constructor (props) {
super(props) super(props)
this.state = {updateAvailable: false} this.state = {updateAvailable: false}

View File

@@ -1,67 +0,0 @@
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
}

View File

@@ -1,27 +0,0 @@
/* global localStorage*/
var mixin = {}
mixin.OnlyGuest = {
componentDidMount: function () {
var currentUser = JSON.parse(localStorage.getItem('currentUser'))
if (currentUser == null) {
return
}
this.transitionTo('homeDefault')
}
}
mixin.OnlyUser = {
componentDidMount: function () {
var currentUser = localStorage.getItem('currentUser')
if (currentUser == null) {
this.transitionTo('login')
return
}
}
}
module.exports = mixin

View File

@@ -1,8 +0,0 @@
var shell = require('shell')
module.exports = {
openExternal: function (e) {
shell.openExternal(e.currentTarget.href)
e.preventDefault()
}
}

View File

@@ -1,14 +0,0 @@
var ForceUpdate = function (interval) {
return {
componentDidMount: function () {
this.refreshTimer = setInterval(function () {
this.forceUpdate()
}.bind(this), interval)
},
componentWillUnmount: function () {
clearInterval(this.refreshTimer)
}
}
}
module.exports = ForceUpdate

View File

@@ -1,33 +0,0 @@
function deleteItemFromTargetArray (item, targetArray) {
if (targetArray == null) targetArray = []
targetArray.some(function (_item, index) {
if (_item.id === item.id) {
targetArray.splice(index, 1)
return true
}
return false
})
return targetArray
}
function updateItemToTargetArray (item, targetArray) {
if (targetArray == null) targetArray = []
var isNew = !targetArray.some(function (_item, index) {
if (_item.id === item.id) {
targetArray.splice(index, 1, item)
return true
}
return false
})
if (isNew) targetArray.push(item)
return targetArray
}
module.exports = {
deleteItemFromTargetArray: deleteItemFromTargetArray,
updateItemToTargetArray: updateItemToTargetArray
}

View File

@@ -1,100 +0,0 @@
var Reflux = require('reflux')
var state = {
}
var keyDown = Reflux.createAction()
var KeyStore = Reflux.createStore({
init: function () {
this.listenTo(keyDown, this.onKeyDown)
document.addEventListener('keydown', function (e) {
keyDown(e)
})
},
setState: function (newState, cb) {
for (var key in newState) {
state[key] = newState[key]
}
if (typeof cb === 'function') cb()
},
onKeyDown: function (e) {
/*
Modals
*/
if (state.codeForm || state.noteForm || state.noteDeleteModal || state.codeDeleteModal || state.addMemberModal || state.aboutModal || state.editProfileModal || state.contactModal || state.teamCreateModal || state.planetCreateModal || state.planetSettingModal || state.teamSettingsModal || state.logoutModal) {
// ESC
if (e.keyCode === 27) this.cast('closeModal')
// Cmd + Enter
if (e.keyCode === 13 && e.metaKey) {
if (state.codeForm) this.cast('submitCodeForm')
if (state.noteForm) this.cast('submitNoteForm')
if (state.codeDeleteModal) this.cast('submitCodeDeleteModal')
if (state.noteDeleteModal) this.cast('submitNoteDeleteModal')
if (state.addMemberModal) this.cast('submitAddMemberModal')
if (state.contactModal) this.cast('submitContactModal')
if (state.teamCreateModal) this.cast('submitTeamCreateModal')
if (state.planetCreateModal) this.cast('submitPlanetCreateModal')
if (state.logoutModal) this.cast('submitLogoutModal')
}
return
}
/*
PlanetContainer
*/
if (state.planetContainer) {
// Cmd + Enter, A
if ((e.keyCode === 13 && e.metaKey) || e.keyCode === 65) this.cast('openLaunchModal')
// Esc
if (e.keyCode === 27) this.cast('toggleFocusSearchInput')
// Up
if (e.keyCode === 38) this.cast('selectPriorArticle')
// Down
if (e.keyCode === 40) this.cast('selectNextArticle')
// E
if (e.keyCode === 69) this.cast('openEditModal')
// D
if (e.keyCode === 68) this.cast('openDeleteModal')
}
/*
HomeContainer
*/
if (state.homeContainer) {
if (e.keyCode > 48 && e.keyCode < 58 && e.metaKey) {
this.cast('switchPlanet', e.keyCode - 48)
}
}
},
cast: function (status, data) {
this.trigger({
status: status,
data: data
})
}
})
module.exports = function (stateKey) {
return {
mixins: [Reflux.listenTo(KeyStore, 'onKeyCast')],
componentDidMount: function () {
var newState = {}
newState[stateKey] = true
KeyStore.setState(newState)
},
componentWillUnmount: function () {
var newState = {}
newState[stateKey] = false
KeyStore.setState(newState)
}
}
}

View File

@@ -1,14 +0,0 @@
var markdownit = require('markdown-it')
var md = markdownit({
typographer: true,
linkify: true
})
var Markdown = {
markdown: function (content) {
if (content == null) content = ''
return md.render(content)
}
}
module.exports = Markdown

View File

@@ -1,42 +0,0 @@
import React from 'react'
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})
}
}

View File

@@ -1,29 +0,0 @@
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))
}
export default function linkState (path) {
return {
value: getIn(this.state, path),
requestChange: setPartialState.bind(null, this, path)
}
}

View File

@@ -1,82 +0,0 @@
var request = require('superagent-promise')(require('superagent'), Promise)
var apiUrl = require('../../../config').apiUrl
module.exports = {
// Auth
login: function (input) {
return request
.post(apiUrl + 'auth/login')
.send(input)
},
signup: function (input) {
return request
.post(apiUrl + 'auth/register')
.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)
},
fetchArticles: function (userId) {
return request
.get(apiUrl + 'teams/' + userId +'/articles')
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
},
fetchArticlesByFolderId: function (folderId) {
return request
.get(apiUrl + 'folders/' + folderId +'/articles')
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
},
createArticle: function (input) {
return request
.post(apiUrl + 'folders/' + input.FolderId + '/articles')
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
.send(input)
},
updateArticle: function (articleId, input) {
return request
.put(apiUrl + 'articles/' + articleId)
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
.send(input)
},
// Search
searchTag: function (tagName) {
return request
.get(apiUrl + 'search/tags')
.query({name: tagName})
},
searchUser: function (userName) {
return request
.get(apiUrl + 'search/users')
.query({name: userName})
},
// Mail
sendEmail: function (input) {
return request
.post(apiUrl + 'mail')
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
.send(input)
}
}

View File

@@ -1,17 +0,0 @@
/* global localStorage */
var config = require('../../../config')
var io = require('socket.io-client')(config.apiUrl)
io.on('connected', function (data) {
console.log('connected by WS')
})
io.on('userUpdated', function (data) {
console.log('userUpdated')
})
module.exports = {
io: io
}

View File

@@ -1,9 +1,8 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import { Link } from 'react-router' import { Link } from 'react-router'
import linkState from '../helpers/linkState' import linkState from 'boost/linkState'
import openExternal from '../helpers/openExternal' import openExternal from 'boost/openExternal'
import { signup } from 'boost/api'
var Hq = require('../Services/Hq')
export default class SignupContainer extends React.Component { export default class SignupContainer extends React.Component {
constructor (props) { constructor (props) {
@@ -26,7 +25,7 @@ export default class SignupContainer extends React.Component {
isSending: true, isSending: true,
error: null error: null
}, function () { }, function () {
Hq.signup(this.state.user) signup(this.state.user)
.then(res => { .then(res => {
localStorage.setItem('token', res.body.token) localStorage.setItem('token', res.body.token)
localStorage.setItem('currentUser', JSON.stringify(res.body.user)) localStorage.setItem('currentUser', JSON.stringify(res.body.user))

View File

@@ -1,14 +1,14 @@
import React from 'react' import React from 'react'
import { createStore } from 'redux' import { createStore } from 'redux'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import { updateUser, updateArticles } from './HomeContainer/actions' import { updateUser, updateArticles } from './actions'
import reducer from './HomeContainer/reducer' import reducer from './reducer'
import { fetchCurrentUser, fetchArticles } from './HomeContainer/lib/api' import { fetchCurrentUser, fetchArticles } from 'boost/api'
import { Router, Route, IndexRoute } from 'react-router' import { Router, Route, IndexRoute } from 'react-router'
import MainContainer from './Containers/MainContainer' import MainPage from './MainPage'
import LoginContainer from './Containers/LoginContainer' import LoginPage from './LoginPage'
import SignupContainer from './Containers/SignupContainer' import SignupPage from './SignupPage'
import HomeContainer from './HomeContainer' import HomePage from './HomePage'
require('../styles/main/index.styl') require('../styles/main/index.styl')
function onlyUser (state, replaceState) { function onlyUser (state, replaceState) {
@@ -18,11 +18,11 @@ function onlyUser (state, replaceState) {
} }
let routes = ( let routes = (
<Route path='/' component={MainContainer}> <Route path='/' component={MainPage}>
<Route name='login' path='login' component={LoginContainer}/> <Route name='login' path='login' component={LoginPage}/>
<Route name='signup' path='signup' component={SignupContainer}/> <Route name='signup' path='signup' component={SignupPage}/>
<IndexRoute name='home' component={HomeContainer} onEnter={onlyUser}/> <IndexRoute name='home' component={HomePage} onEnter={onlyUser}/>
<Route name='user' path='/users/:userId' component={HomeContainer} onEnter={onlyUser}/> <Route name='user' path='/users/:userId' component={HomePage} onEnter={onlyUser}/>
</Route> </Route>
) )

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,17 @@
var request = require('superagent-promise')(require('superagent'), Promise) var request = require('superagent-promise')(require('superagent'), Promise)
var apiUrl = require('../../../../config').apiUrl var apiUrl = require('../config').apiUrl
export function login (input) {
return request
.post(apiUrl + 'auth/login')
.send(input)
}
export function signup (input) {
return request
.post(apiUrl + 'auth/register')
.send(input)
}
export function fetchCurrentUser () { export function fetchCurrentUser () {
return request return request
@@ -49,3 +61,12 @@ export function deleteMember (teamId, input) {
}) })
.send(input) .send(input)
} }
export function sendEmail (input) {
return request
.post(apiUrl + 'mail')
.set({
Authorization: 'Bearer ' + localStorage.getItem('token')
})
.send(input)
}

View File

@@ -1,4 +1,4 @@
var React = require('react') import React from 'react'
var ace = window.ace var ace = window.ace

View File

@@ -1,6 +1,6 @@
import shell from 'shell' import shell from 'shell'
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import markdown from '../HomeContainer/lib/markdown' import markdown from 'boost/markdown'
function handleAnchorClick (e) { function handleAnchorClick (e) {
shell.openExternal(e.target.href) shell.openExternal(e.target.href)

View File

@@ -1,6 +1,6 @@
import React, { PropTypes, findDOMNode } from 'react' import React, { PropTypes, findDOMNode } from 'react'
import linkState from '../helpers/linkState' import linkState from 'boost/linkState'
var Hq = require('../Services/Hq') import { sendEmail } from 'boost/api'
export default class ContactModal extends React.Component { export default class ContactModal extends React.Component {
constructor (props) { constructor (props) {
@@ -37,7 +37,7 @@ export default class ContactModal extends React.Component {
} }
sendEmail () { sendEmail () {
Hq.sendEmail(this.state.mail) sendEmail(this.state.mail)
.then(function (res) { .then(function (res) {
this.setState({isSent: !this.state.isSent}) this.setState({isSent: !this.state.isSent})
}.bind(this)) }.bind(this))

View File

@@ -1,7 +1,7 @@
import React, { PropTypes } from 'react' import React, { PropTypes } from 'react'
import ProfileImage from '../../../components/ProfileImage' import ProfileImage from 'boost/components/ProfileImage'
import { searchUser, createTeam, setMember, deleteMember } from '../api' import { searchUser, createTeam, setMember, deleteMember } from 'boost/api'
import linkState from '../../../helpers/linkState' import linkState from 'boost/linkState'
import Select from 'react-select' import Select from 'react-select'
function getUsers (input, cb) { function getUsers (input, cb) {

View File

@@ -21,7 +21,7 @@ var update = null
var version = app.getVersion() var version = app.getVersion()
var versionText = (version == null || version.length === 0) ? 'DEV version' : 'v' + version var versionText = (version == null || version.length === 0) ? 'DEV version' : 'v' + version
var nn = require('node-notifier') var nn = require('node-notifier')
var updater = require('./updater') var updater = require('./atom-lib/updater')
var path = require('path') var path = require('path')
var appQuit = false var appQuit = false
@@ -48,7 +48,7 @@ app.on('ready', function () {
updater.setFeedUrl('http://orbital.b00st.io/rokt33r/boost/latest?version=' + version) updater.setFeedUrl('http://orbital.b00st.io/rokt33r/boost/latest?version=' + version)
updater.checkForUpdates() updater.checkForUpdates()
// menu start // menu start
var template = require('./modules/menu-template') var template = require('./atom-lib/menu-template')
ipc.on('update-app', function (event, msg) { ipc.on('update-app', function (event, msg) {
if (update != null) { if (update != null) {
@@ -78,7 +78,7 @@ app.on('ready', function () {
})) }))
appIcon.setContextMenu(trayMenu) appIcon.setContextMenu(trayMenu)
mainWindow = require('./main-window') mainWindow = require('./atom-lib/main-window')
mainWindow.on('close', function (e) { mainWindow.on('close', function (e) {
if (appQuit) return true if (appQuit) return true
e.preventDefault() e.preventDefault()
@@ -95,7 +95,7 @@ app.on('ready', function () {
mainWindow.show() mainWindow.show()
}) })
finderWindow = require('./finder-window') finderWindow = require('./atom-lib/finder-window')
var globalShortcut = require('global-shortcut') var globalShortcut = require('global-shortcut')
console.log('jetpack launch') console.log('jetpack launch')

1
node_modules/boost generated vendored Symbolic link
View File

@@ -0,0 +1 @@
../lib

View File

@@ -10,7 +10,7 @@
}, },
"config": { "config": {
"version": "--version=0.33.0 --app-version=$npm_package_version --app-bundle-id=com.maisin.boost", "version": "--version=0.33.0 --app-version=$npm_package_version --app-bundle-id=com.maisin.boost",
"platform": "--platform=darwin --arch=x64 --prune --icon=app.icns", "platform": "--platform=darwin --arch=x64 --prune --icon=resources/app.icns",
"ignore": "--ignore=Boost-darwin-x64 --ignore=node_modules/devicon/icons --ignore=submodules/ace/(?!src-min)|submodules/ace/(?=src-min-noconflict)" "ignore": "--ignore=Boost-darwin-x64 --ignore=node_modules/devicon/icons --ignore=submodules/ace/(?!src-min)|submodules/ace/(?=src-min-noconflict)"
}, },
"repository": { "repository": {
@@ -73,7 +73,6 @@
}, },
"standard": { "standard": {
"ignore": [ "ignore": [
"/browser/ace/"
], ],
"globals": [ "globals": [
"localStorage" "localStorage"