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 ( +
+
{article.title}
+
+
+
+
+ ) + } + } + return ( +
+
Nothing selected
+
+ ) + } +}) 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 ( +
    +
      + {list} +
    +
    + ) + } +}) 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