mirror of
https://github.com/BoostIo/Boostnote
synced 2026-04-18 23:19:08 +00:00
before applying redux
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var ExternalLink = require('../Mixins/ExternalLink')
|
||||
var KeyCaster = require('../Mixins/KeyCaster')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var Select = require('react-select')
|
||||
|
||||
var LinkedState = require('../Mixins/LinkedState')
|
||||
|
||||
209
browser/main/Components/ArticleDetail.jsx
Normal file
209
browser/main/Components/ArticleDetail.jsx
Normal file
@@ -0,0 +1,209 @@
|
||||
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}
|
||||
by {article.User.profileName}
|
||||
Created {moment(article.createdAt).format('YYYY/MM/DD')}
|
||||
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>
|
||||
)
|
||||
}
|
||||
})
|
||||
63
browser/main/Components/ArticleList.jsx
Normal file
63
browser/main/Components/ArticleList.jsx
Normal file
@@ -0,0 +1,63 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var ace = window.ace
|
||||
|
||||
@@ -7,7 +7,13 @@ module.exports = React.createClass({
|
||||
code: React.PropTypes.string,
|
||||
mode: React.PropTypes.string,
|
||||
className: React.PropTypes.string,
|
||||
onChange: React.PropTypes.func
|
||||
onChange: React.PropTypes.func,
|
||||
readOnly: React.PropTypes.bool
|
||||
},
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
readOnly: false
|
||||
}
|
||||
},
|
||||
componentDidMount: function () {
|
||||
var el = React.findDOMNode(this.refs.target)
|
||||
@@ -17,6 +23,9 @@ module.exports = React.createClass({
|
||||
editor.renderer.setShowGutter(true)
|
||||
editor.setTheme('ace/theme/xcode')
|
||||
editor.clearSelection()
|
||||
if (this.props.readOnly) {
|
||||
editor.setReadOnly(true)
|
||||
}
|
||||
|
||||
var session = editor.getSession()
|
||||
if (this.props.mode != null && this.props.mode.length > 0) {
|
||||
@@ -53,7 +62,7 @@ module.exports = React.createClass({
|
||||
},
|
||||
render: function () {
|
||||
return (
|
||||
<div ref='target' className={this.props.className}></div>
|
||||
<div ref='target' className={this.props.className == null ? 'CodeEditor' : 'CodeEditor ' + this.props.className}></div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var CodeEditor = require('./CodeEditor')
|
||||
var Select = require('react-select')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var ace = window.ace
|
||||
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
var React = require('react')
|
||||
|
||||
var LinkedState = require('../Mixins/LinkedState')
|
||||
var KeyCaster = require('../Mixins/KeyCaster')
|
||||
|
||||
import React, { PropTypes, findDOMNode } from 'react'
|
||||
import linkState from '../helpers/linkState'
|
||||
var Hq = require('../Services/Hq')
|
||||
|
||||
module.exports = React.createClass({
|
||||
mixins: [LinkedState, KeyCaster('contactModal')],
|
||||
propTypes: {
|
||||
close: React.PropTypes.func
|
||||
},
|
||||
getInitialState: function () {
|
||||
return {
|
||||
export default class ContactModal extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.linkState = linkState
|
||||
|
||||
this.state = {
|
||||
isSent: false,
|
||||
mail: {
|
||||
title: '',
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
onKeyCast: function (e) {
|
||||
}
|
||||
|
||||
onKeyCast (e) {
|
||||
switch (e.status) {
|
||||
case 'closeModal':
|
||||
this.props.close()
|
||||
@@ -32,11 +30,13 @@ module.exports = React.createClass({
|
||||
this.sendEmail()
|
||||
break
|
||||
}
|
||||
},
|
||||
componentDidMount: function () {
|
||||
React.findDOMNode(this.refs.title).focus()
|
||||
},
|
||||
sendEmail: function () {
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
findDOMNode(this.refs.title).focus()
|
||||
}
|
||||
|
||||
sendEmail () {
|
||||
Hq.sendEmail(this.state.mail)
|
||||
.then(function (res) {
|
||||
this.setState({isSent: !this.state.isSent})
|
||||
@@ -44,8 +44,9 @@ module.exports = React.createClass({
|
||||
.catch(function (err) {
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
render: function () {
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className='ContactModal modal'>
|
||||
<div className='modal-header'><h1>Contact form</h1></div>
|
||||
@@ -77,4 +78,8 @@ module.exports = React.createClass({
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
ContactModal.propTypes = {
|
||||
close: PropTypes.func
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var Hq = require('../Services/Hq')
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react/addons')
|
||||
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')
|
||||
|
||||
@@ -65,30 +64,12 @@ module.exports = React.createClass({
|
||||
openTeamCreateModal: function () {
|
||||
this.openModal(TeamCreateModal, {user: this.state.currentUser, transitionTo: this.transitionTo})
|
||||
},
|
||||
openPreferencesModal: function () {
|
||||
this.openModal(PreferencesModal)
|
||||
},
|
||||
openPlanetCreateModal: function () {
|
||||
this.openModal(PlanetCreateModal, {transitionTo: this.transitionTo})
|
||||
},
|
||||
toggleProfilePopup: function () {
|
||||
this.openProfilePopup()
|
||||
},
|
||||
openProfilePopup: function () {
|
||||
this.setState({isProfilePopupOpen: true}, function () {
|
||||
document.addEventListener('click', this.closeProfilePopup)
|
||||
})
|
||||
},
|
||||
closeProfilePopup: function () {
|
||||
document.removeEventListener('click', this.closeProfilePopup)
|
||||
this.setState({isProfilePopupOpen: false})
|
||||
},
|
||||
handleLogoutClick: function () {
|
||||
this.openModal(LogoutModal, {transitionTo: this.transitionTo})
|
||||
},
|
||||
switchPlanetByIndex: function (index) {
|
||||
var planetProps = this.refs.planets.props.children[index - 1].props
|
||||
this.transitionTo('planet', {userName: planetProps.userName, planetName: planetProps.planetName})
|
||||
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()
|
||||
@@ -96,88 +77,33 @@ module.exports = React.createClass({
|
||||
if (this.state.currentUser == null) {
|
||||
return null
|
||||
}
|
||||
console.log(this.state.currentUser.Teams)
|
||||
|
||||
var planets = this.state.currentUser.Planets.map(function (planet) {
|
||||
planet.userName = this.state.currentUser.name
|
||||
return planet
|
||||
}.bind(this)).concat(this.state.currentUser.Teams.reduce(function (_planets, team) {
|
||||
return _planets.concat(team.Planets == null ? [] : team.Planets.map(function (planet) {
|
||||
planet.userName = team.name
|
||||
return planet
|
||||
}))
|
||||
}, [])).map(function (planet, index) {
|
||||
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 userName={planet.userName} planetName={planet.name} key={planet.id} className={params.userName === planet.userName && params.planetName === planet.name ? 'active' : ''}>
|
||||
<Link to='planet' params={{userName: planet.userName, planetName: planet.name}}>
|
||||
{planet.name[0]}
|
||||
<div className='planetTooltip'>{planet.userName}/{planet.name}</div>
|
||||
<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>
|
||||
)
|
||||
})
|
||||
|
||||
var popup = this.renderPopup()
|
||||
|
||||
return (
|
||||
<div className='HomeNavigator'>
|
||||
<button onClick={this.toggleProfilePopup} className='profileButton'>
|
||||
<ProfileImage size='55' email={this.state.currentUser.email}/>
|
||||
</button>
|
||||
{popup}
|
||||
<ul ref='planets' className='planetList'>
|
||||
{planets}
|
||||
<ul ref='users' className='userList'>
|
||||
{userButtons}
|
||||
</ul>
|
||||
<button onClick={this.openPlanetCreateModal} className='newPlanet'>
|
||||
<button onClick={this.openTeamCreateModal} className='newTeamButton'>
|
||||
<i className='fa fa-plus'/>
|
||||
<div className='tooltip'>Create new planet</div>
|
||||
<div className='tooltip'>Create new team</div>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
renderPopup: function () {
|
||||
var teams = this.state.currentUser.Teams == null ? [] : this.state.currentUser.Teams.map(function (team) {
|
||||
return (
|
||||
<li key={'user-' + team.id}>
|
||||
<Link to='userHome' params={{userName: team.name}} className='userName'>{team.profileName} ({team.name})</Link>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div ref='profilePopup' className={'profilePopup' + (this.state.isProfilePopupOpen ? '' : ' close')}>
|
||||
<div className='profileGroup'>
|
||||
<div className='profileGroupLabel'>
|
||||
<span>You</span>
|
||||
</div>
|
||||
<ul className='profileGroupList'>
|
||||
<li>
|
||||
<Link to='userHome' params={{userName: this.state.currentUser.name}} className='userName'>Profile ({this.state.currentUser.name})</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className='profileGroup'>
|
||||
<div className='profileGroupLabel'>
|
||||
<span>Team</span>
|
||||
</div>
|
||||
<ul className='profileGroupList'>
|
||||
{teams}
|
||||
<li>
|
||||
<button onClick={this.openTeamCreateModal} className='createNewTeam'><i className='fa fa-plus-square-o'/> create new team</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul className='controlGroup'>
|
||||
<li>
|
||||
<button onClick={this.openPreferencesModal}><i className='fa fa-gears fa-fw'/> Preferences</button>
|
||||
</li>
|
||||
<li>
|
||||
<button onClick={this.handleLogoutClick}><i className='fa fa-sign-out fa-fw'/> Log out</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var CodeForm = require('./CodeForm')
|
||||
var NoteForm = require('./NoteForm')
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react')
|
||||
|
||||
var socket = require('../Services/socket')
|
||||
|
||||
79
browser/main/Components/ModeIcon.jsx
Normal file
79
browser/main/Components/ModeIcon.jsx
Normal file
@@ -0,0 +1,79 @@
|
||||
var React = require('react')
|
||||
|
||||
module.exports = React.createClass({
|
||||
propTypes: {
|
||||
className: React.PropTypes.string,
|
||||
mode: React.PropTypes.string
|
||||
},
|
||||
getClassName: function () {
|
||||
var mode = this.props.mode
|
||||
switch (mode) {
|
||||
// Script
|
||||
case 'javascript':
|
||||
return 'devicon-javascript-plain'
|
||||
case 'jsx':
|
||||
return 'devicon-react-original'
|
||||
case 'coffee':
|
||||
return 'devicon-coffeescript-original'
|
||||
case 'ruby':
|
||||
return 'devicon-ruby-plain'
|
||||
case 'erlang':
|
||||
return 'devicon-erlang-plain'
|
||||
case 'php':
|
||||
return 'devicon-php-plain'
|
||||
|
||||
// HTML
|
||||
case 'html':
|
||||
return 'devicon-html5-plain'
|
||||
|
||||
// Stylesheet
|
||||
case 'css':
|
||||
return 'devicon-css3-plain'
|
||||
case 'less':
|
||||
return 'devicon-less-plain-wordmark'
|
||||
case 'sass':
|
||||
case 'scss':
|
||||
return 'devicon-sass-original'
|
||||
|
||||
// Compile
|
||||
case 'c_cpp':
|
||||
return 'devicon-c-plain'
|
||||
case 'csharp':
|
||||
return 'devicon-csharp-plain'
|
||||
case 'objc':
|
||||
return 'devicon-apple-original'
|
||||
case 'golang':
|
||||
return 'devicon-go-plain'
|
||||
case 'java':
|
||||
return 'devicon-java-plain'
|
||||
|
||||
// Framework
|
||||
case 'django':
|
||||
return 'devicon-django-plain'
|
||||
|
||||
// Config
|
||||
case 'dockerfile':
|
||||
return 'devicon-docker-plain'
|
||||
case 'gitignore':
|
||||
return 'devicon-git-plain'
|
||||
|
||||
// Shell
|
||||
case 'sh':
|
||||
case 'batchfile':
|
||||
case 'powershell':
|
||||
return 'fa fa-fw fa-terminal'
|
||||
|
||||
case 'text':
|
||||
case 'plain_text':
|
||||
case 'markdown':
|
||||
return 'fa fa-fw fa-file-text-o'
|
||||
}
|
||||
return 'fa fa-fw fa-code'
|
||||
},
|
||||
render: function () {
|
||||
var className = this.getClassName()
|
||||
return (
|
||||
<i className={this.props.className + ' ' + className}/>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var Select = require('react-select')
|
||||
|
||||
var Hq = require('../Services/Hq')
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
var React = require('react/addons')
|
||||
var moment = require('moment')
|
||||
|
||||
var CodeViewer = require('./CodeViewer')
|
||||
var CodeEditModal = require('./CodeEditModal')
|
||||
var CodeDeleteModal = require('./CodeDeleteModal')
|
||||
var NoteEditModal = require('./NoteEditModal')
|
||||
var NoteDeleteModal = require('./NoteDeleteModal')
|
||||
var MarkdownPreview = require('./MarkdownPreview')
|
||||
var ProfileImage = require('./ProfileImage')
|
||||
|
||||
var Modal = require('../Mixins/Modal')
|
||||
var ForceUpdate = require('../Mixins/ForceUpdate')
|
||||
|
||||
module.exports = React.createClass({
|
||||
mixins: [ForceUpdate(60000), Modal],
|
||||
propTypes: {
|
||||
article: React.PropTypes.object,
|
||||
showOnlyWithTag: React.PropTypes.func,
|
||||
planet: React.PropTypes.object
|
||||
},
|
||||
getInitialState: function () {
|
||||
return {
|
||||
isEditModalOpen: false
|
||||
}
|
||||
},
|
||||
openEditModal: function () {
|
||||
if (this.props.article == null) return
|
||||
switch (this.props.article.type) {
|
||||
case 'code' :
|
||||
this.openModal(CodeEditModal, {code: this.props.article, planet: this.props.planet})
|
||||
break
|
||||
case 'note' :
|
||||
this.openModal(NoteEditModal, {note: this.props.article, planet: this.props.planet})
|
||||
}
|
||||
},
|
||||
openDeleteModal: function () {
|
||||
if (this.props.article == null) return
|
||||
switch (this.props.article.type) {
|
||||
case 'code' :
|
||||
this.openModal(CodeDeleteModal, {code: this.props.article, planet: this.props.planet})
|
||||
break
|
||||
case 'note' :
|
||||
this.openModal(NoteDeleteModal, {note: this.props.article, planet: this.props.planet})
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
var article = this.props.article
|
||||
if (article == null) {
|
||||
return (
|
||||
<div className='PlanetArticleDetail'>
|
||||
Nothing selected
|
||||
</div>
|
||||
)
|
||||
}
|
||||
var tags = article.Tags.length > 0 ? article.Tags.map(function (tag) {
|
||||
return (
|
||||
<a onClick={this.props.showOnlyWithTag(tag.name)} key={tag.id}>#{tag.name}</a>
|
||||
)
|
||||
}.bind(this)) : (
|
||||
<a className='noTag'>Not tagged yet</a>
|
||||
)
|
||||
if (article.type === 'code') {
|
||||
return (
|
||||
<div className='PlanetArticleDetail codeDetail'>
|
||||
<div className='detailHeader'>
|
||||
<div className='itemLeft'>
|
||||
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||
<i className='fa fa-code fa-fw'></i>
|
||||
</div>
|
||||
|
||||
<div className='itemRight'>
|
||||
<div className='itemInfo'>{moment(article.updatedAt).fromNow()} by <span className='userProfileName'>{article.User.profileName}</span></div>
|
||||
<div className='description'>{article.description}</div>
|
||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||
</div>
|
||||
|
||||
<span className='itemControl'>
|
||||
<button id='articleEditButton' onClick={this.openEditModal} className='editButton'>
|
||||
<i className='fa fa-edit fa-fw'></i>
|
||||
<div className='tooltip'>Edit</div>
|
||||
</button>
|
||||
<button onClick={this.openDeleteModal} className='deleteButton'>
|
||||
<i className='fa fa-trash fa-fw'></i>
|
||||
<div className='tooltip'>Delete</div>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div className='detailBody'>
|
||||
<CodeViewer className='content' code={article.content} mode={article.mode}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className='PlanetArticleDetail noteDetail'>
|
||||
<div className='detailHeader'>
|
||||
<div className='itemLeft'>
|
||||
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||
<i className='fa fa-file-text-o fa-fw'></i>
|
||||
</div>
|
||||
|
||||
<div className='itemRight'>
|
||||
<div className='itemInfo'>{moment(article.updatedAt).fromNow()} by <span className='userProfileName'>{article.User.profileName}</span></div>
|
||||
<div className='description'>{article.title}</div>
|
||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||
</div>
|
||||
|
||||
<span className='itemControl'>
|
||||
<button id='articleEditButton' onClick={this.openEditModal} className='editButton'>
|
||||
<i className='fa fa-edit fa-fw'></i>
|
||||
<div className='tooltip'>Edit</div>
|
||||
</button>
|
||||
<button onClick={this.openDeleteModal} className='deleteButton'>
|
||||
<i className='fa fa-trash fa-fw'></i>
|
||||
<div className='tooltip'>Delete</div>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div className='detailBody'>
|
||||
<MarkdownPreview className='content' content={article.content}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,100 +0,0 @@
|
||||
var React = require('react/addons')
|
||||
var ReactRouter = require('react-router')
|
||||
var moment = require('moment')
|
||||
|
||||
var ForceUpdate = require('../Mixins/ForceUpdate')
|
||||
var Markdown = require('../Mixins/Markdown')
|
||||
|
||||
var ProfileImage = require('../Components/ProfileImage')
|
||||
|
||||
module.exports = React.createClass({
|
||||
mixins: [ReactRouter.Navigation, ReactRouter.State, ForceUpdate(60000), Markdown],
|
||||
propTypes: {
|
||||
articles: React.PropTypes.array,
|
||||
showOnlyWithTag: React.PropTypes.func
|
||||
},
|
||||
handleArticleClikck: function (article) {
|
||||
if (article.type === 'code') {
|
||||
return function (e) {
|
||||
var params = this.getParams()
|
||||
|
||||
this.transitionTo('codes', {
|
||||
userName: params.userName,
|
||||
planetName: params.planetName,
|
||||
localId: article.localId
|
||||
})
|
||||
}.bind(this)
|
||||
}
|
||||
|
||||
if (article.type === 'note') {
|
||||
return function (e) {
|
||||
var params = this.getParams()
|
||||
|
||||
this.transitionTo('notes', {
|
||||
userName: params.userName,
|
||||
planetName: params.planetName,
|
||||
localId: article.localId
|
||||
})
|
||||
}.bind(this)
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
var articles = this.props.articles.map(function (article) {
|
||||
var tags = article.Tags.length > 0 ? article.Tags.map(function (tag) {
|
||||
return (
|
||||
<a onClick={this.props.showOnlyWithTag(tag.name)} key={tag.id}>#{tag.name}</a>
|
||||
)
|
||||
}.bind(this)) : (
|
||||
<a className='noTag'>Not tagged yet</a>
|
||||
)
|
||||
var params = this.getParams()
|
||||
var isActive = article.type === 'code' ? this.isActive('codes') && parseInt(params.localId, 10) === article.localId : this.isActive('notes') && parseInt(params.localId, 10) === article.localId
|
||||
|
||||
if (article.type === 'code') {
|
||||
return (
|
||||
<li onClick={this.handleArticleClikck(article)} key={'code-' + article.id}>
|
||||
<div className={'articleItem' + (isActive ? ' active' : '')}>
|
||||
<div className='itemLeft'>
|
||||
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||
<i className='fa fa-code fa-fw'></i>
|
||||
</div>
|
||||
<div className='itemRight'>
|
||||
<div className='itemInfo'>{moment(article.updatedAt).fromNow()} by <span className='userProfileName'>{article.User.profileName}</span></div>
|
||||
<div className='description'>{article.description}</div>
|
||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='divider'></div>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<li onClick={this.handleArticleClikck(article)} key={'note-' + article.id}>
|
||||
<div className={'articleItem blueprintItem' + (isActive ? ' active' : '')}>
|
||||
<div className='itemLeft'>
|
||||
<ProfileImage className='profileImage' size='25' email={article.User.email}/>
|
||||
<i className='fa fa-file-text-o fa-fw'></i>
|
||||
</div>
|
||||
|
||||
<div className='itemRight'>
|
||||
<div className='itemInfo'>{moment(article.updatedAt).fromNow()} by <span className='userProfileName'>{article.User.profileName}</span></div>
|
||||
<div className='description'>{article.title}</div>
|
||||
<div className='tags'><i className='fa fa-tags'/>{tags}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='divider'></div>
|
||||
</li>
|
||||
)
|
||||
|
||||
}.bind(this))
|
||||
|
||||
return (
|
||||
<div className='PlanetArticleList'>
|
||||
<ul ref='articles'>
|
||||
{articles}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var Hq = require('../Services/Hq')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var ReactRouter = require('react-router')
|
||||
var Link = ReactRouter.Link
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var ReactRouter = require('react-router')
|
||||
var Navigation = ReactRouter.Navigation
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var Hq = require('../Services/Hq')
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var ipc = require('ipc')
|
||||
var remote = require('remote')
|
||||
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var LinkedState = require('../Mixins/LinkedState')
|
||||
var ExternalLink = require('../Mixins/ExternalLink')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var md5 = require('md5')
|
||||
|
||||
module.exports = React.createClass({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
|
||||
var Hq = require('../Services/Hq')
|
||||
var socket = require('../Services/socket')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* global localStorage */
|
||||
|
||||
var React = require('react/addons')
|
||||
var React = require('react')
|
||||
var Reflux = require('reflux')
|
||||
var Select = require('react-select')
|
||||
|
||||
|
||||
30
browser/main/Components/TopBar.jsx
Normal file
30
browser/main/Components/TopBar.jsx
Normal file
@@ -0,0 +1,30 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
})
|
||||
53
browser/main/Components/UserNavigator.jsx
Normal file
53
browser/main/Components/UserNavigator.jsx
Normal file
@@ -0,0 +1,53 @@
|
||||
var React = require('react')
|
||||
var _ = require('lodash')
|
||||
|
||||
module.exports = React.createClass({
|
||||
propTypes: {
|
||||
createNewArticle: React.PropTypes.func,
|
||||
search: React.PropTypes.string,
|
||||
user: React.PropTypes.object
|
||||
},
|
||||
render: function () {
|
||||
var user = this.props.user
|
||||
|
||||
var folders = _.isArray(user.Folders) ? user.Folders.map(function (folder) {
|
||||
var isActive = this.props.search.match(new RegExp('in:' + folder.name))
|
||||
return (
|
||||
<button className={'folderButton' + (isActive ? ' active' : '')}><i className='fa fa-fw fa-square'/> {folder.name}</button>
|
||||
)
|
||||
}.bind(this)) : null
|
||||
|
||||
var members = _.isArray(user.Members) ? user.Members.map(function (member) {
|
||||
return <button className='memberButton'>{member.profileName}</button>
|
||||
}) : null
|
||||
|
||||
return (
|
||||
<div className='UserNavigator'>
|
||||
<div className='profile'>
|
||||
<div className='profileName'>{user.profileName}</div>
|
||||
<div className='name'>{user.name}</div>
|
||||
<div className='dropdownIcon'><i className='fa fa-chevron-down'/></div>
|
||||
</div>
|
||||
|
||||
<div className='control'>
|
||||
<button onClick={this.props.createNewArticle} className='newPostButton'>New Post</button>
|
||||
</div>
|
||||
|
||||
<div className='menu'>
|
||||
<div className='menuGruop folders'>
|
||||
<div className='label'>
|
||||
Folders
|
||||
<button className='plusButton'><i className='fa fa-plus'/></button>
|
||||
</div>
|
||||
<button className={'folderButton' + (this.props.search.match(/in:[a-z0-9-_]/) ? '' : ' active')}>All Folders</button>
|
||||
{folders}
|
||||
</div>
|
||||
|
||||
{user.userType === 'team' ? (
|
||||
<div className='members'>{members}</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user