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

add ModalBase, LaunchModal & install Reflux

This commit is contained in:
Rokt33r
2015-07-09 01:48:49 +09:00
parent 27701bbe1b
commit 472d79cbf2
18 changed files with 415 additions and 24 deletions

View File

@@ -3,6 +3,7 @@
"dependencies": {
"react": "~0.13.3",
"fontawesome": "~4.3.0",
"react-router": "~0.13.3"
"react-router": "~0.13.3",
"reflux": "~0.2.8"
}
}

View File

@@ -0,0 +1,48 @@
var React = require('react/addons')
var ace = require('ace')
var CodeEditor = React.createClass({
propTypes: {
code: React.PropTypes.string,
mode: React.PropTypes.string,
onChange: React.PropTypes.func
},
componentDidMount: function () {
var el = React.findDOMNode(this.refs.target)
var editor = ace.edit(el)
editor.setValue(this.props.code)
editor.$blockScrolling = Infinity
editor.renderer.setShowGutter(true)
editor.setTheme('ace/theme/xcode')
var session = editor.getSession()
session.setMode('ace/mode/' + this.props.mode)
session.setUseSoftTabs(true)
session.setOption('useWorker', false)
session.on('change', function (e) {
if (this.props.onChange != null) {
var value = editor.getValue()
this.props.onChange(e, value)
}
}.bind(this))
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) {
this.state.editor.getSession().setMode('ace/mode/' + this.props.mode)
}
},
render: function () {
return (
<div ref='target'></div>
)
}
})
module.exports = CodeEditor

View File

@@ -13,16 +13,24 @@ var CodeViewer = React.createClass({
editor.$blockScrolling = Infinity
editor.renderer.setShowGutter(false)
editor.setReadOnly(true)
editor.setTheme('ace/theme/xcode')
editor.setHighlightActiveLine(false)
var session = editor.getSession()
session.setMode('ace/mode/' + this.props.mode)
session.setUseSoftTabs(true)
session.setOption('useWorker', false)
this.setState({editor: editor})
},
componentDidUpdate: function () {
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) {
this.state.editor.getSession().setMode('ace/mode/' + this.props.mode)
}
},
render: function () {
return (

View File

@@ -0,0 +1,148 @@
var React = require('react/addons')
var CodeEditor = require('./CodeEditor')
var Catalyst = require('../Mixins/Catalyst')
var Select = require('react-select')
// TODO: remove
var options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
]
var LaunchModal = React.createClass({
mixins: [Catalyst.LinkedStateMixin],
propTypes: {
submit: React.PropTypes.func,
close: React.PropTypes.func
},
getInitialState: function () {
return {
snippet: {
description: '',
mode: 'javascript',
content: '',
callSign: '',
tags: []
},
blueprint: {
title: '',
content: '',
tags: []
},
currentTab: 'snippet'
}
},
handleClick: function (e) {
e.stopPropagation()
},
selectSnippetTab: function () {
this.setState({currentTab: 'snippet'})
},
selectBlueprintTab: function () {
this.setState({currentTab: 'blueprint'})
},
handleSnippetTagsChange: function (selected, all) {
var snippet = this.state.snippet
snippet.tags = all
this.setState({snippet: snippet})
},
handleSnippetContentChange: function (e, value) {
var snippet = this.state.snippet
snippet.content = value
this.setState({snippet: snippet})
},
handleBlueprintTagsChange: function (selected, all) {
var blueprint = this.state.blueprint
blueprint.tags = all
this.setState({blueprint: blueprint})
},
handleBlueprintContentChange: function (e, value) {
var blueprint = this.state.blueprint
blueprint.content = value
this.setState({blueprint: blueprint})
},
submit: function () {
// this.props.submit('yolo')
if (this.state.currentTab === 'snippet') {
console.log(this.state.snippet)
} else {
console.log(this.state.blueprint)
}
},
render: function () {
var form
if (this.state.currentTab === 'snippet') {
form = (
<div>
<div className='form-group'>
<textarea className='block-input' valueLink={this.linkState('snippet.description')} placeholder='Description'/>
</div>
<div className='form-group'>
<input className='inline-input' valueLink={this.linkState('snippet.callSign')} type='text' placeholder='Callsign'/>
<select className='inline-input' valueLink={this.linkState('snippet.mode')}>
<option value='javascript'>Javascript</option>
<option value='html'>HTML</option>
<option value='css'>CSS</option>
</select>
</div>
<div className='form-group'>
<CodeEditor onChange={this.handleSnippetContentChange} code={this.state.snippet.content} mode={this.state.snippet.mode}/>
</div>
<div className='form-group'>
<Select
name='tags'
multi={true}
allowCreate={true}
value={this.state.snippet.tags}
placeholder='Tags...'
options={options}
onChange={this.handleSnippetTagsChange}
/>
</div>
</div>
)
} else {
form = (
<div>
<div className='form-group'>
<input className='block-input' valueLink={this.linkState('blueprint.title')} placeholder='Title'/>
</div>
<div className='form-group'>
<CodeEditor onChange={this.handleBlueprintContentChange} code={this.state.blueprint.content} mode={'markdown'}/>
</div>
<div className='form-group'>
<Select
name='tags'
multi={true}
allowCreate={true}
value={this.state.blueprint.tags}
placeholder='Tags...'
options={options}
onChange={this.handleBlueprintTagsChange}
/>
</div>
</div>
)
}
return (
<div onClick={this.handleClick} className='modal launch-modal'>
<div className='modal-body'>
<div className='modal-tab form-group'>
<button className={this.state.currentTab === 'snippet' ? 'btn-primary active' : 'btn-default'} onClick={this.selectSnippetTab}>Snippet</button> <button className={this.state.currentTab === 'blueprint' ? 'btn-primary active' : 'btn-default'} onClick={this.selectBlueprintTab}>Blueprint</button>
</div>
{form}
</div>
<div className='modal-footer'>
<div className='modal-control'>
<button onClick={this.props.close} className='btn-default'>Cancle</button>
<button onClick={this.submit} className='btn-primary'>Launch</button>
</div>
</div>
</div>
)
}
})
module.exports = LaunchModal

View File

@@ -0,0 +1,23 @@
var React = require('react/addons')
var ModalBase = React.createClass({
propTypes: {
isOpen: React.PropTypes.bool,
children: React.PropTypes.element,
close: React.PropTypes.func
},
render: function () {
if (this.props.isOpen) {
return (
<div onClick={this.props.close} className='ModalBase'>
{this.props.children}
</div>
)
}
return (
<div className='Modal hide'></div>
)
}
})
module.exports = ModalBase

View File

@@ -0,0 +1,7 @@
var React = require('react/addons')
var ModeSelect = React.createClass({
})
module.exports = ModeSelect

View File

@@ -28,11 +28,11 @@ module.exports = React.createClass({
<form onSubmit={this.handleSubmit}>
<div className='form-group'>
<label>E-mail</label>
<input valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
<input className='block-input' valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
</div>
<div className='form-group'>
<label>Password</label>
<input valueLink={this.linkState('password')} onChange={this.handleChange} type='password' placeholder='Password'/>
<input className='block-input' valueLink={this.linkState('password')} onChange={this.handleChange} type='password' placeholder='Password'/>
</div>
<div className='form-group'>
<button className='btn-primary btn-block' type='submit'><i className='fa fa-sign-in'></i> Login</button>

View File

@@ -2,6 +2,8 @@ var React = require('react/addons')
var RouteHandler = require('react-router').RouteHandler
var ReactRouter = require('react-router')
var Link = ReactRouter.Link
var ModalBase = require('../Components/ModalBase')
var LaunchModal = require('../Components/LaunchModal')
var userPlanets = [
{
@@ -62,6 +64,22 @@ var SideNavigator = React.createClass({
name: React.PropTypes.string
})
},
getInitialState: function () {
return {
isLaunchModalOpen: false
}
},
openLaunchModal: function () {
console.log('and...OPEN!!')
this.setState({isLaunchModalOpen: true})
},
closeLaunchModal: function () {
this.setState({isLaunchModalOpen: false})
},
submitLaunchModal: function (ret) {
console.log(ret)
this.setState({isLaunchModalOpen: false})
},
render: function () {
var currentPlanetName = this.props.currentPlanet.name
@@ -73,9 +91,12 @@ var SideNavigator = React.createClass({
<i className='fa fa-chevron-down'></i>
</button>
</div>
<button className='btn-primary btn-block'>
<button onClick={this.openLaunchModal} className='btn-primary btn-block'>
<i className='fa fa-rocket fa-fw'/> Launch
</button>
<ModalBase isOpen={this.state.isLaunchModalOpen} close={this.closeLaunchModal}>
<LaunchModal submit={this.submitLaunchModal} close={this.closeLaunchModal}/>
</ModalBase>
<nav>
<Link to='dashboard' params={{planetName: currentPlanetName}}>
<i className='fa fa-home fa-fw'/> Home

View File

@@ -30,20 +30,20 @@ module.exports = React.createClass({
<form onSubmit={this.handleSubmit}>
<div className='form-group'>
<label>E-mail</label>
<input valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
<input className='block-input' valueLink={this.linkState('email')} type='text' placeholder='E-mail'/>
</div>
<div className='form-group'>
<label>Password</label>
<input valueLink={this.linkState('password')} type='password' placeholder='Password'/>
<input className='block-input' valueLink={this.linkState('password')} type='password' placeholder='Password'/>
</div>
<hr></hr>
<div className='form-group'>
<label>User name</label>
<input valueLink={this.linkState('name')} type='text' placeholder='name'/>
<input className='block-input' valueLink={this.linkState('name')} type='text' placeholder='name'/>
</div>
<div className='form-group'>
<label>Profile name</label>
<input valueLink={this.linkState('profileName')} type='text' placeholder='Profile name'/>
<input className='block-input' valueLink={this.linkState('profileName')} type='text' placeholder='Profile name'/>
</div>
<div className='form-group'>
<button className='btn-primary btn-block' type='submit'><i className='fa fa-sign-in'></i> Register</button>

View File

@@ -32,7 +32,7 @@ var SnippetList = React.createClass({
return (
<div className='SnippetList'>
<div className='search form-group'><input type='text' placeholder='Search...'/></div>
<div className='search'><input className='block-input' type='text' placeholder='Search...'/></div>
<ul>
{snippets}
</ul>
@@ -106,10 +106,58 @@ var SnippetContainer = React.createClass({
selectSnippet: function (snippet) {
this.setState({currentSnippet: snippet})
},
updateSnippet: function (snippet) {
var snippets = this.state.snippets.map(function (_snippet) {
if (snippet.id === _snippet.id) {
return snippet
}
return _snippet
})
var currentSnippet = this.state.currentSnippet.id === snippet.id ? snippet : this.state.currentSnippet
this.setState({snippets: snippets, currentSnippet: currentSnippet})
},
destroySnippet: function (snippet) {
var snippets = this.state.snippets
var currentSnippet = this.state.currentSnippet
if (currentSnippet.id === snippet.id) {
var index
snippets.some(function (_snippet, _index) {
if (snippet.id === _snippet.id) {
index = _index
return true
}
return false
})
if (index == null) {
index = 0
} else if (index > snippet.length - 1) {
index--
} else {
index++
}
if (snippets.length > 0) {
currentSnippet = snippets[index]
} else {
currentSnippet = {}
}
}
snippets = snippets.filter(function (_snippet, index) {
if (snippet.id === _snippet.id) {
return false
}
return true
})
this.setState({snippets: snippets, currentSnippet: currentSnippet})
},
render: function () {
return (
<div className='SnippetContainer'>
<SnippetList selectSnippet={this.selectSnippet} snippets={this.state.snippets}/>
<SnippetList selectSnippet={this.selectSnippet} snippets={this.state.snippets} currentSnippet={this.state.currentSnippet}/>
<SnippetViewer snippet={this.state.currentSnippet}/>
</div>
)

View File

@@ -0,0 +1,38 @@
(function (root, factory) {
module.exports = factory()
}(this, function () {
function getIn (object, path) {
var stack = path.split('.')
while (stack.length > 1) {
object = object[stack.shift()]
}
return object[stack.shift()]
}
function updateIn (object, path, value) {
var current = object
var stack = path.split('.')
while (stack.length > 1) {
current = current[stack.shift()]
}
current[stack.shift()] = value
return object
}
function setPartialState (component, path, value) {
component.setState(
updateIn(component.state, path, value))
}
return {
LinkedStateMixin: {
linkState: function (path) {
return {
value: getIn(this.state, path),
requestChange: setPartialState.bind(null, this, path)
}
}
}
}
}))

View File

@@ -7,6 +7,7 @@
<script src="../vendor/react/react-with-addons.js"></script>
<script src="../vendor/react-router/build/umd/ReactRouter.js"></script>
<script src="../vendor/reflux/dist/reflux.js"></script>
<script src="../ace/src-min/ace.js"></script>
</head>

View File

@@ -1,4 +1,5 @@
require('../styles/main/index.styl')
require('react-select/dist/default.css')
var React = require('react/addons')

View File

@@ -37,16 +37,29 @@ hr
&>label
display block
margin-bottom 5px
&>input[type='text'], &>input[type='password']
display block
border solid 2px borderColor
.block-input, .inline-input
border solid 1px borderColor
padding 0 15px
font-size 1em
height 33px
border-radius 16.5px
border-radius 5px
box-sizing border-box
.block-input
display block
width 100%
.inline-input
display inline-block
margin-right 5px
textarea.block-input
resize vertical
height 125px
border-radius 5px
padding 5px
#content
fullsize()

View File

@@ -10,6 +10,7 @@
font-weight 600
transition 0.1s
cursor pointer
margin 0 5px
.btn-block
display block

View File

@@ -0,0 +1,30 @@
.ModalBase
fixed top left right bottom
z-index 1000
overflow-y auto
overflow-x auto
background-color transparentify(black, 35%)
&.hide
display none
.modal
width 500px
margin 25px auto 0
absolute top left right
background-color white
border-radius 10px
padding 15px
.modal-body
.modal-tab
text-align center
.modal-footer
clearfix()
border-top solid 1px borderColor
padding-top 15px
.modal-control
float right
.launch-modal
.ace_editor
height 300px
border-radius 5px
border solid 1px borderColor

View File

@@ -37,7 +37,9 @@
"node-notifier": "^4.2.1",
"react": "^0.13.3",
"react-router": "^0.13.3",
"react-tooltip": "^0.3.3"
"react-select": "^0.5.4",
"react-tooltip": "^0.3.3",
"reflux": "^0.2.8"
},
"devDependencies": {
"css-loader": "^0.15.1",

View File

@@ -30,7 +30,8 @@ module.exports = {
'react': 'React',
'react/addons': 'React',
'react-router': 'ReactRouter',
'ace': 'ace'
'ace': 'ace',
'reflux': 'Reflux'
},
resolve: {
extensions: ['', '.js', '.jsx']