1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-14 10:16:26 +00:00

Compare commits

..

8 Commits
v0.1 ... v0.1.1

Author SHA1 Message Date
Rokt33r
1a832c1fc4 rename api routes 2015-06-25 23:19:45 +09:00
Rokt33r
ee139ca36d update popup and set stage api 2015-06-25 21:01:57 +09:00
Rokt33r
549ce7f299 add How-to & Signout modal 2015-06-25 20:31:38 +09:00
Rokt33r
c72b5449bd clean up recipe 2015-06-25 19:28:36 +09:00
Rokt33r
debfa6323b update recipe states 2015-06-24 20:39:36 +09:00
Rokt33r
0e6fe35ca4 add Recipes(scaffolding) 2015-06-23 19:18:00 +09:00
Rokt33r
7c2cbfb32e fix injector bug & add tray-icon 2015-06-22 12:20:16 +09:00
Rokt33r
25eccacb4c refactor build config 2015-06-21 02:40:06 +09:00
117 changed files with 7949 additions and 609 deletions

7
.gitignore vendored
View File

@@ -1,5 +1,6 @@
/build
/node_modules
/electron_build
build/
node_modules/
electron_build/
.env
dist/
vendor/

View File

@@ -1,116 +1,43 @@
require('dotenv').load()
var env = process.env
var gulp = require('gulp')
var styl = require('gulp-stylus')
var autoprefixer = require('gulp-autoprefixer')
var templateCache = require('gulp-angular-templatecache')
var globby = require('globby')
var template = require('gulp-template')
var del = require('del')
var runSequence = require('run-sequence')
var plumber = require('gulp-plumber')
var notify = require('gulp-notify')
var changed = require('gulp-changed')
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 streamqueue = require('streamqueue')
var minifyHtml = require('gulp-minify-html')
var config = require('./build.config.js')
gulp.task('js', function () {
return streamqueue({objectMode: true},
gulp.src('tpls/env.js')
.pipe(template({
apiUrl: env.BUILD_API_URL
})),
gulp.src(['src/**/*.js'])
)
.pipe(changed('build'))
.pipe(gulp.dest('build'))
})
gulp.task('dist', function () {
var js = streamqueue({objectMode: true},
gulp.src(['src/**/*.js']),
gulp.src('tpls/env.js')
.pipe(template({
apiUrl: env.DIST_API_URL
})),
gulp.src('src/**/*.tpl.html')
.pipe(templateCache())
)
.pipe(ngAnnotate())
.pipe(uglify())
.pipe(concat('app.js'))
.pipe(gulp.dest('dist'))
var css = gulp.src('src/styles/main.styl')
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
.pipe(styl())
.pipe(autoprefixer())
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('dist'))
var index = gulp.src('src/index.html')
.pipe(template({
scripts: ['app.js'],
styles: ['main.css'],
env: 'dist'
}))
.pipe(minifyHtml())
.pipe(gulp.dest('dist'))
return merge(js, css, index)
})
gulp.task('styl', function () {
return gulp.src('src/styles/main.styl')
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
.pipe(styl())
.pipe(autoprefixer())
.pipe(gulp.dest('build'))
.pipe(notify('Stylus!!'))
.pipe(livereload())
})
gulp.task('tpls', function () {
return gulp.src('src/**/*.tpl.html')
.pipe(templateCache())
.pipe(notify('Tpls Done!! :)'))
.pipe(gulp.dest('build'))
})
gulp.task('index', function () {
var files = globby.sync(['build/**/*', '!build/vendor/**/*'])
var filter = function (files, ext) {
return files.filter(function (file) {
var reg = new RegExp('.+\.' + ext + '$')
return file.match(reg)
}).map(function (file) {
return file.replace('build/', '')
})
}
var scripts = filter(files, 'js')
var styles = filter(files, 'css')
return gulp.src('src/index.html')
.pipe(template({
scripts: scripts,
styles: styles,
env: 'build'
}))
.pipe(gulp.dest('build'))
.pipe(livereload())
return merge(tpls, js, css)
})
gulp.task('vendor', function () {
@@ -125,30 +52,73 @@ gulp.task('vendor', function () {
vendorFiles.push('node_modules/font-awesome/**/FontAwesome.*')
return gulp.src(vendorFiles)
.pipe(gulp.dest('build/vendor'))
.pipe(gulp.dest('src/browser/vendor'))
})
gulp.task('resources', function () {
return gulp.src('resources/**/*')
.pipe(changed('build/resources'))
.pipe(gulp.dest('build/resources'))
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('build', function (cb) {
runSequence(['js', 'styl', 'tpls', 'vendor', 'resources'], 'index', cb)
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('watch', function (cb) {
gulp.watch(['.env', 'tpls/env.js', 'src/**/*.js'], ['js'])
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.watch('src/styles/**/*.styl', ['styl'])
gulp.task('inject', function (cb) {
runSequence(['inject-main', 'inject-popup'], cb)
})
gulp.watch('src/**/*.tpl.html', ['tpls'])
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.watch(['build/**/*.js', 'src/index.html'], ['index'])
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)
@@ -157,5 +127,3 @@ gulp.task('del', function (cb) {
gulp.task('default', function (cb) {
runSequence('del', 'build', 'watch', cb)
})
require('./gulp-electron')(gulp)

View File

@@ -39,6 +39,10 @@ module.exports = {
{
name: 'angular-hotkeys',
src: 'node_modules/angular-hotkeys/build/hotkeys.js'
},
{
name: 'marked',
src: 'node_modules/marked/lib/marked.js'
}
]
}

View File

@@ -1,13 +0,0 @@
@import '../../src/styles/_vars'
@import '../../src/styles/mixins/*'
@import '../../src/styles/_bootstrap'
@import '../../src/styles/_index'
@import '../../src/styles/_shared'
@import '../../src/styles/modals/*'
@import '../../src/styles/directives/*'
@import '../../src/styles/states/*'
@import '_popup'

View File

@@ -1,139 +0,0 @@
require('dotenv').load()
var env = process.env
var styl = require('gulp-stylus')
var autoprefixer = require('gulp-autoprefixer')
var templateCache = require('gulp-angular-templatecache')
var globby = require('globby')
var template = require('gulp-template')
var del = require('del')
var runSequence = require('run-sequence')
var plumber = require('gulp-plumber')
var notify = require('gulp-notify')
var changed = require('gulp-changed')
var livereload = require('gulp-livereload')
var merge = require('merge-stream')
var config = require('./build.config.js')
module.exports = function (gulp) {
gulp.task('elec-env', function () {
return gulp.src('tpls/env.js')
.pipe(template({
apiUrl: env.ELEC_API_URL
}))
.pipe(gulp.dest('electron_build/config'))
})
gulp.task('elec-js', function () {
var main = gulp.src('src/**/*.js')
.pipe(changed('electron_build'))
.pipe(gulp.dest('electron_build'))
var electron = gulp.src('electron_src/**/*.js')
.pipe(changed('electron_build/electron'))
.pipe(gulp.dest('electron_build/electron'))
return merge(main, electron)
})
gulp.task('elec-styl', function () {
return gulp.src('electron_src/styles/main.styl')
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
.pipe(styl())
.pipe(autoprefixer())
.pipe(gulp.dest('electron_build'))
.pipe(notify('Stylus!!'))
.pipe(livereload())
})
gulp.task('elec-tpls', function () {
var main = gulp.src('src/**/*.tpl.html')
.pipe(templateCache())
.pipe(gulp.dest('electron_build'))
var electron = gulp.src('electron_src/**/*.tpl.html')
.pipe(templateCache())
.pipe(gulp.dest('electron_build/electron'))
return merge(main, electron)
})
gulp.task('elec-index', function () {
var files = globby.sync(['electron_build/**/*', '!electron_build/vendor/**/*', '!electron_build/electron/**/*'])
var filter = function (files, ext) {
return files.filter(function (file) {
var reg = new RegExp('.+\.' + ext + '$')
return file.match(reg)
}).map(function (file) {
return file.replace('electron_build/', '')
})
}
var scripts = filter(files, 'js')
var styles = filter(files, 'css')
var main = gulp.src('src/index.html')
.pipe(template({
scripts: scripts,
styles: styles,
env: 'build'
}))
.pipe(gulp.dest('electron_build'))
.pipe(livereload())
var electron = gulp.src('electron_src/**/index.html')
.pipe(gulp.dest('electron_build/electron'))
return merge(main, electron)
})
gulp.task('elec-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('electron_build/vendor'))
})
gulp.task('elec-resources', function () {
return gulp.src('resources/**/*')
.pipe(changed('electron_build/resources'))
.pipe(gulp.dest('electron_build/resources'))
})
gulp.task('elec-build', function (cb) {
runSequence(['elec-env', 'elec-js', 'elec-styl', 'elec-tpls', 'elec-vendor', 'elec-resources'], 'elec-index', cb)
})
gulp.task('elec-watch', function (cb) {
gulp.watch(['.env', 'tpls/env.js'], ['elec-env'])
gulp.watch(['src/**/*.js', 'electron_src/**/*.js'], ['elec-js'])
gulp.watch(['src/styles/**/*.styl', 'electron_src/styles/**/*.styl'], ['elec-styl'])
gulp.watch('src/**/*.tpl.html', ['elec-tpls'])
gulp.watch(['electron_build/**/*.js', 'src/index.html', 'src/index.html', 'electron_src/**/index.html'], ['elec-index'])
livereload.listen()
})
gulp.task('elec-del', function (cb) {
del(['electron_build/**/*'], cb)
})
gulp.task('elec', function (cb) {
runSequence('elec-del', 'elec-build', 'elec-watch', cb)
})
}

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

View File

@@ -1,8 +1,7 @@
{
"name": "codexen-app",
"version": "0.0.1",
"description": "CodeXen App",
"main": "index.js",
"name": "codexen-app-builder",
"version": "0.2.0",
"description": "CodeXen App Builder",
"scripts": {
"install": "gulp build",
"start": "http-server build",
@@ -31,6 +30,11 @@
},
"homepage": "https://github.com/Rokt33r/codexen-app#readme",
"dependencies": {
"dotenv": "^1.1.0",
"robotjs": "^0.1.2",
"node-notifier": "^4.2.1"
},
"devDependencies": {
"@rokt33r/ace-builds": "^1.1.9",
"@rokt33r/angular-ui-ace": "^0.2.3",
"angular": "^1.3.15",
@@ -39,38 +43,35 @@
"angular-md5": "^0.1.7",
"angular-sanitize": "^1.3.15",
"angular-ui-router": "^0.2.15",
"bootstrap-sass": "^3.3.4",
"bootstrap-styl": "^4.0.4",
"del": "^1.2.0",
"dotenv": "^1.1.0",
"electron-prebuilt": "^0.27.2",
"electron-rebuild": "^0.2.1",
"font-awesome": "^4.3.0",
"globby": "^2.0.0",
"gulp": "^3.8.11",
"gulp-angular-templatecache": "^1.6.0",
"gulp-autoprefixer": "^2.3.0",
"gulp-cached": "^1.1.0",
"gulp-changed": "^1.2.1",
"gulp-concat": "^2.5.2",
"gulp-inject": "^1.3.1",
"gulp-livereload": "^3.8.0",
"gulp-minify-css": "^1.1.1",
"gulp-minify-html": "^1.0.3",
"gulp-ng-annotate": "^0.5.3",
"gulp-notify": "^2.2.0",
"gulp-plumber": "^1.0.1",
"gulp-remember": "^0.3.0",
"gulp-rename": "^1.2.2",
"gulp-rev": "^4.0.0",
"gulp-stylus": "^2.0.3",
"gulp-template": "^3.0.0",
"gulp-uglify": "^1.2.0",
"marked": "^0.3.3",
"merge-stream": "^0.1.7",
"moment": "^2.10.3",
"node-notifier": "^4.2.1",
"robotjs": "^0.1.2",
"run-sequence": "^1.1.0",
"satellizer": "^0.10.1",
"streamqueue": "^1.1.0",
"ui-select": "^0.11.2"
},
"devDependencies": {
"gulp-concat": "^2.5.2",
"gulp-minify-html": "^1.0.3",
"streamqueue": "^1.1.0"
}
}

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -1,5 +1,6 @@
/* global angular */
angular.module('codexen', [
'codexen.shared',
'ngSanitize',
'ui.select',
'ui.ace',
@@ -8,4 +9,5 @@ angular.module('codexen', [
'satellizer',
'angular-md5',
'templates'])
.constant('appName', 'main')
angular.module('templates', [])

View File

@@ -1,6 +1,21 @@
/* global angular */
angular.module('codexen')
.config(function ($stateProvider, $urlRouterProvider) {
.config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
$httpProvider.interceptors.push(function ($q, $injector) {
return {
responseError: function (res) {
switch (res.status) {
case 401:
var $state = $injector.get('$state')
$state.go('auth.signin')
break
}
return $q.reject(res)
}
}
})
$urlRouterProvider
.when('/auth', '/auth/register')
.when('/auth/', '/auth/register')
@@ -71,4 +86,26 @@ angular.module('codexen')
}
})
/* Recipes */
.state('recipes', {
url: '/recipes',
views: {
'main-view': {
templateUrl: 'tpls/states/recipes.list.tpl.html',
controller: 'RecipesListController as vm'
}
},
resolve: {
myRecipes: function (Recipe) {
return Recipe.findMine().then(function (res) {
return res.data
})
}
}
})
.state('recipes.detail', {
url: '/:id',
templateUrl: 'tpls/states/recipes.detail.html',
controller: 'RecipesDetailController as vm'
})
})

View File

@@ -1,6 +1,6 @@
/* global angular */
angular.module('codexen')
.controller('SideNavController', function ($auth, User, $rootScope, $scope) {
.controller('SideNavController', function ($auth, User, $rootScope, $scope, Modal) {
var vm = this
vm.isAuthenticated = $auth.isAuthenticated()
@@ -16,11 +16,7 @@ angular.module('codexen')
reloadUser()
vm.signOut = function () {
$auth.logout()
.then(function () {
console.log('Sign Out')
$rootScope.$broadcast('userSignOut')
})
Modal.signOut()
}
$scope.$on('userSignIn', function () {
@@ -31,6 +27,5 @@ angular.module('codexen')
$scope.$on('userSignOut', function () {
vm.isAuthenticated = false
vm.currentUser = null
})
})

View File

@@ -0,0 +1,16 @@
/* global angular */
angular.module('codexen')
.controller('DeleteRecipeModalController', function ($modalInstance, Recipe, recipe) {
var vm = this
vm.submit = function () {
Recipe.delete(recipe.id)
.success(function (recipe) {
$modalInstance.close(recipe)
})
}
vm.cancel = function () {
$modalInstance.dismiss()
}
})

View File

@@ -0,0 +1,42 @@
/* global angular */
angular.module('codexen')
.controller('EditRecipeModalController', function (Recipe, Tag, $modalInstance, recipe) {
var vm = this
vm.recipe = recipe
vm.submit = function () {
var params = {
title: vm.recipe.title,
content: vm.recipe.content,
Tags: angular.isArray(vm.recipe.Tags) ? vm.recipe.Tags.map(function (tag) { return tag.name }) : []
}
Recipe.update(vm.recipe.id, params)
.success(function (data) {
$modalInstance.close(data)
})
}
// vm.tags = []
vm.tagCandidates = []
vm.refreshTagCandidates = function (tagName) {
if (tagName == null || tagName === '') return null
return Tag.findByName(tagName)
.success(function (data) {
console.log('tags fetched!!', data)
vm.tagCandidates = data
})
}
vm.transform = function (tagName) {
return {
id: 0,
name: tagName
}
}
vm.cancel = function () {
$modalInstance.dismiss()
}
})

View File

@@ -17,6 +17,7 @@ angular.module('codexen')
Snippet.update(vm.snippet.id, params)
.success(function (data) {
console.log('updated res :', data)
$rootScope.$broadcast('snippetUpdated', snippet)
$modalInstance.close(data)
})
}

View File

@@ -0,0 +1,23 @@
/* global angular */
angular.module('codexen')
.controller('ExpandRecipeModalController', function (recipe, $modalInstance, $scope, Modal) {
var vm = this
console.log(recipe)
vm.recipe = recipe
vm.cancel = function () {
$modalInstance.dismiss('cancel')
}
vm.insert = function (type) {
$scope.$broadcast('insertRequested', type)
}
vm.insertSnippet = function () {
Modal.selectSnippet()
.then(function (snippet) {
$scope.$broadcast('insertSnippetRequested', snippet)
})
}
})

View File

@@ -0,0 +1,42 @@
/* global angular */
angular.module('codexen')
.controller('NewRecipeModalController', function (Recipe, Tag, $modalInstance) {
var vm = this
vm.recipe = {}
vm.submit = function () {
var params = {
title: vm.recipe.title,
content: vm.recipe.content,
Tags: angular.isArray(vm.recipe.Tags) ? vm.recipe.Tags.map(function (tag) { return tag.name }) : []
}
Recipe.create(params)
.success(function (data) {
$modalInstance.close(data)
})
}
// vm.tags = []
vm.tagCandidates = []
vm.refreshTagCandidates = function (tagName) {
if (tagName == null || tagName === '') return null
return Tag.findByName(tagName)
.success(function (data) {
console.log('tags fetched!!', data)
vm.tagCandidates = data
})
}
vm.transform = function (tagName) {
return {
id: 0,
name: tagName
}
}
vm.cancel = function () {
$modalInstance.dismiss()
}
})

View File

@@ -1,6 +1,6 @@
/* global angular */
angular.module('codexen')
.controller('NewSnippetModalController', function ($modalInstance, aceModes, $log, Snippet, $rootScope, Tag) {
.controller('NewSnippetModalController', function ($modalInstance, aceModes, $log, Snippet, Tag) {
var vm = this
vm.aceModes = aceModes

View File

@@ -0,0 +1,18 @@
/* global angular */
angular.module('codexen')
.controller('SelectSnippetModalController', function (Snippet, $modalInstance) {
var vm = this
vm.select = function (snippet) {
$modalInstance.close(snippet)
}
vm.cancel = function () {
$modalInstance.dismiss('cancel')
}
Snippet.findMine()
.success(function (snippets) {
vm.snippets = snippets
})
})

View File

@@ -0,0 +1,13 @@
/* global angular */
angular.module('codexen')
.controller('SignOutModalController', function ($modalInstance) {
var vm = this
vm.submit = function () {
$modalInstance.close()
}
vm.cancel = function () {
$modalInstance.dismiss('cancel')
}
})

View File

@@ -3,13 +3,19 @@ angular.module('codexen')
.controller('AuthSignInController', function ($auth, $rootScope) {
var vm = this
vm.authFailed = false
vm.signIn = function () {
vm.authFailed = false
$auth.login({
email: vm.email,
password: vm.password
}).then(function (data) {
console.log(data)
$rootScope.$broadcast('userSignIn')
}, function (err) {
console.log(err)
vm.authFailed = true
})
}
})

View File

@@ -0,0 +1,32 @@
/* global angular */
angular.module('codexen')
.controller('RecipesDetailController', function (Recipe, $state, $rootScope, $scope, Modal) {
var vm = this
vm.isLoaded = false
var recipeId = $state.params.id
Recipe.show(recipeId)
.success(function (data) {
vm.recipe = data
vm.isLoaded = true
})
$scope.$on('taggingRequested', function (e) {
e.stopPropagation()
e.preventDefault()
Modal.editRecipe(angular.copy(vm.recipe))
.then(function (recipe) {
console.log('edited', recipe)
}, function () {
console.log('edit recipe modal dismissed')
})
})
$scope.$on('recipeUpdated', function (e, recipe) {
console.log('event received', recipe)
if (recipe.id === vm.recipe.id) vm.recipe = recipe
})
})

View File

@@ -0,0 +1,98 @@
/* global angular */
angular.module('codexen')
.controller('RecipesListController', function (Recipe, $state, $scope, $filter, myRecipes, User, $auth) {
var vm = this
vm.recipes = myRecipes
vm.searchRecipes = searchRecipes
vm.searchRecipes()
vm.isAuthenticated = $auth.isAuthenticated()
var reloadUser = function () {
if (vm.isAuthenticated) {
User.me().success(function (data) {
vm.currentUser = data
})
}
}
reloadUser()
$scope.$on('$stateChangeSuccess', function (e, toState, toParams) {
if (!toState.name.match(/recipes/)) return null
vm.recipeId = parseInt(toParams.id, 10)
if (!vm.recipeId && vm.filtered && vm.filtered[0]) {
$state.go('recipes.detail', {id: vm.filtered[0].id})
}
})
$scope.$on('recipeUpdated', function (e, recipe) {
if (!myRecipes.some(function (_recipe, index) {
if (_recipe.id === recipe.id) {
myRecipes[index] = recipe
return true
}
return false
})) myRecipes.unshift(recipe)
searchRecipes()
vm.recipeId = recipe.id
$state.go('recipes.detail', {id: recipe.id})
})
$scope.$on('recipeDeleted', function () {
if ($state.is('recipes.detail')) {
var currentRecipeId = parseInt($state.params.id, 10)
// Delete recipe from recipe list
for (var i = 0; i < vm.recipes.length; i++) {
if (vm.recipes[i].id === currentRecipeId) {
vm.recipes.splice(i, 1)
break
}
}
// Delete recipe from `filtered list`
// And redirect `next filtered recipe`
for (i = 0; i < vm.filtered.length; i++) {
if (vm.filtered[i].id === currentRecipeId) {
if (vm.filtered[i + 1] != null) $state.go('recipes.detail', {id: vm.filtered[i + 1].id})
else if (vm.filtered[i - 1] != null) $state.go('recipes.detail', {id: vm.filtered[i - 1].id})
else $state.go('recipes')
vm.filtered.splice(i, 1)
break
}
}
}
})
$scope.$on('tagSelected', function (e, tag) {
e.stopPropagation()
$scope.$apply(function () {
vm.search = '#' + tag.name
searchRecipes()
})
})
function loadRecipes () {
if ($auth.isAuthenticated) {
Recipe.findMine()
.success(function (data) {
vm.recipes = data
})
} else {
vm.recipes = void 0
}
}
function searchRecipes () {
vm.filtered = $filter('searchSnippets')(myRecipes, vm.search)
if (vm.search && vm.filtered && vm.filtered[0] && (!vm.recipeId || vm.recipeId !== vm.filtered[0].id)) {
$state.go('recipes.detail', {id: vm.filtered[0].id})
}
}
})

View File

@@ -17,11 +17,11 @@ angular.module('codexen')
e.stopPropagation()
e.preventDefault()
Modal.editSnippet(angular.copy(vm.snippet))
.result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
}, function () {
console.log('edit snippet modal dismissed')
})
.then(function (snippet) {
console.log('edited', snippet)
}, function () {
console.log('edit snippet modal dismissed')
})
})
$scope.$on('snippetUpdated', function (e, snippet) {

View File

@@ -1,10 +1,8 @@
/* global angular */
angular.module('codexen')
.controller('SnippetsListController', function ($auth, Snippet, $scope, $state, $scope, $filter, mySnippets, User) {
.controller('SnippetsListController', function ($auth, Snippet, $scope, $state, $filter, mySnippets, User) {
var vm = this
vm.isLoading = false
vm.snippetId = parseInt($state.params.id)
vm.snippets = mySnippets
@@ -33,14 +31,13 @@ angular.module('codexen')
$scope.$on('$stateChangeSuccess', function (e, toState, toParams) {
if (!toState.name.match(/snippets/)) return null
vm.snippetId = parseInt(toParams.id)
vm.snippetId = parseInt(toParams.id, 10)
if (!vm.snippetId && vm.filtered[0]) {
$state.go('snippets.detail', {id: vm.filtered[0].id})
}
})
$scope.$on('snippetUpdated', function (e, snippet) {
if (!mySnippets.some(function (_snippet, index) {
if (_snippet.id === snippet.id) {
@@ -57,7 +54,7 @@ angular.module('codexen')
$scope.$on('snippetDeleted', function () {
if ($state.is('snippets.detail')) {
var currentSnippetId = parseInt($state.params.id)
var currentSnippetId = parseInt($state.params.id, 10)
// Delete snippet from snippet list
for (var i = 0; i < vm.snippets.length; i++) {
if (vm.snippets[i].id === currentSnippetId) {
@@ -67,10 +64,10 @@ angular.module('codexen')
}
// Delete snippet from `filtered list`
// And redirect `next filtered snippet`
for (var i = 0; i < vm.filtered.length; i++) {
for (i = 0; i < vm.filtered.length; i++) {
if (vm.filtered[i].id === currentSnippetId) {
if (vm.filtered[i+1] != null) $state.go('snippets.detail', {id: vm.filtered[i+1].id})
else if (vm.filtered[i-1] != null) $state.go('snippets.detail', {id: vm.filtered[i-1].id})
if (vm.filtered[i + 1] != null) $state.go('snippets.detail', {id: vm.filtered[i + 1].id})
else if (vm.filtered[i - 1] != null) $state.go('snippets.detail', {id: vm.filtered[i - 1].id})
else $state.go('snippets')
vm.filtered.splice(i, 1)
@@ -100,7 +97,7 @@ angular.module('codexen')
}
}
function searchSnippets() {
function searchSnippets () {
vm.filtered = $filter('searchSnippets')(mySnippets, vm.search)
if (vm.search && vm.filtered[0] && (!vm.snippetId || vm.snippetId !== vm.filtered[0].id)) {
$state.go('snippets.detail', {id: vm.filtered[0].id})

View File

@@ -0,0 +1,19 @@
/* global angular */
angular.module('codexen')
.directive('btnDeleteRecipe', function (Modal, $rootScope) {
return {
scope: {
recipe: '=btnDeleteRecipe'
},
link: function (scope, el) {
el.on('click', function () {
Modal.deleteRecipe(scope.recipe)
.then(function (recipe) {
console.log('deleted', recipe)
}, function () {
console.log('delete snippet modal dismissed')
})
})
}
}
})

View File

@@ -8,8 +8,8 @@ angular.module('codexen')
link: function (scope, el) {
el.on('click', function () {
Modal.deleteSnippet(scope.snippet)
.result.then(function (snippet) {
$rootScope.$broadcast('snippetDeleted', snippet)
.then(function (snippet) {
console.log('deleted', snippet)
}, function () {
console.log('delete snippet modal dismissed')
})

View File

@@ -0,0 +1,14 @@
/* global angular */
angular.module('codexen')
.directive('btnEditRecipe', function (Modal) {
return {
scope: {
recipe: '=btnEditRecipe'
},
link: function (scope, el) {
el.on('click', function () {
Modal.editRecipe(angular.copy(scope.recipe))
})
}
}
})

View File

@@ -1,6 +1,6 @@
/* global angular */
angular.module('codexen')
.directive('btnEditSnippet', function (Modal, $rootScope) {
.directive('btnEditSnippet', function (Modal) {
return {
scope: {
snippet: '=btnEditSnippet'
@@ -8,11 +8,6 @@ angular.module('codexen')
link: function (scope, el) {
el.on('click', function () {
Modal.editSnippet(angular.copy(scope.snippet))
.result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
}, function () {
console.log('edit snippet modal dismissed')
})
})
}
}

View File

@@ -0,0 +1,15 @@
/* global angular */
angular.module('codexen')
.directive('btnExpandRecipe', function (Modal) {
return {
restrict: 'A',
scope: {
recipe: '=btnExpandRecipe'
},
link: function (scope, el) {
el.on('click', function () {
Modal.expandRecipe(scope.recipe)
})
}
}
})

View File

@@ -0,0 +1,12 @@
/* global angular */
angular.module('codexen')
.directive('btnNewRecipe', function (Modal) {
return {
restrict: 'A',
link: function (scope, el) {
el.on('click', function () {
Modal.newRecipe()
})
}
}
})

View File

@@ -5,11 +5,6 @@ angular.module('codexen')
link: function (scope, el) {
el.on('click', function () {
Modal.newSnippet()
.result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
}, function () {
console.log('new snippet modal dismissed')
})
})
}
}

View File

@@ -0,0 +1,19 @@
/* global angular */
angular.module('codexen')
.directive('recipeItem', function (Modal, $rootScope) {
return {
restrict: 'A',
transclude: true,
template: '<div ng-transclude></div>',
scope: {
recipe: '=recipeItem'
},
link: function (scope, elem) {
scope.$on('taggingRequested', function (e) {
e.stopPropagation()
e.preventDefault()
Modal.editRecipe(angular.copy(scope.recipe))
})
}
}
})

View File

@@ -13,11 +13,6 @@ angular.module('codexen')
e.stopPropagation()
e.preventDefault()
Modal.editSnippet(angular.copy(scope.snippet))
.result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
}, function () {
console.log('edit snippet modal dismissed')
})
})
}
}

View File

@@ -0,0 +1,19 @@
/* global angular marked*/
angular.module('codexen')
.filter('marked', function () {
marked.setOptions({
renderer: new marked.Renderer(),
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: false
})
return function (input) {
if (!angular.isString(input)) input = ''
return marked(input)
}
})

View File

@@ -0,0 +1,90 @@
<!DOCTYPE html>
<html ng-app="codexen">
<head>
<title>
CodeXen App
</title>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<meta name="description" content="CodeXen - Short code storage service">
<title>Codexen!</title>
<link rel="stylesheet" href="../vendor/css/font-awesome.css" media="screen" title="no title" charset="utf-8">
<!-- inject:css -->
<link rel="stylesheet" href="styles/app.css">
<link rel="stylesheet" href="../shared/styles/bootstrap.css">
<!-- endinject -->
</head>
<body ng-controller="AppController as app">
<div side-nav id="side-view"></div>
<div ui-view name="main-view" id="main-view"></div>
<script src="../vendor/ace.js"></script>
<script src="../vendor/angular.js"></script>
<script src="../vendor/angular-sanitize.js"></script>
<script src="../vendor/angular-ui-router.js"></script>
<script src="../vendor/ui-bootstrap-tpls.js"></script>
<script src="../vendor/select.js"></script>
<script src="../vendor/satellizer.js"></script>
<script src="../vendor/angular-md5.js"></script>
<script src="../vendor/moment.js"></script>
<script src="../vendor/marked.js"></script>
<script src="../vendor/hotkeys.js" charset="utf-8"></script>
<!-- inject:js -->
<script src="app.js"></script>
<script src="config/states.js"></script>
<script src="controllers/AppController.js"></script>
<script src="directives/btn-delete-recipe.js"></script>
<script src="directives/btn-delete-snippet.js"></script>
<script src="directives/btn-edit-recipe.js"></script>
<script src="directives/btn-edit-snippet.js"></script>
<script src="directives/btn-expand-recipe.js"></script>
<script src="directives/btn-new-recipe.js"></script>
<script src="directives/btn-new-snippet.js"></script>
<script src="directives/recipe-item.js"></script>
<script src="directives/side-nav.js"></script>
<script src="directives/snippet-item.js"></script>
<script src="directives/tag-item.js"></script>
<script src="directives/tag-list.js"></script>
<script src="filters/from-now.js"></script>
<script src="filters/marked.js"></script>
<script src="filters/search-snippets.js"></script>
<script src="services/Modal.js"></script>
<script src="services/Recipe.js"></script>
<script src="services/Settings.js"></script>
<script src="services/Tag.js"></script>
<script src="services/User.js"></script>
<script src="controllers/directives/SideNavController.js"></script>
<script src="controllers/states/AuthRegisterController.js"></script>
<script src="controllers/states/AuthSignInController.js"></script>
<script src="controllers/states/HomeController.js"></script>
<script src="controllers/states/RecipesDetailController.js"></script>
<script src="controllers/states/RecipesListController.js"></script>
<script src="controllers/states/SettingsController.js"></script>
<script src="controllers/states/SnippetsDetailController.js"></script>
<script src="controllers/states/SnippetsListController.js"></script>
<script src="controllers/modals/DeleteRecipeModalController.js"></script>
<script src="controllers/modals/DeleteSnippetModalController.js"></script>
<script src="controllers/modals/EditRecipeModalController.js"></script>
<script src="controllers/modals/EditSnippetModalController.js"></script>
<script src="controllers/modals/ExpandRecipeModalController.js"></script>
<script src="controllers/modals/NewRecipeModalController.js"></script>
<script src="controllers/modals/NewSnippetModalController.js"></script>
<script src="controllers/modals/SelectSnippetModalController.js"></script>
<script src="controllers/modals/SignOutModalController.js"></script>
<script src="../shared/shared.js"></script>
<script src="../shared/config/ace.js"></script>
<script src="../shared/config/env.js"></script>
<script src="../shared/config/satellizer.js"></script>
<script src="../shared/directives/ui-ace.js"></script>
<script src="../shared/services/Snippet.js"></script>
<!-- endinject -->
</body>
</html>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html ng-app="codexen">
<head>
<title>
CodeXen App
</title>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<meta name="description" content="CodeXen - Short code storage service">
<title>Codexen!</title>
<link rel="stylesheet" href="../vendor/css/font-awesome.css" media="screen" title="no title" charset="utf-8">
<!-- inject:css -->
<!-- endinject -->
</head>
<body ng-controller="AppController as app">
<div side-nav id="side-view"></div>
<div ui-view name="main-view" id="main-view"></div>
<script src="../vendor/ace.js"></script>
<script src="../vendor/angular.js"></script>
<script src="../vendor/angular-sanitize.js"></script>
<script src="../vendor/angular-ui-router.js"></script>
<script src="../vendor/ui-bootstrap-tpls.js"></script>
<script src="../vendor/select.js"></script>
<script src="../vendor/satellizer.js"></script>
<script src="../vendor/angular-md5.js"></script>
<script src="../vendor/moment.js"></script>
<script src="../vendor/marked.js"></script>
<script src="../vendor/hotkeys.js" charset="utf-8"></script>
<!-- inject:js -->
<!-- endinject -->
</body>
</html>

View File

@@ -0,0 +1,124 @@
/* global angular */
angular.module('codexen')
.factory('Modal', function ($modal, $rootScope, $auth) {
var signOut = function () {
return $modal.open({
templateUrl: 'tpls/modals/sign-out-modal.html',
controller: 'SignOutModalController as vm'
}).result.then(function () {
$auth.logout()
.then(function () {
console.log('Sign Out')
$rootScope.$broadcast('userSignOut')
})
})
}
/* Recipe */
var newRecipe = function () {
return $modal.open({
templateUrl: 'tpls/modals/new-recipe-modal.html',
controller: 'NewRecipeModalController as vm'
}).result.then(function (recipe) {
$rootScope.$broadcast('recipeUpdated', recipe)
})
}
var editRecipe = function (recipe) {
return $modal.open({
resolve: {
recipe: function () {
return recipe
}
},
templateUrl: 'tpls/modals/edit-recipe-modal.html',
controller: 'EditRecipeModalController as vm'
}).result.then(function (recipe) {
$rootScope.$broadcast('recipeUpdated', recipe)
})
}
var expandRecipe = function (recipe) {
return $modal.open({
size: 'lg',
resolve: {
recipe: function () {
return recipe
}
},
templateUrl: 'tpls/modals/expand-recipe-modal.html',
controller: 'ExpandRecipeModalController as vm'
})
}
var deleteRecipe = function (recipe) {
return $modal.open({
resolve: {
recipe: function () {
return recipe
}
},
templateUrl: 'tpls/modals/delete-recipe-modal.html',
controller: 'DeleteRecipeModalController as vm'
}).result.then(function (recipe) {
$rootScope.$broadcast('recipeDeleted', recipe)
})
}
/* Snippet */
var newSnippet = function () {
return $modal.open({
templateUrl: 'tpls/modals/new-snippet-modal.tpl.html',
controller: 'NewSnippetModalController as vm'
}).result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
})
}
var editSnippet = function (snippet) {
return $modal.open({
resolve: {
snippet: function () {
return snippet
}
},
templateUrl: 'tpls/modals/edit-snippet-modal.tpl.html',
controller: 'EditSnippetModalController as vm'
}).result.then(function (snippet) {
$rootScope.$broadcast('snippetUpdated', snippet)
})
}
var deleteSnippet = function (snippet) {
return $modal.open({
resolve: {
snippet: function () {
return snippet
}
},
templateUrl: 'tpls/modals/delete-snippet-modal.tpl.html',
controller: 'DeleteSnippetModalController as vm'
}).result.then(function (snippet) {
$rootScope.$broadcast('snippetDeleted', snippet)
})
}
var selectSnippet = function (snippet) {
return $modal.open({
templateUrl: 'tpls/modals/select-snippet-modal.html',
controller: 'SelectSnippetModalController as vm'
}).result
}
return {
signOut: signOut,
newRecipe: newRecipe,
editRecipe: editRecipe,
deleteRecipe: deleteRecipe,
expandRecipe: expandRecipe,
newSnippet: newSnippet,
editSnippet: editSnippet,
deleteSnippet: deleteSnippet,
selectSnippet: selectSnippet
}
})

View File

@@ -0,0 +1,52 @@
/* global angular */
angular.module('codexen')
.factory('Recipe', function ($http, $auth, apiUrl) {
var findByUser = function (user) {
var url = apiUrl + 'blueprints/search'
return $http.get(url, {
params: {
user: user
}
})
}
var findMine = function (params) {
var url = apiUrl + 'blueprints/my'
return $http.get(url, {params: params})
}
var create = function (params) {
var url = apiUrl + 'blueprints/create'
return $http.post(url, params)
}
var show = function (id, params) {
var url = apiUrl + 'blueprints/id/' + id
return $http.get(url, {params: params})
}
var update = function (id, params) {
var url = apiUrl + 'blueprints/id/' + id
return $http.put(url, params)
}
var destroy = function (id) {
var url = apiUrl + 'blueprints/id/' + id
return $http.delete(url)
}
return {
findByUser: findByUser,
findMine: findMine,
create: create,
show: show,
delete: destroy,
update: update
}
})

View File

@@ -0,0 +1,543 @@
.expand-recipe-modal .expand-editor .editor-pane {
height: 500px;
}
.expand-recipe-modal .expand-editor .editor-pane .ace_editor {
height: 500px;
}
.expand-recipe-modal .expand-editor .preview-pane {
height: 500px;
overflow-y: auto;
}
.new-snippet-modal .ace_editor {
height: 200px;
}
.select-snippet-modal .snippet-list {
list-style: none;
padding: 0;
}
.select-snippet-modal .snippet-list li {
padding: 10px;
border: solid 1px #001a20;
background-color: #003b4a;
border-radius: 5px;
margin-bottom: 5px;
cursor: pointer;
}
.select-snippet-modal .snippet-list li:hover {
background-color: #004b5f;
}
.select-snippet-modal .snippet-list li .ace_editor {
height: 150px;
}
.select-snippet-modal .snippet-list li .call-sign {
color: #d5dfe2;
}
#side-view .nav-control-group {
margin: auto 10px;
}
#side-view .new-block {
margin: 20px auto;
}
#side-view .new-block button {
padding: 10px inherit;
}
#side-view .new-block button:nth-child(1) {
width: 147px;
padding-left: 15px;
text-align: left;
}
#side-view .new-block button:nth-child(2) {
width: 33px;
}
#side-view .new-block .success-menu {
background-color: #167b59;
}
#side-view .new-block .success-menu a {
padding: 5px 15px;
color: #fff;
}
#side-view .new-block .success-menu a.hover,
#side-view .new-block .success-menu a:hover {
background-color: #22bd89;
}
#side-view .new-block .success-menu a.focus,
#side-view .new-block .success-menu a:focus {
background-color: #20b482;
}
#side-view ul.nav.nav-pills {
margin-top: 10px;
}
#side-view ul.nav.nav-pills li a {
padding: 12px 15px;
margin-bottom: 7px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
-webkit-transition: 0.2s;
transition: 0.2s;
}
#side-view ul.nav.nav-pills li.active > a,
#side-view ul.nav.nav-pills .nav-pills > li.active > a:hover,
#side-view ul.nav.nav-pills .nav-pills > li.active > a:focus {
background-color: #004b5f;
}
/*
* ui-select
* http://github.com/angular-ui/ui-select
* Version: 0.11.2 - 2015-03-17T04:08:46.478Z
* License: MIT
*/
.ui-select-highlight {
font-weight: bold;
}
.ui-select-offscreen {
clip: rect(0 0 0 0) !important;
width: 1px !important;
height: 1px !important;
border: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
position: absolute !important;
outline: 0 !important;
left: 0px !important;
top: 0px !important;
}
.ng-dirty.ng-invalid > a.select2-choice {
border-color: #d44950;
}
.select2-result-single {
padding-left: 0;
}
.select2-locked > .select2-search-choice-close {
display: none;
}
.select-locked > .ui-select-match-close {
display: none;
}
body > .select2-container.open {
z-index: 9999;
}
.selectize-input.selectize-focus {
border-color: #007fbb !important;
}
.selectize-control > .selectize-input > input {
width: 100%;
}
.selectize-control > .selectize-dropdown {
width: 100%;
}
.ng-dirty.ng-invalid > div.selectize-input {
border-color: #d44950;
}
.btn-default-focus {
color: #333;
background-color: #ebebeb;
border-color: #adadad;
text-decoration: none;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075), 0 0 8px rgba(102,175,233,0.6);
}
.ui-select-bootstrap .ui-select-toggle {
position: relative;
border-radius: $input-border-radius;
}
.ui-select-bootstrap .ui-select-toggle .ui-select-placeholder {
color: #99b2b8;
}
.ui-select-bootstrap .ui-select-toggle > .caret {
position: absolute;
height: 10px;
top: 50%;
right: 10px;
margin-top: -2px;
}
.input-group > .ui-select-bootstrap.dropdown {
/* Instead of relative */
position: static;
}
.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
border-radius: $input-border-radius;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.ui-select-bootstrap > .ui-select-match > .btn {
/* Instead of center because of .btn */
text-align: left !important;
padding-right: 25px;
border-radius: $input-border-radius;
border: solid 1px #001a20;
}
.ui-select-bootstrap > .ui-select-match > .caret {
position: absolute;
top: 45%;
right: 15px;
}
.ui-select-bootstrap > .ui-select-choices {
width: 100%;
height: auto;
max-height: 200px;
overflow-x: hidden;
margin-top: -1px;
}
body > .ui-select-bootstrap.open {
z-index: 1000;
}
.ui-select-multiple.ui-select-bootstrap {
height: auto;
padding: 3px 3px 0 10px;
}
.ui-select-multiple.ui-select-bootstrap.open {
border-color: #52dcff;
outline: 0;
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075), 0 0 8px rgba(82,220,255,0.6);
}
.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
background-color: transparent !important;
border: none;
outline: none;
height: 1.666666em;
margin-bottom: 3px;
}
.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
font-size: 1.6em;
line-height: 0.75;
}
.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
outline: 0;
margin: 0 3px 3px 0;
}
.ui-select-multiple .ui-select-match-item {
position: relative;
}
.ui-select-multiple .ui-select-match-item.dropping-before:before {
content: "";
position: absolute;
top: 0;
right: 100%;
height: 100%;
margin-right: 2px;
border-left: 1px solid #428bca;
}
.ui-select-multiple .ui-select-match-item.dropping-after:after {
content: "";
position: absolute;
top: 0;
left: 100%;
height: 100%;
margin-left: 2px;
border-right: 1px solid #428bca;
}
.ui-select-bootstrap .ui-select-choices-row>a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: 400;
line-height: 1.42857143;
color: #99b2b8;
white-space: nowrap;
}
.ui-select-bootstrap .ui-select-choices-row>a:hover,
.ui-select-bootstrap .ui-select-choices-row>a:focus {
text-decoration: none;
color: #fff;
background-color: #004b5f;
}
.ui-select-bootstrap .ui-select-choices-row.active>a {
color: #fff;
text-decoration: none;
outline: 0;
background-color: #004b5f;
}
.ui-select-bootstrap .ui-select-choices-row.disabled>a,
.ui-select-bootstrap .ui-select-choices-row.active.disabled>a {
color: #777;
cursor: not-allowed;
background-color: #fff;
}
.ui-select-match.ng-hide-add,
.ui-select-search.ng-hide-add {
display: none !important;
}
.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
border-color: #d44950;
}
.auth-state .panel {
margin-top: 50px;
}
.auth-state h1 {
margin: 15px 0;
}
.auth-state .auth-control {
margin: 10px 0;
}
.home-state {
padding: 10px;
}
.home-state p {
margin: 5px auto 15px;
}
.home-state ol {
margin: 35px auto;
}
.home-state li {
margin-bottom: 25px;
}
.settings-state .panel {
margin-top: 15px;
}
.settings-state h1 {
margin: 30px 0;
}
.settings-state .section h4 {
margin-bottom: 15px;
}
.snippets-list-state {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.snippets-list-state .left-pane {
border-right: 1px solid #001a20;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 275px;
overflow: hidden;
}
.snippets-list-state .left-pane .snippet-search {
position: absolute;
top: 0;
height: 50px;
left: 0;
right: 0;
border-right: 1px solid #001a20;
padding: 7px 5px;
}
.snippets-list-state .left-pane .snippet-list {
position: absolute;
top: 50px;
bottom: 0;
left: 0;
right: 0;
overflow-x: hidden;
overflow-y: auto;
list-style: none;
padding: 0;
}
.snippets-list-state .left-pane .snippet-list li {
cursor: pointer;
padding: 5px;
border-right: 1px solid #001a20;
border-bottom: 1px solid #001a20;
}
.snippets-list-state .left-pane .snippet-list li:nth-child(even) {
background-color: #002b36;
}
.snippets-list-state .left-pane .snippet-list li:nth-child(odd) {
background-color: #00323f;
}
.snippets-list-state .left-pane .snippet-list li h4 {
margin: 0;
}
.snippets-list-state .left-pane .snippet-list li:hover {
background-color: #004b5f;
}
.snippets-list-state .left-pane .snippet-list li p {
margin: 0;
}
.snippets-list-state .left-pane .snippet-list li p.call-sign {
font-size: 0.8em;
}
.snippets-list-state .left-pane .snippet-list li p.created-at {
font-size: 0.8em;
opacity: 0.8;
}
.snippets-list-state .left-pane .snippet-list li.active {
color: #fff;
background-color: #088cff;
}
.snippets-list-state .left-pane .snippet-list li.active a {
color: #fff;
}
.snippets-list-state .right-pane {
position: absolute;
top: 0;
bottom: 0;
left: 275px;
right: 0;
overflow-x: hidden;
overflow-y: auto;
background-color: #00323f;
}
.snippets-detail-state {
position: absolute;
top: 0;
width: 100%;
bottom: 0;
overflow: hidden;
}
.snippets-detail-state .detail-header {
position: absolute;
top: 0;
width: 100%;
background-color: #003d4d;
padding: 5px 10px;
height: 50px;
border-bottom: solid 1px #001a20;
}
.snippets-detail-state .detail-header .detail-header-title {
color: #d5dfe2;
line-height: 40px;
font-size: 1.2em;
}
.snippets-detail-state .detail-header .detail-header-title small {
font-size: 0.6em;
color: #99b2b8;
}
.snippets-detail-state .detail-header .detail-header-control {
padding: 3px;
}
.snippets-detail-state .detail-body {
position: absolute;
top: 50px;
width: 100%;
bottom: 0;
padding: 5px 10px;
overflow-y: auto;
}
.snippets-detail-state .detail-body .ace_editor {
min-height: 300px;
border: solid 1px $border-color;
border-radius: 5px;
margin-bottom: 5px;
}
.tags {
word-break: break-all;
}
.tags a {
margin: 0 2px;
}
#side-view {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 200px;
background-color: #002b36;
border-right: solid 2px #004b5f;
box-sizing: border-box;
padding: 10px 0 10px 10px;
}
#main-view {
position: absolute;
top: 0;
bottom: 0;
left: 200px;
right: 0;
overflow-x: hidden;
overflow-y: auto;
background-color: $bgDarker;
}
.marked h1,
.marked h2,
.marked h3,
.marked h4,
.marked h5 {
margin: 0.75em 0;
}
.marked h1:nth-child(1),
.marked h2:nth-child(1),
.marked h3:nth-child(1),
.marked h4:nth-child(1),
.marked h5:nth-child(1) {
margin-top: 0;
}
.marked code {
background-color: #003644;
color: #fff;
border: 1px solid #001a20;
border-radius: 5px;
box-shadow: 0 1px 1px rgba(0,0,0,0.05);
padding: 5px;
line-height: 200%;
}
.marked pre {
margin-bottom: 10px;
background-color: #003644;
color: #fff;
border: 1px solid #001a20;
border-radius: 5px;
box-shadow: 0 1px 1px rgba(0,0,0,0.05);
padding: 5px;
}
.marked pre >code {
background-color: transparent;
color: inherit;
border: none;
border-radius: 0;
box-shadow: none;
padding: 0;
line-height: inherit;
}
.marked blockquote {
font-size: 1em;
border-left: 5px solid #6494ed;
}
.marked a {
text-decoration: underline;
color: #6494ed;
}
.marked table {
width: 100%;
max-width: 100%;
margin-bottom: $line-height-computed;
border: 1px solid #001a20;
margin-bottom: 10px;
}
.marked table > thead > tr > th,
.marked table > tbody > tr > th,
.marked table > tfoot > tr > th,
.marked table > thead > tr > td,
.marked table > tbody > tr > td,
.marked table > tfoot > tr > td {
padding: 10px;
line-height: $line-height-base;
vertical-align: top;
border-top: 1px solid #001a20;
border-right: 1px solid #001a20;
}
.marked table > thead > tr > th:nth-last-child(1),
.marked table > tbody > tr > th:nth-last-child(1),
.marked table > tfoot > tr > th:nth-last-child(1),
.marked table > thead > tr > td:nth-last-child(1),
.marked table > tbody > tr > td:nth-last-child(1),
.marked table > tfoot > tr > td:nth-last-child(1) {
border-right: none;
}
.marked table > thead > tr > th {
vertical-align: bottom;
border-bottom: 2px solid #001a20;
}
.marked table > caption + thead,
.marked table > colgroup + thead,
.marked table > thead:first-child {
background-color: #004b5f;
}
.marked table > caption + thead > tr:first-child > th,
.marked table > colgroup + thead > tr:first-child > th,
.marked table > thead:first-child > tr:first-child > th,
.marked table > caption + thead > tr:first-child > td,
.marked table > colgroup + thead > tr:first-child > td,
.marked table > thead:first-child > tr:first-child > td {
border-top: 0;
}
.marked table > tbody >tr:nth-child(odd) {
background-color: #002b36;
}
.marked table > tbody >tr:nth-child(even) {
background-color: #003644;
}

View File

@@ -0,0 +1,101 @@
@import '../../shared/styles/_vars'
@import '../../shared/styles/mixins/*'
@import 'modals/*'
@import 'directives/*'
@import 'states/*'
#side-view
position:absolute
top: 0
bottom: 0
left: 0
width: 200px
background-color: $baseBackgroundColor
border-right solid 2px $backgroundColorSelected
box-sizing: border-box
padding: 10px 0 10px 10px
#main-view
position:absolute
top: 0
bottom: 0
left: 200px
right: 0
overflow-x: hidden
overflow-y: auto
background-color $bgDarker
.marked
h1, h2, h3, h4, h5
margin 0.75em 0
&:nth-child(1)
margin-top 0
code
background-color lighten($baseBackgroundColor, 3%)
color $textColorSelected
border 1px solid $baseBorderColor
border-radius 5px
box-shadow 0 1px 1px rgba(0, 0, 0, .05)
padding 5px
line-height 200%
pre
margin-bottom 10px
background-color lighten($baseBackgroundColor, 3%)
color $textColorSelected
border 1px solid $baseBorderColor
border-radius 5px
box-shadow 0 1px 1px rgba(0, 0, 0, .05)
padding 5px
>code
background-color transparent
color inherit
border none
border-radius 0
box-shadow none
padding 0
line-height inherit
blockquote
font-size 1em
border-left 5px solid $textColorInfo
a
text-decoration underline
color $textColorInfo
table
width 100%
max-width 100%
margin-bottom $line-height-computed
border 1px solid $table-border-color
margin-bottom 10px
// Cells
> thead,
> tbody,
> tfoot
> tr
> th,
> td
padding 10px
line-height $line-height-base
vertical-align top
border-top 1px solid $table-border-color
border-right 1px solid $table-border-color
&:nth-last-child(1)
border-right none
> thead > tr > th
vertical-align bottom
border-bottom 2px solid $table-border-color
> caption + thead,
> colgroup + thead,
> thead:first-child
background-color $backgroundColorSelected
> tr:first-child
> th,
> td
border-top 0
> tbody
>tr
&:nth-child(odd)
background-color $baseBackgroundColor
&:nth-child(even)
background-color lighten($baseBackgroundColor, 3%)

View File

@@ -0,0 +1,34 @@
#side-view
.nav-control-group
margin auto 10px
.new-block
margin 20px auto
button
padding 10px inherit
button:nth-child(1)
width 147px
padding-left 15px
text-align left
button:nth-child(2)
width 33px
.success-menu
background-color darken($brand-success, 35%)
a
padding 5px 15px
color $textColorSelected
&.hover, &:hover
background-color $brand-success
&.focus, &:focus
background-color darken($brand-success, 5%)
ul.nav.nav-pills
margin-top 10px
li a
padding 12px 15px
margin-bottom 7px
border-top-right-radius 0
border-bottom-right-radius 0
transition 0.2s
li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus{
background-color: $backgroundColorSelected
}

View File

@@ -0,0 +1,9 @@
.expand-recipe-modal
.expand-editor
.editor-pane
height 500px
.ace_editor
height 500px
.preview-pane
height 500px
overflow-y auto

View File

@@ -0,0 +1,17 @@
.select-snippet-modal
.snippet-list
list-style none
padding 0
li
padding 10px
border solid 1px $baseBorderColor
background-color $backgroundColorHighlight
border-radius 5px
margin-bottom 5px
cursor pointer
&:hover
background-color $backgroundColorSelected
.ace_editor
height 150px
.call-sign
color $textColorHighlight

View File

@@ -0,0 +1,8 @@
.home-state
padding 10px
p
margin 5px auto 15px
ol
margin 35px auto
li
margin-bottom 25px

View File

@@ -3,7 +3,7 @@
<img width="30" class="img-circle" ng-src="http://www.gravatar.com/avatar/{{ vm.currentUser.email | gravatar }}">
<a href ng-bind="vm.currentUser.name"></a>
<span class="nav-control-group pull-right">
<a ui-sref="settings" class="btn btn-sm btn-default" ui-sref-active="active"}"><i class="fa fa-gears fa-fw"></i></a>
<a ui-sref="settings" class="btn btn-sm btn-default" ui-sref-active="active"><i class="fa fa-gears fa-fw"></i></a>
<a href class="btn btn-sm btn-default" ng-click="vm.signOut()"><i class="fa fa-sign-out fa-fw"></i></a>
</span>
@@ -19,17 +19,27 @@
</div>
</div>
<div class="new-block">
<div class="btn-group" dropdown>
<button ng-disabled="!vm.isAuthenticated" btn-new-snippet type="button" class="btn btn-success"><i class="fa fa-plus-square-o fa-fw"></i> New Snippet</button>
<button ng-disabled="!vm.isAuthenticated" type="button" class="btn btn-success dropdown-toggle" dropdown-toggle>
<span class="caret"></span>
<span class="sr-only">Split button!</span>
</button>
<ul class="dropdown-menu success-menu" role="menu">
<li><a href btn-new-recipe><i class="fa fa-bookmark-o fa-fw"></i> New Recipe</a></li>
</ul>
</div>
</div>
<ul class="nav nav-pills nav-stacked">
<li>
<a btn-new-snippet href="#"><i class="fa fa-plus-square-o"></i> New Snippet</a>
</li>
<li class="divider"><hr></li>
<li>
<li ui-sref-active="active">
<a ui-sref="home"><i class="fa fa-home fa-fw"></i> Home</a>
</li>
<li ui-sref-active="active">
<a ui-sref="home"><i class="fa fa-home"></i> Home</a>
<a ui-sref="snippets"><i class="fa fa-code fa-fw"></i> Snippets</a>
</li>
<li ui-sref-active="active">
<a ui-sref="snippets"><i class="fa fa-code"></i> Snippets</a>
<a ui-sref="recipes"><i class="fa fa-bookmark-o fa-fw"></i> Recipes</a>
</li>
</ul>

View File

@@ -0,0 +1,14 @@
<div
ui-ace="{
showGutter: false,
useWrapMode : true,
mode:snippet.mode.toLowerCase(),
maxLines: -1,
theme:'solarized_dark',
rendererOptions: {
maxLinks: Infinity
}
}"
readonly
ng-model="snippet.content"
></div>

View File

@@ -0,0 +1,19 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>Delete Recipe</h4>
</div>
<div class="modal-body">
<p>
Are you sure to delete it?
</p>
<blockquote>
Snippets of this recipe will not be removed.
</blockquote>
</div>
<div class="modal-footer">
<button ng-click="vm.submit()" type="button" name="button" class="btn btn-danger">Delete It</button>
<button ng-click="vm.cancel()" type="button" name="button" class="btn btn-default">Cancel</button>
</div>
</div>

View File

@@ -0,0 +1,60 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>New Recipe</h4>
</div>
<div class="modal-body">
<div class="form-group">
<input ng-model="vm.recipe.title" type="text" class="form-control" placeholder="Title">
</div>
<tabset>
<tab>
<tab-heading>
<i class="glyphicon glyphicon-bell"></i> Markdown
</tab-heading>
<div class="form-group">
<div
ui-ace="{
mode: 'Markdown',
theme: 'solarized_dark',
useWrapMode: true
}"
ng-model="vm.recipe.content"
></div>
</div>
</tab>
<tab>
<tab-heading>
<i class=""></i> Preview
</tab-heading>
<div class="panel panel-default">
<div class="panel-body">
<div ng-bind-html="vm.recipe.content | marked" class="marked"></div>
</div>
</div>
</tab>
</tabset>
<div class="form-group">
<button btn-expand-recipe="vm.recipe" class="btn btn-default">Expand Editor</button>
</div>
<div class="form-group">
<ui-select multiple tagging="vm.transform" tagging-tokens="SPACE|,|/" ng-model="vm.recipe.Tags" theme="bootstrap">
<ui-select-match placeholder="Tags...">{{$item.name}}</ui-select-match>
<ui-select-choices repeat="tag in vm.tagCandidates" refresh="vm.refreshTagCandidates($select.search)"
refresh-delay="100">
<div><span ng-bind-html="tag.name | highlight: $select.search"></span><span ng-if="tag.isTag">(new)</span></div>
</ui-select-choices>
</ui-select>
</div>
</div>
<div class="modal-footer">
<button ng-click="vm.submit()" type="button" name="button" class="btn btn-primary">Submit</button>
<button ng-click="vm.cancel()" type="button" name="button" class="btn btn-default">Cancel</button>
</div>
</div>

View File

@@ -0,0 +1,37 @@
<div class="expand-recipe-modal">
<div class="modal-header">
<button ng-click="vm.insert('h1')" class="btn btn-default"><i class="fa fa-header fa-fw"></i></button>
<button ng-click="vm.insert('ul')" class="btn btn-default"><i class="fa fa-list-ul fa-fw"></i></button>
<button ng-click="vm.insert('ol')" class="btn btn-default"><i class="fa fa-list-ol fa-fw"></i></button>
<button ng-click="vm.insert('a')" class="btn btn-default"><i class="fa fa-link fa-fw"></i></button>
<button ng-click="vm.insert('table')" class="btn btn-default"><i class="fa fa-table fa-fw"></i></button>
<button ng-click="vm.insertSnippet()" class="btn btn-default">Insert Snippet</button>
</div>
<div class="modal-body">
<div class="container-fluid expand-editor">
<div class="row">
<div class="col-xs-6 editor-pane">
<div
ui-ace="{
mode: 'Markdown',
theme: 'solarized_dark',
useWrapMode: true
}"
ng-model="vm.recipe.content"
></div>
</div>
<div class="col-xs-6">
<div class="panel panel-default preview-pane">
<div class="panel-body">
<div ng-bind-html="vm.recipe.content | marked" class="marked"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="vm.cancel()">Close</button>
</div>
</div>

View File

@@ -0,0 +1,60 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>New Recipe</h4>
</div>
<div class="modal-body">
<div class="form-group">
<input ng-model="vm.recipe.title" type="text" class="form-control" placeholder="Title">
</div>
<tabset>
<tab>
<tab-heading>
<i class="glyphicon glyphicon-bell"></i> Markdown
</tab-heading>
<div class="form-group">
<div
ui-ace="{
mode: 'Markdown',
theme: 'solarized_dark',
useWrapMode: true
}"
ng-model="vm.recipe.content"
></div>
</div>
</tab>
<tab>
<tab-heading>
<i class=""></i> Preview
</tab-heading>
<div class="panel panel-default">
<div class="panel-body">
<div ng-bind-html="vm.recipe.content | marked" class="marked"></div>
</div>
</div>
</tab>
</tabset>
<div class="form-group">
<button btn-expand-recipe="vm.recipe" class="btn btn-default">Expand Editor</button>
</div>
<div class="form-group">
<ui-select multiple tagging="vm.transform" tagging-tokens="SPACE|,|/" ng-model="vm.recipe.Tags" theme="bootstrap">
<ui-select-match placeholder="Tags...">{{$item.name}}</ui-select-match>
<ui-select-choices repeat="tag in vm.tagCandidates" refresh="vm.refreshTagCandidates($select.search)"
refresh-delay="100">
<div><span ng-bind-html="tag.name | highlight: $select.search"></span><span ng-if="tag.isTag">(new)</span></div>
</ui-select-choices>
</ui-select>
</div>
</div>
<div class="modal-footer">
<button ng-click="vm.submit()" type="button" name="button" class="btn btn-primary">Submit</button>
<button ng-click="vm.cancel()" type="button" name="button" class="btn btn-default">Cancel</button>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<div class="select-snippet-modal">
<div class="modal-header">
Select a snippet
</div>
<div class="modal-body">
<ul class="snippet-list">
<li ng-repeat="snippet in vm.snippets" ng-click="vm.select(snippet)">
<p><small>callsign</small> <span ng-bind="snippet.callSign"></span> <small ng-bind="snippet.updatedAt|fromNow" class="call-sign"></small></p>
<p ng-bind="snippet.description"></p>
<div ui-ace="{
showGutter: true,
useWrapMode : true,
mode:snippet.mode.toLowerCase(),
theme:'solarized_dark'
}"
readonly
ng-model="snippet.content"></div>
</li>
</ul>
</div>
<div class="modal-footer">
<button ng-click="vm.cancel()" class="btn btn-default">Cancel</button>
</div>
</div>

View File

@@ -0,0 +1,16 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>Sign Out</h4>
</div>
<div class="modal-body">
<p>
Are you sure to sign out?
</p>
</div>
<div class="modal-footer">
<button ng-click="vm.submit()" type="button" name="button" class="btn btn-danger">Sign Out</button>
<button ng-click="vm.cancel()" type="button" name="button" class="btn btn-default">Cancel</button>
</div>
</div>

View File

@@ -1,4 +1,7 @@
<form ng-submit="vm.signIn()">
<p ng-if="vm.authFailed" class="alert alert-danger">
Incorrect email or password entered. Please try again.
</p>
<div class="form-group">
<label for="email">E-mail</label>
<input ng-model="vm.email" type="text" id="email" name="name" class="form-control" placeholder="E-mail">

View File

@@ -0,0 +1,48 @@
<div class="home-state">
<h1 class="jumbotron">Codexen App <small>v0.1.1</small></h1>
<h2>About CodeXen</h2>
<p>
CodeXen is short code storage tool make coding more stressless. If you use CodeXen, then you will be disentangled from troublesome organizing a large number of snippets and googling same code many times.
</p>
<ol>
<li>
<h4>
Post your code
</h4>
<p>
Post your commonly used code with description,category,and tags.
</p>
</li>
<li>
<h4>
Save on cloud
</h4>
<p>
From short snippet to long complex code,CodeXen saves any code simply.
</p>
</li>
<li>
<h4>
Use code like a magic
</h4>
<p>
CodeXen call code you posted whereever you are.Type [shift+control+tab] simultaneously.
</p>
</li>
<li>
<h4>
Code Elegantly
</h4>
<p>
That's all!
You must be loved with CodeXen. Enjoy coding;)
</p>
</li>
</ol>
<p>
© 2015 MAISIN&CO.,Inc.
</p>
</div>

View File

@@ -0,0 +1,33 @@
<div class="snippets-detail-state">
<div class="detail-header">
<span class="detail-header-title">
<small>callsign</small>
<span ng-bind="vm.recipe.title"></span>
<small><span ng-bind="vm.recipe.updatedAt|fromNow"></span> <i class="fa fa-clock-o"></i></small>
</span>
<span class="detail-header-control pull-right">
<!-- <button type="button" name="button" class="btn btn-default"><i class="fa fa-share"></i></button> -->
<button btn-edit-recipe="vm.recipe" type="button" name="button" class="btn btn-default"><i class="fa fa-edit"></i></button>
<button btn-delete-recipe="vm.recipe" type="button" name="button" class="btn btn-danger"><i class="fa fa-trash"></i></button>
</span>
</div>
<div class="detail-body">
<div ng-if="!vm.isLoaded" class="">
Loadding
</div>
<div ng-if="vm.isLoaded" class="">
<div tag-list="vm.recipe.Tags"></div>
<div class="panel panel-default">
<div class="panel-body">
<div ng-bind-html="vm.recipe.content | marked" class="marked"></div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,62 @@
<div class="snippets-list-state">
<div class="left-pane">
<div class="snippet-search">
<div class="input-group">
<input ng-model="vm.search" ng-change="vm.searchRecipes()" type="text" name="name" class="form-control" placeholder="Search ..." autocomplete="off">
<span class="input-group-btn">
<button btn-new-recipe class="btn btn-default" type="button">
<i class="fa fa-plus-square-o"></i>
</button>
</span>
</div>
</div>
<ul class="snippet-list">
<li ng-if="vm.isLoading" class="message-item">
<h4>
Loading
</h4>
</li>
<li ng-if="!vm.isLoading && vm.snippets==0 && !vm.isGuest" class="message-item">
<h4>
Empty List
</h4>
<button btn-new-snippet class="btn btn-default"><i class="fa fa-plus-square-o"></i> New Snippet</button>
</li>
<li ng-if="!vm.isLoading && vm.isGuest" class="message-item">
<h4>
Sign In to access
</h4>
<a ui-sref="auth.signin" class="btn btn-default"><i class="fa fa-signin"></i> Sign In</a>
</li>
<li recipe-item="recipe" ng-repeat="recipe in vm.filtered" ui-sref="recipes.detail({id:recipe.id})" ng-class="{active:vm.recipeId===recipe.id}">
<div class="media">
<div class="media-left">
<img width="25" height="25" class="img-circle" ng-src="http://www.gravatar.com/avatar/{{ vm.currentUser.email | gravatar }}" alt="" />
</div>
<div class="media-body">
<p ng-bind="recipe.title"></p>
<p class="created-at">
<span ng-bind="recipe.updatedAt|fromNow"></span>
</p>
</div>
</div>
<div tag-list="recipe.Tags"></div>
</li>
</ul>
</div>
<div class="right-pane">
<div ng-if="'recipes'|isState">
No snippet selected.
</div>
<div ui-view></div>
</div>
</div>

View File

@@ -2,7 +2,14 @@
<div class="left-pane">
<div class="snippet-search">
<input ng-model="vm.search" ng-change="vm.searchSnippets()" type="text" name="name" class="form-control" placeholder="Search ..." autocomplete="off">
<div class="input-group">
<input ng-model="vm.search" ng-change="vm.searchSnippets()" type="text" name="name" class="form-control" placeholder="Search ..." autocomplete="off">
<span class="input-group-btn">
<button btn-new-snippet class="btn btn-default" type="button">
<i class="fa fa-plus-square-o"></i>
</button>
</span>
</div>
</div>
<ul class="snippet-list">

View File

@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html ng-app="codexen.popup">
<head>
<title>
CodeXen App
</title>
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<meta name="description" content="CodeXen - Short code storage service">
<link rel="stylesheet" href="../vendor/css/font-awesome.css" media="screen" title="no title" charset="utf-8">
<!-- inject:css -->
<link rel="stylesheet" href="styles/app.css">
<link rel="stylesheet" href="../shared/styles/bootstrap.css">
<!-- endinject -->
</head>
<body class="popup-body" ng-controller="PopUpController">
<div class="search-block">
<input ng-change="filterList(searchNeedle)" search-input id="search-input" type="text" class="form-control" ng-model="searchNeedle" ng-change="refreshResult">
</div>
<div class="result-block row-fluid">
<ul id="result-list" class="result-list left-pane">
<li ng-click="selectSnippet($index)" ng-repeat="snippet in filteredSnippets" ng-class="{active:$index == selectIndex}"><a href="#"> <small ng-bind="snippet.callSign"></small>&nbsp;/&nbsp;<span ng-bind="snippet.description"></span></a></li>
</ul>
<div class="right-pane">
<div class="result-detail-control">
<button ng-click="writeCode(selectedItem.content)" id="btnClipboard" type="button" name="button" class="btn btn-default"><i class="fa fa-clipboard"></i></button>
</div>
<div id="aceView" class="result-detail-content"
ui-ace="{
showGutter: false,
useWrapMode: true,
mode:selectedItem.mode.toLowerCase(),
onLoad: aceLoaded,
theme: 'solarized_dark'
}"
readonly
ng-model="selectedItem.content"
></div>
</div>
</div>
<script src="../vendor/ace.js"></script>
<script src="../vendor/angular.js" charset="utf-8"></script>
<script src="../vendor/satellizer.js"></script>
<script src="../vendor/hotkeys.js" charset="utf-8"></script>
<!-- inject:js -->
<script src="popup.js"></script>
<script src="services/snippet.js"></script>
<script src="../shared/shared.js"></script>
<script src="../shared/directives/ui-ace.js"></script>
<script src="../shared/config/ace.js"></script>
<script src="../shared/config/env.js"></script>
<script src="../shared/config/satellizer.js"></script>
<script src="../shared/services/Snippet.js"></script>
<!-- endinject -->
</body>
</html>

View File

@@ -10,8 +10,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<meta name="description" content="CodeXen - Short code storage service">
<link rel="stylesheet" href="../../vendor/css/font-awesome.css" media="screen" title="no title" charset="utf-8">
<link rel="stylesheet" href="../../main.css" media="screen" title="no title" charset="utf-8">
<link rel="stylesheet" href="../vendor/css/font-awesome.css" media="screen" title="no title" charset="utf-8">
<!-- inject:css -->
<!-- endinject -->
</head>
<body class="popup-body" ng-controller="PopUpController">
@@ -21,14 +24,12 @@
<div class="result-block row-fluid">
<ul id="result-list" class="result-list left-pane">
<li ng-click="selectSnippet($index)" ng-repeat="snippet in filteredSnippets" ng-class="{active:$index == selectIndex}"><a href="#"> <span ng-bind="snippet.callSign"></span> <small ng-bind="snippet.description"></small></a></li>
<li ng-click="selectSnippet($index)" ng-repeat="snippet in filteredSnippets" ng-class="{active:$index == selectIndex}"><a href="#"> <small ng-bind="snippet.callSign"></small>&nbsp;/&nbsp;<span ng-bind="snippet.description"></span></a></li>
</ul>
<div class="right-pane">
<div class="result-detail-control">
<button ng-click="writeCode(selectedItem.content)" id="btnClipboard" type="button" name="button" class="btn btn-default"><i class="fa fa-clipboard"></i></button>
<!-- <button ng-click="editSnippet(selectedItem.id)" id="btnEdit" type="button" name="button" class="btn btn-default"><i class="fa fa-edit"></i></button> -->
<!-- <button id="btnShare" type="button" name="button" class="btn btn-default"><i class="fa fa-share"></i></button> -->
</div>
<div id="aceView" class="result-detail-content"
ui-ace="{
@@ -44,12 +45,12 @@
></div>
</div>
</div>
<script src="../../vendor/ace.js"></script>
<script src="../../vendor/angular.js" charset="utf-8"></script>
<script src="../../directives/ui-ace.js"></script>
<script src="../../vendor/satellizer.js"></script>
<script src="../../vendor/hotkeys.js" charset="utf-8"></script>
<script src="popup.js" charset="utf-8"></script>
<script src="services/snippet.js" charset="utf-8"></script>
<script src="../vendor/ace.js"></script>
<script src="../vendor/angular.js" charset="utf-8"></script>
<script src="../vendor/satellizer.js"></script>
<script src="../vendor/hotkeys.js" charset="utf-8"></script>
<!-- inject:js -->
<!-- endinject -->
</body>
</html>

View File

@@ -6,10 +6,12 @@ var ipc = require('ipc')
var resultList = document.getElementById('result-list')
angular.module('codexen.popup', [
'codexen.shared',
'ui.ace',
'satellizer',
'cfp.hotkeys'
])
.constant('appName', 'popup')
.controller('PopUpController', function ($scope, Snippet, $auth, $window, hotkeys, $document, $filter) {
// Setup Events
remote.getCurrentWindow().on('focus', function () {

View File

@@ -26,6 +26,7 @@
padding: 0
border-right: 1px solid $baseBorderColor
li
white-space nowrap
&:nth-child(even)
background-color $baseBackgroundColor
&:nth-child(odd)

View File

@@ -0,0 +1,68 @@
.popup-body .search-block {
padding: 5px;
height: 44px;
position: absolute;
top: 0;
width: 100%;
}
.popup-body .result-block {
position: absolute;
top: 44px;
bottom: 0;
width: 100%;
overflow: hidden;
}
.popup-body .result-block .left-pane {
margin: 0;
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 40%;
overflow-y: auto;
overflow-x: hidden;
}
.popup-body .result-block .result-list {
list-style: none;
padding: 0;
border-right: 1px solid #001a20;
}
.popup-body .result-block .result-list li {
white-space: nowrap;
}
.popup-body .result-block .result-list li:nth-child(even) {
background-color: #002b36;
}
.popup-body .result-block .result-list li:nth-child(odd) {
background-color: #00323f;
}
.popup-body .result-block .result-list li.active {
color: #fff;
background-color: #088cff;
}
.popup-body .result-block .result-list li a {
display: block;
padding: 5px 10px;
border-bottom: 1px solid #001a20;
}
.popup-body .result-block .right-pane {
position: absolute;
left: 40%;
top: 0;
bottom: 0;
width: 60%;
overflow-y: auto;
overflow-x: hidden;
}
.popup-body .result-block .result-detail-control {
position: absolute;
top: 0;
width: 100%;
height: 34px;
}
.popup-body .result-block .result-detail-content {
position: absolute;
top: 34px;
bottom: 0;
width: 100%;
}

View File

@@ -0,0 +1,4 @@
@import '../../shared/styles/_vars'
@import '../../shared/styles/mixins/*'
@import '_popup'

View File

@@ -1,3 +1,3 @@
/* global angular */
angular.module('codexen')
angular.module('codexen.shared')
.constant('aceModes', ['ABAP', 'ABC', 'ActionScript', 'ADA', 'Apache_Conf', 'AsciiDoc', 'Assembly_x86', 'AutoHotKey', 'BatchFile', 'C9Search', 'C_Cpp', 'Cirru', 'Clojure', 'Cobol', 'coffee', 'ColdFusion', 'CSharp', 'CSS', 'Curly', 'D', 'Dart', 'Diff', 'Dockerfile', 'Dot', 'Dummy', 'DummySyntax', 'Eiffel', 'EJS', 'Elixir', 'Elm', 'Erlang', 'Forth', 'FTL', 'Gcode', 'Gherkin', 'Gitignore', 'Glsl', 'golang', 'Groovy', 'HAML', 'Handlebars', 'Haskell', 'haXe', 'HTML', 'HTML_Ruby', 'INI', 'Io', 'Jack', 'Jade', 'Java', 'JavaScript', 'JSON', 'JSONiq', 'JSP', 'JSX', 'Julia', 'LaTeX', 'Lean', 'LESS', 'Liquid', 'Lisp', 'LiveScript', 'LogiQL', 'LSL', 'Lua', 'LuaPage', 'Lucene', 'Makefile', 'Markdown', 'Mask', 'MATLAB', 'MEL', 'MUSHCode', 'MySQL', 'Nix', 'ObjectiveC', 'OCaml', 'Pascal', 'Perl', 'pgSQL', 'PHP', 'Powershell', 'Praat', 'Prolog', 'Properties', 'Protobuf', 'Python', 'R', 'RDoc', 'RHTML', 'Ruby', 'Rust', 'SASS', 'SCAD', 'Scala', 'Scheme', 'SCSS', 'SH', 'SJS', 'Smarty', 'snippets', 'Soy_Template', 'Space', 'SQL', 'SQLServer', 'Stylus', 'SVG', 'Tcl', 'Tex', 'Text', 'Textile', 'Toml', 'Twig', 'Typescript', 'Vala', 'VBScript', 'Velocity', 'Verilog', 'VHDL', 'XML', 'XQuery', 'YAML', 'Django'])

View File

@@ -0,0 +1,4 @@
/* global angular */
angular.module('codexen.shared')
// .constant('apiUrl', 'http://localhost:8000/')
.constant('apiUrl', 'http://codexen-server-dev.elasticbeanstalk.com/')

View File

@@ -0,0 +1,8 @@
/* global angular */
angular.module('codexen.shared')
.config(function ($authProvider, $httpProvider, apiUrl) {
$authProvider.baseUrl = apiUrl
$httpProvider.defaults.useXDomain = true
delete $httpProvider.defaults.headers.common['X-Requested-With']
})

View File

@@ -338,6 +338,49 @@ angular.module('ui.ace', [])
acee.focus()
})
scope.$on('insertRequested', function (e, req) {
var cursor = acee.selection.getCursor()
var str = ''
if (cursor.column > 0) str += '\n\n'
switch (req) {
case 'h1':
acee.insert(str + '# some heading\n\n')
break
case 'ul':
acee.insert(str + '- item1\n- item2\n- item3')
break
case 'ol':
acee.insert(str + '1. item1\n2. item2\n3. item3')
break
case 'a':
acee.insert(str + '[example.com](http://example.com)')
break
case 'table':
acee.insert(str +
'First Header | Second Header\n' +
'------------- | -------------\n' +
'Content Cell | Content Cell\n' +
'Content Cell | Content Cell\n')
}
scope.$evalAsync(function () {
ngModel.$setViewValue(session.getValue())
})
})
scope.$on('insertSnippetRequested', function (e, snippet) {
var cursor = acee.selection.getCursor()
var str = ''
if (cursor.column > 0) str += '\n\n'
acee.insert(str + '```\n' + snippet.content + '\n```\n> [snippet#' + snippet.id + '](#/snippets/' + snippet.id + ')\n\n')
scope.$evalAsync(function () {
ngModel.$setViewValue(session.getValue())
})
})
}
}
}])

View File

@@ -1,5 +1,5 @@
/* global angular */
angular.module('codexen')
angular.module('codexen.shared')
.factory('Snippet', function ($http, $auth, apiUrl) {
var findByUser = function (user) {
var url = apiUrl + 'snippets/search'

View File

@@ -0,0 +1,3 @@
angular.module('codexen.shared', [
'satellizer'
])

View File

@@ -0,0 +1,24 @@
html
overflow: hidden
height: 100%
body
height: 100%
overflow: auto
font-family: "Lato", sans-serif
color $textColor
background-color: $appBackgroundColor
label
font-family: "Lato", sans-serif
color $textColor
h1, h2, h3, h4, h5
color $textColorHighlight
margin 0
textarea
resize: vertical
hr
border-color $baseBorderColor

View File

@@ -84,3 +84,16 @@ $alert-warning-text= $textColorSelected
$panel-bg= $baseBackgroundColor
$panel-default-border= $baseBorderColor
$nav-tabs-border-color= $baseBorderColor
$nav-tabs-link-hover-border-color= $baseBorderColor
$nav-tabs-active-link-hover-bg= transparent $backgroundColorSelected
$nav-tabs-active-link-hover-color= $textColorSelected
$nav-tabs-active-link-hover-border-color= $baseBorderColor
$nav-tabs-justified-link-border-color= $baseBorderColor
$nav-tabs-justified-active-link-border-color= $baseBorderColor
$table-border-color= $baseBorderColor

5639
src/browser/shared/styles/bootstrap.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
// Override vars and mixins
@import '_vars'
@import 'mixins/*'
// Core variables and mixins
@import '../../../../node_modules/bootstrap-styl/bootstrap/variables'
@import '../../../../node_modules/bootstrap-styl/bootstrap/mixins'
// Utilities
@import '../../../../node_modules/bootstrap-styl/bootstrap/utilities'
@import '../../../../node_modules/bootstrap-styl/bootstrap/responsive-utilities'
// Reset and dependencies
@import '../../../../node_modules/bootstrap-styl/bootstrap/normalize'
@import '../../../../node_modules/bootstrap-styl/bootstrap/print'
// Core CSS
@import '../../../../node_modules/bootstrap-styl/bootstrap/scaffolding'
@import '../../../../node_modules/bootstrap-styl/bootstrap/type'
// @import '../../../../node_modules/bootstrap-styl/bootstrap/code'
@import '../../../../node_modules/bootstrap-styl/bootstrap/grid'
@import '../../../../node_modules/bootstrap-styl/bootstrap/tables'
@import '../../../../node_modules/bootstrap-styl/bootstrap/forms'
@import '../../../../node_modules/bootstrap-styl/bootstrap/buttons'
// Components
@import '../../../../node_modules/bootstrap-styl/bootstrap/component-animations'
@import '../../../../node_modules/bootstrap-styl/bootstrap/dropdowns'
@import '../../../../node_modules/bootstrap-styl/bootstrap/button-groups'
@import '../../../../node_modules/bootstrap-styl/bootstrap/input-groups'
@import '../../../../node_modules/bootstrap-styl/bootstrap/navs'
@import '../../../../node_modules/bootstrap-styl/bootstrap/navbar'
// @import '../../../../node_modules/bootstrap-styl/bootstrap/breadcrumbs'
// @import '../../../../node_modules/bootstrap-styl/bootstrap/pagination'
// @import '../../../../node_modules/bootstrap-styl/bootstrap/pager'
@import '../../../../node_modules/bootstrap-styl/bootstrap/labels'
@import '../../../../node_modules/bootstrap-styl/bootstrap/badges'
@import '../../../../node_modules/bootstrap-styl/bootstrap/jumbotron'
@import '../../../../node_modules/bootstrap-styl/bootstrap/thumbnails'
@import '../../../../node_modules/bootstrap-styl/bootstrap/alerts'
@import '../../../../node_modules/bootstrap-styl/bootstrap/progress-bars'
@import '../../../../node_modules/bootstrap-styl/bootstrap/media'
@import '../../../../node_modules/bootstrap-styl/bootstrap/list-group'
@import '../../../../node_modules/bootstrap-styl/bootstrap/panels'
@import '../../../../node_modules/bootstrap-styl/bootstrap/responsive-embed'
@import '../../../../node_modules/bootstrap-styl/bootstrap/wells'
@import '../../../../node_modules/bootstrap-styl/bootstrap/close'
// Components w/ JavaScript
@import '../../../../node_modules/bootstrap-styl/bootstrap/modals'
@import '../../../../node_modules/bootstrap-styl/bootstrap/tooltip'
@import '../../../../node_modules/bootstrap-styl/bootstrap/popovers'
// @import '../../../../node_modules/bootstrap-styl/bootstrap/carousel'
// Overrides
@import '_shared'
@import '_index'

Some files were not shown because too many files have changed in this diff Show More