diff --git a/Gulpfile.js b/Gulpfile.js
deleted file mode 100644
index 405da03b..00000000
--- a/Gulpfile.js
+++ /dev/null
@@ -1,129 +0,0 @@
-var gulp = require('gulp')
-var styl = require('gulp-stylus')
-var autoprefixer = require('gulp-autoprefixer')
-var del = require('del')
-var runSequence = require('run-sequence')
-var plumber = require('gulp-plumber')
-var notify = require('gulp-notify')
-var rename = require('gulp-rename')
-var livereload = require('gulp-livereload')
-var inject = require('gulp-inject')
-
-// for Dist
-var rev = require('gulp-rev')
-var ngAnnotate = require('gulp-ng-annotate')
-var templateCache = require('gulp-angular-templatecache')
-var uglify = require('gulp-uglify')
-var minifyCss = require('gulp-minify-css')
-var merge = require('merge-stream')
-var concat = require('gulp-concat')
-var minifyHtml = require('gulp-minify-html')
-
-var config = require('./build.config.js')
-
-gulp.task('build', function () {
- var tpls = gulp.src(['src/browser/main/**/*.html','!src/browser/main/index.html','!src/browser/main/index.inject.html'])
- .pipe(templateCache({}))
- .pipe(concat('tpls.js'))
- .pipe(ngAnnotate())
- .pipe(uglify())
- .pipe(gulp.dest('build'))
- var js = gulp.src(['src/browser/main/**/*.js', 'src/browser/shared/**/*.js'])
- .pipe(concat('app.js'))
- .pipe(ngAnnotate())
- .pipe(uglify())
- .pipe(gulp.dest('build'))
- var css = gulp.src(['src/browser/main/**/*.css', 'src/browser/shared/**/*.css'])
- .pipe(concat('all.css'))
- .pipe(minifyCss())
- .pipe(gulp.dest('build'))
- return merge(tpls, js, css)
-})
-
-gulp.task('vendor', function () {
- var vendors = config.vendors
-
- var vendorFiles = vendors.map(function (vendor) {
- return vendor.src
- })
-
- vendorFiles.push('node_modules/font-awesome/**/font-awesome.css')
- vendorFiles.push('node_modules/font-awesome/**/fontawesome-webfont.*')
- vendorFiles.push('node_modules/font-awesome/**/FontAwesome.*')
-
- return gulp.src(vendorFiles)
- .pipe(gulp.dest('src/browser/vendor'))
-})
-
-gulp.task('styl', function () {
- return gulp.src('src/browser/main/styles/app.styl')
- .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
- .pipe(styl())
- .pipe(autoprefixer())
- .pipe(gulp.dest('src/browser/main/styles/'))
- .pipe(livereload())
- .pipe(notify('Stylus!!'))
-})
-
-gulp.task('styl-popup', function () {
- return gulp.src('src/browser/popup/styles/app.styl')
- .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
- .pipe(styl())
- .pipe(autoprefixer())
- .pipe(gulp.dest('src/browser/popup/styles/'))
- .pipe(livereload())
- .pipe(notify('Stylus!! @POPUP'))
-})
-
-gulp.task('bs', function () {
- return gulp.src('src/browser/shared/styles/bootstrap.styl')
- .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
- .pipe(styl())
- .pipe(autoprefixer())
- .pipe(gulp.dest('src/browser/shared/styles'))
- .pipe(notify('Bootstrap compiled!!'))
- .pipe(livereload())
-})
-
-gulp.task('inject', function (cb) {
- runSequence(['inject-main', 'inject-popup'], cb)
-})
-
-gulp.task('inject-main', function () {
- return gulp.src('src/browser/main/index.inject.html')
- .pipe(inject(gulp.src(['src/browser/main/**/*.js', 'src/browser/main/**/*.css', 'src/browser/shared/**/*.js', 'src/browser/shared/**/*.css'], {read: false}), {
- relative: true
- }))
- .pipe(rename(function (path) {
- path.basename = 'index'
- }))
- .pipe(gulp.dest('src/browser/main/'))
-})
-
-gulp.task('watch-main', function () {
- gulp.watch(
- ['src/browser/main/index.inject.html', 'src/browser/main/**/*.js', 'src/browser/main/**/*.css', 'src/browser/shared/**/*.js', 'src/browser/shared/**/*.css'], ['inject-main'])
-
- gulp.watch('src/browser/main/styles/**/*.styl', ['styl'])
- gulp.watch('src/browser/popup/styles/**/*.styl', ['styl-popup'])
- gulp.watch('src/browser/shared/styles/**/*.styl', ['bs'])
- livereload.listen()
-})
-gulp.task('inject-popup', function () {
- return gulp.src('src/browser/popup/index.inject.html')
- .pipe(inject(gulp.src(['src/browser/popup/**/*.js', 'src/browser/popup/**/*.css', 'src/browser/shared/**/*.js', 'src/browser/shared/**/*.css'], {read: false}), {
- relative: true
- }))
- .pipe(rename(function (path) {
- path.basename = 'index'
- }))
- .pipe(gulp.dest('src/browser/popup/'))
-})
-
-gulp.task('del', function (cb) {
- del(['build/**/*'], cb)
-})
-
-gulp.task('default', function (cb) {
- runSequence('del', 'build', 'watch', cb)
-})
diff --git a/browser/finder/Components/FinderDetail.jsx b/browser/finder/Components/FinderDetail.jsx
new file mode 100644
index 00000000..7a56f3f0
--- /dev/null
+++ b/browser/finder/Components/FinderDetail.jsx
@@ -0,0 +1,43 @@
+var React = require('react/addons')
+
+var CodeViewer = require('../../main/Components/CodeViewer')
+
+var Markdown = require('../../main/Mixins/Markdown')
+
+module.exports = React.createClass({
+ mixins: [Markdown],
+ propTypes: {
+ currentArticle: React.PropTypes.object
+ },
+ render: function () {
+ var article = this.props.currentArticle
+
+ if (article != null) {
+ if (article.type === 'snippet') {
+ return (
+
+
{article.callSign}
+
+
+
+
+ )
+ } else if (article.type === 'blueprint') {
+
+ return (
+
+ )
+ }
+ }
+ return (
+
+ )
+ }
+})
diff --git a/browser/finder/Components/FinderInput.jsx b/browser/finder/Components/FinderInput.jsx
new file mode 100644
index 00000000..467d5a40
--- /dev/null
+++ b/browser/finder/Components/FinderInput.jsx
@@ -0,0 +1,15 @@
+var React = require('react/addons')
+
+module.exports = React.createClass({
+ propTypes: {
+ onChange: React.PropTypes.func,
+ search: React.PropTypes.string
+ },
+ render: function () {
+ return (
+
+
+
+ )
+ }
+})
diff --git a/browser/finder/Components/FinderList.jsx b/browser/finder/Components/FinderList.jsx
new file mode 100644
index 00000000..2227f9f1
--- /dev/null
+++ b/browser/finder/Components/FinderList.jsx
@@ -0,0 +1,69 @@
+var React = require('react/addons')
+
+module.exports = React.createClass({
+ propTypes: {
+ articles: React.PropTypes.arrayOf,
+ currentArticle: React.PropTypes.shape({
+ id: React.PropTypes.number,
+ type: React.PropTypes.string
+ })
+ },
+ componentDidUpdate: function () {
+ var index = this.props.articles.indexOf(this.props.currentArticle)
+ var el = React.findDOMNode(this)
+ var li = el.querySelectorAll('li')[index]
+
+ var overflowBelow = el.clientHeight + el.scrollTop < li.offsetTop + li.clientHeight
+ if (overflowBelow) {
+ el.scrollTop = li.offsetTop + li.clientHeight - el.clientHeight
+ }
+ var overflowAbove = el.scrollTop > li.offsetTop
+ if (overflowAbove) {
+ el.scrollTop = li.offsetTop
+ }
+ },
+ render: function () {
+ var list = this.props.articles.map(function (article) {
+ if (article == null) {
+ return (
+
+ Undefined
+
+
+ )
+ }
+
+ var isActive = this.props.currentArticle != null && (article.type === this.props.currentArticle.type && article.id === this.props.currentArticle.id)
+ if (article.type === 'snippet') {
+ return (
+
+ {article.callSign} / {article.description.substring(0, 10)}
+
+
+ )
+ }
+ if (article.type === 'blueprint') {
+ return (
+
+ {article.title}
+
+
+ )
+ }
+ return (
+
+ Undefined
+
+
+ )
+ }.bind(this))
+
+ return (
+
+ )
+ }
+})
diff --git a/browser/finder/index.electron.html b/browser/finder/index.electron.html
new file mode 100644
index 00000000..c20faec7
--- /dev/null
+++ b/browser/finder/index.electron.html
@@ -0,0 +1,53 @@
+
+
+
+ CodeXen Popup
+
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/finder/index.html b/browser/finder/index.html
new file mode 100644
index 00000000..e69de29b
diff --git a/browser/finder/index.jsx b/browser/finder/index.jsx
new file mode 100644
index 00000000..2a76d444
--- /dev/null
+++ b/browser/finder/index.jsx
@@ -0,0 +1,188 @@
+/* global localStorage */
+var remote = require('remote')
+var hideFinder = remote.getGlobal('hideFinder')
+var clipboard = require('clipboard')
+
+var React = require('react/addons')
+
+var FinderInput = require('./Components/FinderInput')
+var FinderList = require('./Components/FinderList')
+var FinderDetail = require('./Components/FinderDetail')
+
+// filter start
+function basicFilter (keyword, articles) {
+ if (keyword === '' || keyword == null) return articles
+ var firstFiltered = articles.filter(function (article) {
+
+ var first = article.type === 'snippet' ? article.callSign : article.title
+ if (first.match(new RegExp(keyword, 'i'))) return true
+
+ return false
+ })
+
+ var secondFiltered = articles.filter(function (article) {
+ var second = article.type === 'snippet' ? article.description : article.content
+ if (second.match(new RegExp(keyword, 'i'))) return true
+
+ return false
+ })
+
+ var thirdFiltered = articles.filter(function (article) {
+ if (article.type === 'snippet') {
+ if (article.content.match(new RegExp(keyword, 'i'))) return true
+ }
+ return false
+ })
+
+ return firstFiltered.concat(secondFiltered, thirdFiltered).filter(function (value, index, self) {
+ return self.indexOf(value) === index
+ })
+}
+
+function snippetFilter (articles) {
+ return articles.filter(function (article) {
+ return article.type === 'snippet'
+ })
+}
+
+function blueprintFilter (articles) {
+ return articles.filter(function (article) {
+ return article.type === 'blueprint'
+ })
+}
+
+function tagFilter (keyword, articles) {
+ return articles.filter(function (article) {
+ return article.Tags.some(function (tag) {
+ return tag.name.match(new RegExp('^' + keyword, 'i'))
+ })
+ })
+}
+
+function searchArticle (search, articles) {
+ var keywords = search.split(' ')
+
+ for (var keyword of keywords) {
+ if (keyword.match(/^\$s/, 'i')) {
+ articles = snippetFilter(articles)
+ continue
+ } else if (keyword.match(/^\$b/, 'i')) {
+ articles = blueprintFilter(articles)
+ continue
+ } else if (keyword.match(/^#[A-Za-z0-9]+/)) {
+ articles = tagFilter(keyword.substring(1, keyword.length), articles)
+ continue
+ }
+ articles = basicFilter(keyword, articles)
+ }
+
+ return articles
+}
+// Filter end
+
+function fetchArticles () {
+ var user = JSON.parse(localStorage.getItem('user'))
+ if (user == null) {
+ console.log('need to login')
+ return []
+ }
+
+ var articles = []
+ user.Planets.forEach(function (planet) {
+ var _planet = JSON.parse(localStorage.getItem('planet-' + planet.id))
+ articles = articles.concat(_planet.Snippets, _planet.Blueprints)
+ })
+ console.log(articles.length + ' articles')
+
+ return articles
+}
+
+var Finder = React.createClass({
+ getInitialState: function () {
+ var articles = fetchArticles()
+ return {
+ articles: articles,
+ currentArticle: articles[0],
+ search: ''
+ }
+ },
+ componentDidMount: function () {
+ document.addEventListener('keydown', this.handleKeyDown)
+ document.addEventListener('click', this.handleClick)
+ window.addEventListener('focus', this.handleFinderFocus)
+ },
+ componentWillUnmount: function () {
+ document.removeEventListener('keydown', this.handleKeyDown)
+ document.removeEventListener('click', this.handleClick)
+ window.removeEventListener('focus', this.handleFinderFocus)
+ },
+ handleFinderFocus: function () {
+ console.log('focusseeddddd')
+ this.focusInput()
+ var articles = fetchArticles()
+ this.setState({
+ articles: articles,
+ currentArticle: articles[0],
+ search: ''
+ })
+ },
+ handleKeyDown: function (e) {
+ if (e.keyCode === 38) {
+ this.selectPrevious()
+ e.preventDefault()
+ }
+
+ if (e.keyCode === 40) {
+ this.selectNext()
+ e.preventDefault()
+ }
+
+ if (e.keyCode === 13) {
+ var article = this.state.currentArticle
+ if (article.type === 'snippet') {
+ clipboard.writeText(article.content)
+ hideFinder()
+ e.preventDefault()
+ }
+ }
+ if (e.keyCode === 27) {
+ hideFinder()
+ e.preventDefault()
+ }
+ },
+ focusInput: function () {
+ React.findDOMNode(this.refs.finderInput).querySelector('input').focus()
+ },
+ handleClick: function () {
+ this.focusInput()
+ },
+ selectPrevious: function () {
+ var index = this.refs.finderList.props.articles.indexOf(this.state.currentArticle)
+ if (index > 0) {
+ this.setState({currentArticle: this.refs.finderList.props.articles[index - 1]})
+ }
+ },
+ selectNext: function () {
+ var index = this.refs.finderList.props.articles.indexOf(this.state.currentArticle)
+ if (index > -1 && index < this.refs.finderList.props.articles.length - 1) {
+ this.setState({currentArticle: this.refs.finderList.props.articles[index + 1]})
+ }
+ },
+ handleChange: function (e) {
+ this.setState({search: e.target.value}, function () {
+ this.setState({currentArticle: this.refs.finderList.props.articles[0]})
+ })
+ },
+ render: function () {
+ var articles = searchArticle(this.state.search, this.state.articles)
+ return (
+
+
+
+
+
+ )
+ }
+})
+
+React.render(, document.getElementById('content'))
diff --git a/browser/main/Components/BlueprintForm.jsx b/browser/main/Components/BlueprintForm.jsx
index 1c1fe04e..72f06505 100644
--- a/browser/main/Components/BlueprintForm.jsx
+++ b/browser/main/Components/BlueprintForm.jsx
@@ -7,9 +7,11 @@ var Select = require('react-select')
var request = require('superagent')
var PlanetActions = require('../Actions/PlanetActions')
+var apiUrl = require('../../../config').apiUrl
+
var getOptions = function (input, callback) {
request
- .get('http://localhost:8000/tags/search')
+ .get(apiUrl + 'tags/search')
.query({name: input})
.send()
.end(function (err, res) {
diff --git a/browser/main/Components/PersonalSettingModal.jsx b/browser/main/Components/PersonalSettingModal.jsx
index 09206ec7..12b032d3 100644
--- a/browser/main/Components/PersonalSettingModal.jsx
+++ b/browser/main/Components/PersonalSettingModal.jsx
@@ -8,7 +8,7 @@ var AuthActions = require('../Actions/AuthActions')
var AuthStore = require('../Stores/AuthStore')
-var apiUrl = 'http://localhost:8000/'
+var apiUrl = require('../../../config').apiUrl
module.exports = React.createClass({
mixins: [Catalyst.LinkedStateMixin],
diff --git a/browser/main/Components/PlanetAddUserModal.jsx b/browser/main/Components/PlanetAddUserModal.jsx
index 7342edf8..db237df5 100644
--- a/browser/main/Components/PlanetAddUserModal.jsx
+++ b/browser/main/Components/PlanetAddUserModal.jsx
@@ -7,9 +7,11 @@ var Catalyst = require('../Mixins/Catalyst')
var PlanetActions = require('../Actions/PlanetActions')
+var apiUrl = require('../../../config').apiUrl
+
var getOptions = function (input, callback) {
request
- .get('http://localhost:8000/users/search')
+ .get(apiUrl + 'users/search')
.query({name: input})
.send()
.end(function (err, res) {
diff --git a/browser/main/Components/PlanetSettingModal.jsx b/browser/main/Components/PlanetSettingModal.jsx
index f196811c..d3198f31 100644
--- a/browser/main/Components/PlanetSettingModal.jsx
+++ b/browser/main/Components/PlanetSettingModal.jsx
@@ -6,9 +6,11 @@ var Catalyst = require('../Mixins/Catalyst')
var PlanetActions = require('../Actions/PlanetActions')
+var apiUrl = require('../../../config').apiUrl
+
var getOptions = function (input, callback) {
request
- .get('http://localhost:8000/users/search')
+ .get(apiUrl + 'users/search')
.query({name: input})
.send()
.end(function (err, res) {
diff --git a/browser/main/Components/SnippetForm.jsx b/browser/main/Components/SnippetForm.jsx
index 384e0026..4a5dca11 100644
--- a/browser/main/Components/SnippetForm.jsx
+++ b/browser/main/Components/SnippetForm.jsx
@@ -6,9 +6,11 @@ var Select = require('react-select')
var request = require('superagent')
var PlanetActions = require('../Actions/PlanetActions')
+var apiUrl = require('../../../config').apiUrl
+
var getOptions = function (input, callback) {
request
- .get('http://localhost:8000/tags/search')
+ .get(apiUrl + 'tags/search')
.query({name: input})
.send()
.end(function (err, res) {
@@ -22,7 +24,7 @@ var getOptions = function (input, callback) {
label: tag.name,
value: tag.name
}
- }),
+ }),
complete: false
})
})
diff --git a/browser/main/Containers/MainContainer.jsx b/browser/main/Containers/MainContainer.jsx
index 76175980..95ed15b5 100644
--- a/browser/main/Containers/MainContainer.jsx
+++ b/browser/main/Containers/MainContainer.jsx
@@ -1,47 +1,87 @@
+/* global localStorage */
var React = require('react/addons')
var ReactRouter = require('react-router')
var RouteHandler = ReactRouter.RouteHandler
+var request = require('superagent')
var AuthStore = require('../Stores/AuthStore')
+var apiUrl = require('../../../config').apiUrl
+
+function fetchPlanet (planet) {
+ request
+ .get(apiUrl + planet.userName + '/' + planet.name)
+ .send()
+ .end(function (err, res) {
+ if (err) {
+ console.error(err)
+ return
+ }
+
+ var _planet = res.body
+ _planet.userName = planet.userName
+
+ _planet.Snippets = _planet.Snippets.map(function (snippet) {
+ snippet.type = 'snippet'
+ return snippet
+ })
+
+ _planet.Blueprints = _planet.Blueprints.map(function (blueprint) {
+ blueprint.type = 'blueprint'
+ return blueprint
+ })
+
+ localStorage.setItem('planet-' + _planet.id, JSON.stringify(_planet))
+ console.log('planet-' + _planet.id + ' fetched')
+ })
+}
+
module.exports = React.createClass({
- mixins: [ReactRouter.Navigation, ReactRouter.State],
- componentDidMount: function () {
- this.unsubscribe = AuthStore.listen(this.onListen)
- },
- componentWillUnmount: function () {
- this.unsubscribe()
- },
- onListen: function (res) {
- if (res == null || res.status == null) {
- return
- }
+ mixins: [ReactRouter.Navigation, ReactRouter.State],
+ componentDidMount: function () {
+ this.unsubscribe = AuthStore.listen(this.onListen)
- if (res.status === 'loggedIn' || res.status === 'registered') {
- var user = res.data
- var planet = user.Planets.length > 0 ? user.Planets[0] : null
- if (planet == null) {
- this.transitionTo('user', {userName: user.name})
- return
- }
- this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
- return
- }
-
- if (res.status === 'loggedOut') {
- this.transitionTo('login')
- return
- }
- },
- render: function () {
- // Redirect Login state
- if (this.getPath() === '/') {
- this.transitionTo('/login')
- }
- return (
-
-
-
- )
+ var user = JSON.parse(localStorage.getItem('user'))
+ if (user != null) {
+ user.Planets.forEach(fetchPlanet)
+ return
}
+ this.transitionTo('login')
+ },
+ componentWillUnmount: function () {
+ this.unsubscribe()
+ },
+ onListen: function (res) {
+ if (res == null || res.status == null) {
+ return
+ }
+
+ if (res.status === 'loggedIn' || res.status === 'registered') {
+ var user = res.data
+ var planet = user.Planets.length > 0 ? user.Planets[0] : null
+ if (planet == null) {
+ this.transitionTo('user', {userName: user.name})
+ return
+ }
+ this.transitionTo('planetHome', {userName: user.name, planetName: planet.name})
+
+ return
+ }
+
+ if (res.status === 'loggedOut') {
+ this.transitionTo('login')
+ return
+ }
+ },
+ render: function () {
+ // Redirect Login state
+ if (this.getPath() === '/') {
+ this.transitionTo('/login')
+ }
+ return (
+
+
+
+ )
+ }
})
diff --git a/browser/main/Containers/UserContainer.jsx b/browser/main/Containers/UserContainer.jsx
index c9e653be..a82f7f76 100644
--- a/browser/main/Containers/UserContainer.jsx
+++ b/browser/main/Containers/UserContainer.jsx
@@ -10,6 +10,8 @@ var UserNavigator = require('../Components/UserNavigator')
var AuthStore = require('../Stores/AuthStore')
var PlanetStore = require('../Stores/PlanetStore')
+var apiUrl = require('../../../config').apiUrl
+
module.exports = React.createClass({
mixins: [React.addons.LinkedStateMixin, ReactRouter.Navigation, ReactRouter.State],
propTypes: {
@@ -44,7 +46,7 @@ module.exports = React.createClass({
},
fetchUser: function (userName) {
request
- .get('http://localhost:8000/' + userName)
+ .get(apiUrl + userName)
.send()
.end(function (err, res) {
if (err) {
diff --git a/browser/main/Stores/AuthStore.js b/browser/main/Stores/AuthStore.js
index a7f0780c..bc29dd35 100644
--- a/browser/main/Stores/AuthStore.js
+++ b/browser/main/Stores/AuthStore.js
@@ -4,7 +4,7 @@ var request = require('superagent')
var AuthActions = require('../Actions/AuthActions')
-var apiUrl = 'http://localhost:8000/'
+var apiUrl = require('../../../config').apiUrl
var AuthStore = Reflux.createStore({
init: function () {
diff --git a/browser/main/Stores/PlanetStore.js b/browser/main/Stores/PlanetStore.js
index 56dbd025..e5feda88 100644
--- a/browser/main/Stores/PlanetStore.js
+++ b/browser/main/Stores/PlanetStore.js
@@ -4,7 +4,7 @@ var request = require('superagent')
var PlanetActions = require('../Actions/PlanetActions')
-var apiUrl = 'http://localhost:8000/'
+var apiUrl = require('../../../config').apiUrl
var PlanetStore = Reflux.createStore({
init: function () {
@@ -70,6 +70,8 @@ var PlanetStore = Reflux.createStore({
return blueprint
})
+ localStorage.setItem('planet-' + planet.id, JSON.stringify(planet))
+
planet.Articles = planet.Snippets.concat(planet.Blueprints).sort(function (a, b) {
a = new Date(a.updatedAt)
b = new Date(b.updatedAt)
@@ -94,6 +96,7 @@ var PlanetStore = Reflux.createStore({
}
var planet = res.body
+ localStorage.remove('planet-' + planet.id)
this.trigger({
status: 'planetDeleted',
@@ -186,6 +189,11 @@ var PlanetStore = Reflux.createStore({
.end(function (req, res) {
var snippet = res.body
snippet.type = 'snippet'
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
+ planet.Snippets.unshift(snippet)
+ localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
+
this.trigger({
status: 'articleCreated',
data: snippet
@@ -209,6 +217,17 @@ var PlanetStore = Reflux.createStore({
var snippet = res.body
snippet.type = 'snippet'
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
+ planet.Snippets.some(function (_snippet, index) {
+ if (snippet.id === _snippet) {
+ planet.Snippets[index] = snippet
+ return true
+ }
+ return false
+ })
+ localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
+
this.trigger({
status: 'articleUpdated',
data: snippet
@@ -230,6 +249,17 @@ var PlanetStore = Reflux.createStore({
}
var snippet = res.body
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + snippet.PlanetId))
+ planet.Snippets.some(function (_snippet, index) {
+ if (snippet.id === _snippet) {
+ planet.splice(index, 1)
+ return true
+ }
+ return false
+ })
+ localStorage.setItem('planet-' + snippet.PlanetId, JSON.stringify(planet))
+
this.trigger({
status: 'articleDeleted',
data: snippet
@@ -247,6 +277,11 @@ var PlanetStore = Reflux.createStore({
.end(function (req, res) {
var blueprint = res.body
blueprint.type = 'blueprint'
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
+ planet.Blueprints.unshift(blueprint)
+ localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(planet))
+
this.trigger({
status: 'articleCreated',
data: blueprint
@@ -270,6 +305,17 @@ var PlanetStore = Reflux.createStore({
var blueprint = res.body
blueprint.type = 'blueprint'
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
+ planet.Blueprints.some(function (_blueprint, index) {
+ if (blueprint.id === _blueprint) {
+ planet.Blueprints[index] = blueprint
+ return true
+ }
+ return false
+ })
+ localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(blueprint))
+
this.trigger({
status: 'articleUpdated',
data: blueprint
@@ -291,6 +337,17 @@ var PlanetStore = Reflux.createStore({
}
var blueprint = res.body
+
+ var planet = JSON.parse(localStorage.getItem('planet-' + blueprint.PlanetId))
+ planet.Blueprints.some(function (_blueprint, index) {
+ if (blueprint.id === _blueprint) {
+ planet.splice(index, 1)
+ return true
+ }
+ return false
+ })
+ localStorage.setItem('planet-' + blueprint.PlanetId, JSON.stringify(planet))
+
this.trigger({
status: 'articleDeleted',
data: blueprint
diff --git a/browser/main/index.electron.html b/browser/main/index.electron.html
index a47dc8a7..f7e105be 100644
--- a/browser/main/index.electron.html
+++ b/browser/main/index.electron.html
@@ -5,7 +5,7 @@
-
+
diff --git a/browser/styles/finder/index.styl b/browser/styles/finder/index.styl
new file mode 100644
index 00000000..e956490d
--- /dev/null
+++ b/browser/styles/finder/index.styl
@@ -0,0 +1,77 @@
+@import '../../../node_modules/nib/lib/nib'
+@import '../vars'
+@import '../mixins/*'
+global-reset()
+@import '../shared/*'
+
+body
+ font-family "Lato"
+ color textColor
+ font-size fontSize
+
+.Finder
+ absolute top bottom left right
+ .FinderInput
+ position absolute
+ top 11px
+ left 11px
+ right 11px
+ margin 0 auto
+ height 44px
+ box-sizing border-box
+ border-bottom solid 1px borderColor
+ input
+ display block
+ width 100%
+ border solid 1px borderColor
+ padding 0 10px
+ font-size 1em
+ height 33px
+ border-radius 5px
+ box-sizing border-box
+ border-radius 16.5px
+ &:focus, &.focus
+ border-color brandBorderColor
+ outline none
+ .FinderList
+ absolute left bottom
+ top 55px
+ border-right solid 1px borderColor
+ box-sizing border-box
+ width 250px
+ overflow-y auto
+ &>ul>li
+ .articleItem
+ padding 10px
+ border solid 2px transparent
+ box-sizing border-box
+ .divider
+ box-sizing border-box
+ border-bottom solid 1px borderColor
+ &.active
+ .articleItem
+ border-color brandColor
+
+ .FinderDetail
+ absolute right bottom
+ top 55px
+ left 250px
+ .header
+ absolute top left right
+ height 44px
+ box-sizing border-box
+ padding 0 10px
+ border-bottom solid 1px borderColor
+ line-height 44px
+ font-size 1.3em
+ .content
+ .ace_editor, .marked
+ position absolute
+ top 49px
+ left 5px
+ right 5px
+ bottom 5px
+ box-sizing border-box
+ .marked
+ marked()
+ overflow-y auto
diff --git a/build.config.js b/build.config.js
deleted file mode 100644
index d5e96a58..00000000
--- a/build.config.js
+++ /dev/null
@@ -1,48 +0,0 @@
-module.exports = {
- vendors: [
- {
- name: 'ace',
- src: 'node_modules/@rokt33r/ace-builds/src/**/*'
- },
- {
- name: 'angular',
- src: 'node_modules/angular/angular.js'
- },
- {
- name: 'angular-bootstrap',
- src: 'node_modules/angular-bootstrap/dist/ui-bootstrap-tpls.js'
- },
- {
- name: 'angular-sanitize',
- src: 'node_modules/angular-sanitize/angular-sanitize.js'
- },
- {
- name: 'angular-ui-router',
- src: 'node_modules/angular-ui-router/build/angular-ui-router.js'
- },
- {
- name: 'ui-select',
- src: 'node_modules/ui-select/dist/select.js'
- },
- {
- name: 'satellizer',
- src: 'node_modules/satellizer/satellizer.js'
- },
- {
- name: 'angular-md5',
- src: 'node_modules/angular-md5/angular-md5.js'
- },
- {
- name: 'moment',
- src: 'node_modules/moment/moment.js'
- },
- {
- name: 'angular-hotkeys',
- src: 'node_modules/angular-hotkeys/build/hotkeys.js'
- },
- {
- name: 'marked',
- src: 'node_modules/marked/lib/marked.js'
- }
- ]
-}
diff --git a/config.js b/config.js
new file mode 100644
index 00000000..8df966ca
--- /dev/null
+++ b/config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ apiUrl: 'http://codexen-server-dex2-ezebi636yb.elasticbeanstalk.com/'
+ // apiUrl: 'http://localhost:8000/'
+}
diff --git a/docs/events.md b/docs/events.md
deleted file mode 100644
index 62643c5f..00000000
--- a/docs/events.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Event List
-
-|name|Description|Delivery|
-|----|----|----|
-|userSignIn|a user signed in||
-|userSignOut|a user signed out||
-|snippetUpdated|snippet has been updated or created|snippet|
diff --git a/main.js b/main.js
index 61a35e00..1a460f40 100644
--- a/main.js
+++ b/main.js
@@ -1,6 +1,7 @@
var app = require('app') // Module to control application life.
var BrowserWindow = require('browser-window') // Module to create native browser window.
-
+var Menu = require('menu')
+var Tray = require('tray')
// Report crashes to our server.
require('crash-reporter').start()
@@ -13,25 +14,209 @@ var mainWindow = null
// })
app.on('ready', function () {
+ // menu start
+ var template = [
+ {
+ label: 'Electron',
+ submenu: [
+ {
+ label: 'About Electron',
+ selector: 'orderFrontStandardAboutPanel:'
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Services',
+ submenu: []
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Hide Electron',
+ accelerator: 'Command+H',
+ selector: 'hide:'
+ },
+ {
+ label: 'Hide Others',
+ accelerator: 'Command+Shift+H',
+ selector: 'hideOtherApplications:'
+ },
+ {
+ label: 'Show All',
+ selector: 'unhideAllApplications:'
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Quit',
+ accelerator: 'Command+Q',
+ selector: 'terminate:'
+ }
+ ]
+ },
+ {
+ label: 'Edit',
+ submenu: [
+ {
+ label: 'Undo',
+ accelerator: 'Command+Z',
+ selector: 'undo:'
+ },
+ {
+ label: 'Redo',
+ accelerator: 'Shift+Command+Z',
+ selector: 'redo:'
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Cut',
+ accelerator: 'Command+X',
+ selector: 'cut:'
+ },
+ {
+ label: 'Copy',
+ accelerator: 'Command+C',
+ selector: 'copy:'
+ },
+ {
+ label: 'Paste',
+ accelerator: 'Command+V',
+ selector: 'paste:'
+ },
+ {
+ label: 'Select All',
+ accelerator: 'Command+A',
+ selector: 'selectAll:'
+ }
+ ]
+ },
+ {
+ label: 'View',
+ submenu: [
+ {
+ label: 'Reload',
+ accelerator: 'Command+R',
+ click: function () {
+ BrowserWindow.getFocusedWindow().reload()
+ }
+ },
+ {
+ label: 'Toggle DevTools',
+ accelerator: 'Alt+Command+I',
+ click: function () {
+ BrowserWindow.getFocusedWindow().toggleDevTools()
+ }
+ }
+ ]
+ },
+ {
+ label: 'Window',
+ submenu: [
+ {
+ label: 'Minimize',
+ accelerator: 'Command+M',
+ selector: 'performMiniaturize:'
+ },
+ {
+ label: 'Close',
+ accelerator: 'Command+W',
+ selector: 'performClose:'
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Bring All to Front',
+ selector: 'arrangeInFront:'
+ }
+ ]
+ },
+ {
+ label: 'Help',
+ submenu: []
+ }
+ ]
+
+ var menu = Menu.buildFromTemplate(template)
+
+ Menu.setApplicationMenu(menu)
+ // menu end
+ var appIcon = new Tray(__dirname + '/tray-icon.png')
+ appIcon.setToolTip('This is my application.')
+ appIcon.on('clicked', function () {
+ if (mainWindow == null) {
+ makeNewMainWindow()
+ }
+ mainWindow.show()
+ })
+
makeNewMainWindow()
- function makeNewMainWindow () {
- console.log('new Window!')
- mainWindow = new BrowserWindow({
- width: 920,
- height: 640,
- 'web-preferences': {
- 'overlay-scrollbars': true
- }
- })
+ app.on('activate-with-no-open-windows', function () {
+ if (mainWindow == null) {
+ makeNewMainWindow()
+ return
+ }
+ mainWindow.show()
+ })
- mainWindow.loadUrl('file://' + __dirname + '/browser/main/index.electron.html')
+ var popUpWindow = new BrowserWindow({
+ width: 600,
+ height: 400,
+ show: false,
+ frame: false,
+ 'always-on-top': true,
+ 'web-preferences': {
+ 'overlay-scrollbars': true,
+ 'skip-taskbar': true
+ }
+ })
- mainWindow.on('closed', function () {
- console.log('main closed')
- mainWindow = null
- app.dock.hide()
- })
- app.dock.show()
+ popUpWindow.loadUrl('file://' + __dirname + '/browser/finder/index.electron.html')
+
+ popUpWindow.on('blur', function () {
+ popUpWindow.hide()
+ })
+ popUpWindow.setVisibleOnAllWorkspaces(true)
+
+ var globalShortcut = require('global-shortcut')
+
+ globalShortcut.register('ctrl+tab+shift', function () {
+ if (mainWindow != null && !mainWindow.isFocused()) {
+ mainWindow.hide()
+ }
+ popUpWindow.show()
+ })
+
+ global.hideFinder = function () {
+ if (mainWindow == null || !mainWindow.isVisible()) {
+ Menu.sendActionToFirstResponder('hide:')
+ }
+ popUpWindow.hide()
}
})
+
+function makeNewMainWindow () {
+ console.log('new Window!')
+ mainWindow = new BrowserWindow({
+ width: 920,
+ height: 640,
+ 'web-preferences': {
+ 'overlay-scrollbars': true
+ }
+ })
+
+ mainWindow.loadUrl('file://' + __dirname + '/browser/main/index.electron.html')
+
+ mainWindow.on('closed', function () {
+ console.log('main closed')
+ mainWindow = null
+ app.dock.hide()
+ })
+ app.dock.show()
+}
diff --git a/package.json b/package.json
index 9d2b661e..8cf84b79 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,8 @@
{
- "name": "codexen-app-builder",
+ "name": "codexen-app",
"version": "0.2.0",
- "description": "CodeXen App Builder",
+ "description": "CodeXen App",
+ "main": "main.js",
"scripts": {
"start": "npm run serve | npm run dev",
"serve": "./node_modules/.bin/http-server ./browser -p 8080",
@@ -31,6 +32,7 @@
"homepage": "https://github.com/Rokt33r/codexen-app#readme",
"dependencies": {
"dotenv": "^1.1.0",
+ "electron-stylus": "^0.1.0",
"halogen": "^0.1.10",
"markdown-it": "^4.3.1",
"moment": "^2.10.3",
diff --git a/tray-icon.png b/tray-icon.png
new file mode 100644
index 00000000..aba8e7d5
Binary files /dev/null and b/tray-icon.png differ
diff --git a/tray-icon@2x.png b/tray-icon@2x.png
new file mode 100644
index 00000000..eff01fc0
Binary files /dev/null and b/tray-icon@2x.png differ
diff --git a/tray-icon@4x.png b/tray-icon@4x.png
new file mode 100644
index 00000000..c3aba762
Binary files /dev/null and b/tray-icon@4x.png differ