1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-27 16:41:41 +00:00

Merge branch 'dev'

* dev: (79 commits)
  version 0.2.1
  修正 - Member list, Team listのデザイン修正
  実装 - Team pageとPlanet pageにMember List表示
  実装 - PlanetHeaderにPrivate鍵表示
  Noteから外部Linkを開くときにBrowserを使う
  LogoutModal実装
  Contact Modal追加
  on Refactor... #4
  on Refactor... #3
  on Refactor... #2
  on Refactoring...
  test 0.2.0
  Fix: Personal Settingボターンを右にする。写真からまっすぐProfile pageに入れるようにする
  Add: Refresh button
  Fix: Design changed
  Fix: Disable pinch to zoom
  Fix: Preview button修正
  Fix: PlanetNavigatorのHome削除 & SnippetsとBlueprintsはToggleができるように
  Fix: minor features 設定ボタンアイコンの変更 削除Modalでcmd+enterの使用 検索バーデザイン
  Add: Log in / Sign upの時にエラーが出たらAlertを表示する Debug: Tray Icon, PopUpWindow, Menuがいつの間にか消える
  ...

Conflicts:
	src/browser/main/controllers/AppController.js
	src/browser/main/controllers/directives/SideNavController.js
	src/browser/main/controllers/states/AuthRegisterController.js
	src/browser/main/index.html
	src/browser/main/services/Modal.js
	src/browser/main/styles/app.css
	src/browser/main/styles/app.styl
	src/browser/main/styles/directives/side-nav.styl
	src/browser/main/tpls/directives/side-nav.tpl.html
	src/browser/main/tpls/states/home.tpl.html
This commit is contained in:
Rokt33r
2015-08-21 04:58:01 +09:00
180 changed files with 6706 additions and 9556 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -1,13 +0,0 @@
/* global angular */
angular.module('codexen', [
'codexen.shared',
'ngSanitize',
'ui.select',
'ui.ace',
'ui.router',
'ui.bootstrap',
'satellizer',
'angular-md5',
'templates'])
.constant('appName', 'main')
angular.module('templates', [])

View File

@@ -1,111 +0,0 @@
/* global angular */
angular.module('codexen')
.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')
.otherwise('/')
$stateProvider
/* Auth */
.state('auth', {
url: '/auth',
views: {
'main-view': {
templateUrl: 'tpls/states/auth.tpl.html'
}
}
})
.state('auth.register', {
url: '/register',
templateUrl: 'tpls/states/auth.register.tpl.html',
controller: 'AuthRegisterController as vm'
})
.state('auth.signin', {
url: '/signin',
templateUrl: 'tpls/states/auth.signin.tpl.html',
controller: 'AuthSignInController as vm'
})
.state('settings', {
url: '/settings',
views: {
'main-view': {
templateUrl: 'tpls/states/settings.tpl.html',
controller: 'SettingsController as vm'
}
}
})
/* Snippets */
.state('snippets', {
url: '/snippets',
views: {
'main-view': {
templateUrl: 'tpls/states/snippets.list.tpl.html',
controller: 'SnippetsListController as vm'
}
},
resolve: {
mySnippets: function (Snippet) {
return Snippet.findMine().then(function (res) {
return res.data
})
}
}
})
.state('snippets.detail', {
url: '/:id',
templateUrl: 'tpls/states/snippets.detail.tpl.html',
controller: 'SnippetsDetailController as vm'
})
/* Home */
.state('home', {
url: '/',
views: {
'main-view': {
templateUrl: 'tpls/states/home.tpl.html',
controller: 'HomeController as vm'
}
}
})
/* 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,16 +0,0 @@
/* 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

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

View File

@@ -1,42 +0,0 @@
/* 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

@@ -1,45 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('EditSnippetModalController', function ($modalInstance, aceModes, $log, Snippet, $rootScope, Tag, snippet) {
var vm = this
vm.aceModes = aceModes
vm.snippet = snippet
vm.submit = function () {
var params = {
description: vm.snippet.description,
callSign: vm.snippet.callSign,
mode: vm.snippet.mode == null ? null : vm.snippet.mode.toLowerCase(),
content: vm.snippet.content,
Tags: angular.isArray(vm.snippet.Tags) ? vm.snippet.Tags.map(function (tag) { return tag.name }) : []
}
Snippet.update(vm.snippet.id, params)
.success(function (data) {
console.log('updated res :', data)
$rootScope.$broadcast('snippetUpdated', snippet)
$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,23 +0,0 @@
/* 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

@@ -1,42 +0,0 @@
/* 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,43 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('NewSnippetModalController', function ($modalInstance, aceModes, $log, Snippet, Tag) {
var vm = this
vm.aceModes = aceModes
vm.submit = function () {
var params = {
description: vm.description,
callSign: vm.callSign,
mode: vm.mode == null ? null : vm.mode.toLowerCase(),
content: vm.content,
Tags: angular.isArray(vm.Tags) ? vm.Tags.map(function (tag) { return tag.name }) : []
}
Snippet.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,18 +0,0 @@
/* 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

@@ -1,13 +0,0 @@
/* 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

@@ -1,21 +0,0 @@
/* global angular */
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

@@ -1,3 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('HomeController', function ($auth, Snippet, $scope) {})

View File

@@ -1,32 +0,0 @@
/* 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

@@ -1,98 +0,0 @@
/* 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

@@ -1,33 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('SettingsController', function (Settings) {
var vm = this
vm.changePassword = changePassword
vm.isSuccess = false
vm.isError = false
function changePassword () {
var params = {
password: vm.password,
newPassword: vm.newPassword
}
Settings.changePassword(params)
.success(function (data) {
resetInput()
vm.isSuccess = true
vm.isError = false
})
.error(function () {
resetInput()
vm.isError = true
vm.isSuccess = false
})
}
function resetInput () {
vm.password = ''
vm.newPassword = ''
}
})

View File

@@ -1,31 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('SnippetsDetailController', function (Snippet, $state, $rootScope, $scope, Modal) {
var vm = this
vm.isLoaded = false
var snippetId = $state.params.id
Snippet.show(snippetId)
.success(function (data) {
vm.snippet = data
vm.isLoaded = true
})
$scope.$on('taggingRequested', function (e) {
e.stopPropagation()
e.preventDefault()
Modal.editSnippet(angular.copy(vm.snippet))
.then(function (snippet) {
console.log('edited', snippet)
}, function () {
console.log('edit snippet modal dismissed')
})
})
$scope.$on('snippetUpdated', function (e, snippet) {
console.log('event received', snippet)
if (snippet.id === vm.snippet.id) vm.snippet = snippet
})
})

View File

@@ -1,107 +0,0 @@
/* global angular */
angular.module('codexen')
.controller('SnippetsListController', function ($auth, Snippet, $scope, $state, $filter, mySnippets, User) {
var vm = this
vm.snippetId = parseInt($state.params.id)
vm.snippets = mySnippets
vm.searchSnippets = searchSnippets
vm.searchSnippets()
vm.isAuthenticated = $auth.isAuthenticated()
var reloadUser = function () {
if (vm.isAuthenticated) {
User.me().success(function (data) {
vm.currentUser = data
})
}
}
reloadUser()
// TODO: add Navigation methods
// vm.nextSnippet()
// vm.priorSnippet()
// vm.firstSnippet()
// vm.lastSnippet()
// TODO: keyboard navigating UX
$scope.$on('$stateChangeSuccess', function (e, toState, toParams) {
if (!toState.name.match(/snippets/)) return null
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) {
mySnippets[index] = snippet
return true
}
return false
})) mySnippets.unshift(snippet)
searchSnippets()
vm.snippetId = snippet.id
$state.go('snippets.detail', {id: snippet.id})
})
$scope.$on('snippetDeleted', function () {
if ($state.is('snippets.detail')) {
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) {
vm.snippets.splice(i, 1)
break
}
}
// Delete snippet from `filtered list`
// And redirect `next filtered snippet`
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})
else $state.go('snippets')
vm.filtered.splice(i, 1)
break
}
}
}
})
$scope.$on('tagSelected', function (e, tag) {
e.stopPropagation()
$scope.$apply(function () {
vm.search = '#' + tag.name
searchSnippets()
})
})
function loadSnippets() {
if ($auth.isAuthenticated) {
Snippet.findMine()
.success(function (data) {
vm.snippets = data
})
} else {
vm.snippets = void 0
}
}
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

@@ -1,19 +0,0 @@
/* 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

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

View File

@@ -1,14 +0,0 @@
/* 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,14 +0,0 @@
/* global angular */
angular.module('codexen')
.directive('btnEditSnippet', function (Modal) {
return {
scope: {
snippet: '=btnEditSnippet'
},
link: function (scope, el) {
el.on('click', function () {
Modal.editSnippet(angular.copy(scope.snippet))
})
}
}
})

View File

@@ -1,15 +0,0 @@
/* 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

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

View File

@@ -1,11 +0,0 @@
/* global angular */
angular.module('codexen')
.directive('btnNewSnippet', function (Modal, $rootScope) {
return {
link: function (scope, el) {
el.on('click', function () {
Modal.newSnippet()
})
}
}
})

View File

@@ -1,19 +0,0 @@
/* 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

@@ -1,8 +0,0 @@
/* global angular */
angular.module('codexen')
.directive('sideNav', function () {
return {
templateUrl: 'tpls/directives/side-nav.tpl.html',
controller: 'SideNavController as vm'
}
})

View File

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

View File

@@ -1,16 +0,0 @@
/* global angular */
angular.module('codexen')
.directive('tagItem', function () {
return {
restrict: 'A',
template: '#<span ng-bind="tag.name"></span>',
scope: {
tag: '=tagItem'
},
link: function (scope, el) {
el.on('click', function () {
scope.$emit('tagSelected', scope.tag)
})
}
}
})

View File

@@ -1,28 +0,0 @@
/* global angular */
angular.module('codexen')
.directive('tagList', function () {
return {
restrict: 'A',
template: '<p class="tags">' +
'<i class="fa fa-tags"></i> ' +
'<a tag-item="tag" ng-repeat="tag in tags" href></a>' +
'<a ng-if="!tags.length" ng-click="requestTagging($event)" href> Not tagged yet</a>' +
'</p>',
scope: {
tags: '=tagList'
},
link: function (scope, el) {
el.ready(function () {
el.find('a').on('click', function (e) {
e.stopPropagation()
})
})
scope.requestTagging = function (e) {
e.preventDefault()
e.stopPropagation()
scope.$emit('taggingRequested')
}
}
}
})

View File

@@ -1,7 +0,0 @@
/* global angular moment */
angular.module('codexen')
.filter('fromNow', function () {
return function (input) {
return moment(input).fromNow()
}
})

View File

@@ -1,19 +0,0 @@
/* 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

@@ -1,17 +0,0 @@
/* global angular */
angular.module('codexen')
.filter('searchSnippets', function ($filter) {
return function (input, needle) {
if (!angular.isString(needle) || !angular.isArray(input)) return angular.copy(input)
if (needle.match(/#(.+)|tag:(.+)/)) {
var name = needle.match(/#(.+)/) ? needle.match(/#(.+)/)[1] : needle.match(/tag:(.+)/)[1]
return input.filter(function (snippet) {
return snippet.Tags.some(function (tag) {
return tag.name.match(new RegExp('^'+name))
})
})
}
else return $filter('filter')(input, needle)
}
})

View File

@@ -1,41 +0,0 @@
<!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

@@ -1,52 +0,0 @@
/* 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

@@ -1,13 +0,0 @@
/* global angular */
angular.module('codexen')
.factory('Settings', function ($http, apiUrl) {
var changePassword = function (params) {
var url = apiUrl + 'settings/change_password'
return $http.post(url, params)
}
return {
changePassword: changePassword
}
})

View File

@@ -1,17 +0,0 @@
/* global angular */
angular.module('codexen')
.factory('Tag', function ($http, apiUrl) {
var findByName = function (tagName) {
var url = apiUrl + 'tags/search'
return $http.get(url, {
params: {
name: tagName
}
})
}
return {
findByName: findByName
}
})

View File

@@ -1,16 +0,0 @@
/* global angular */
angular.module('codexen')
.factory('User', function ($http, apiUrl, $rootScope, $state) {
$rootScope.$on('userSignOut', function () {
$state.go('auth.signin')
})
var me = function () {
var url = apiUrl + 'auth/user'
return $http.get(url)
}
return {
me: me
}
})

View File

@@ -1,232 +0,0 @@
/*!
* ui-select
* http://github.com/angular-ui/ui-select
* Version: 0.11.2 - 2015-03-17T04:08:46.478Z
* License: MIT
*/
/* Style when highlighting a search. */
.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
/* Select2 theme */
/* Mark invalid Select2 */
.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 /* The z-index Select2 applies to the select2-drop */
/* Selectize theme */
/* Helper class to show styles when focus */
.selectize-input.selectize-focus
border-color: #007FBB !important
/* Fix input width for Selectize theme */
.selectize-control > .selectize-input > input
width: 100%
/* Fix dropdown width for Selectize theme */
.selectize-control > .selectize-dropdown
width: 100%
/* Mark invalid Selectize */
.ng-dirty.ng-invalid > div.selectize-input
border-color: #D44950
/* Bootstrap theme */
/* Helper class to show styles when focus */
.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-placeholder
color $textColor
.ui-select-bootstrap .ui-select-toggle > .caret
position: absolute
height: 10px
top: 50%
right: 10px
margin-top: -2px
/* Fix Bootstrap dropdown position when inside a input-group */
.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 $input-border
.ui-select-bootstrap > .ui-select-match > .caret
position: absolute
top: 45%
right: 15px
/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
.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 /* Standard Bootstrap dropdown z-index */
.ui-select-multiple.ui-select-bootstrap
height: auto
padding: 3px 3px 0 10px
.ui-select-multiple.ui-select-bootstrap.open
border-color $input-border-focus
outline 0
box-shadow inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(red($input-border-focus), green($input-border-focus), blue($input-border-focus), .6)
.ui-select-multiple.ui-select-bootstrap input.ui-select-search
background-color: transparent !important /* To prevent double background when disabled */
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: $dropdown-link-color
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: $dropdown-link-hover-color
background-color: $dropdown-link-hover-bg
.ui-select-bootstrap .ui-select-choices-row.active>a
color: $dropdown-link-hover-color
text-decoration: none
outline: 0
background-color: $dropdown-link-hover-bg
.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
/* fix hide/show angular animation */
.ui-select-match.ng-hide-add,
.ui-select-search.ng-hide-add
display: none !important
/* Mark invalid Bootstrap */
.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match
border-color: #D44950

View File

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

View File

@@ -1,4 +0,0 @@
.new-snippet-modal
.ace_editor
height: 200px

View File

@@ -1,17 +0,0 @@
.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

@@ -1,7 +0,0 @@
.auth-state
.panel
margin-top 50px
h1
margin 15px 0
.auth-control
margin 10px 0

View File

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

View File

@@ -1,8 +0,0 @@
.settings-state
.panel
margin-top 15px
h1
margin 30px 0
.section
h4
margin-bottom 15px

View File

@@ -1,132 +0,0 @@
$left-pane-width= 275px
$pane-border-color= $border-color
$snippet-list-border-color= $border-color
$snippet-list-item-hover-bg= #EEE
$snippet-list-active-color= white
$snippet-list-active-bg= $brand-primary
.snippets-list-state
position: absolute
top:0
left:0
right:0
bottom:0
.left-pane
border-right 1px solid $baseBorderColor
position: absolute
top: 0
bottom: 0
left: 0
width: $left-pane-width
overflow:hidden
.snippet-search
position: absolute
top: 0
height: 50px
left: 0
right: 0
border-right 1px solid $baseBorderColor
padding: 7px 5px
.snippet-list
position: absolute
top: 50px
bottom: 0
left: 0
right: 0
overflow-x: hidden
overflow-y: auto
list-style: none
padding: 0
li
cursor: pointer
padding: 5px
border-right 1px solid $baseBorderColor
border-bottom 1px solid $baseBorderColor
&:nth-child(even)
background-color $baseBackgroundColor
&:nth-child(odd)
background-color lighten($baseBackgroundColor, 2%)
h4
margin: 0
&:hover
background-color: $backgroundColorSelected
p
margin:0
p.call-sign
font-size:0.8em
p.created-at
font-size:0.8em
opacity: 0.8
&.active
color: $snippet-list-active-color
background-color: $snippet-list-active-bg
a
color: white
.right-pane
position: absolute
top: 0
bottom: 0
left: $left-pane-width
right: 0
overflow-x: hidden
overflow-y: auto
background-color lighten($baseBackgroundColor, 2%)
.snippets-detail-state
position absolute
top 0
width 100%
bottom 0
overflow hidden
.detail-header
position absolute
top 0
width 100%
background-color lighten($baseBackgroundColor, 5%)
padding 5px 10px
height 50px
border-bottom solid 1px $baseBorderColor
.detail-header-title
color $textColorHighlight
line-height 40px
font-size 1.2em
small
font-size: 0.6em
color $textColor
.detail-header-control
padding 3px
.detail-body
position absolute
top 50px
width 100%
bottom 0
padding 5px 10px
overflow-y auto
.ace_editor
min-height 300px
border solid 1px $border-color
border-radius 5px
margin-bottom 5px
.tags
word-break: break-all
a
margin: 0 2px

View File

@@ -1,14 +0,0 @@
<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

@@ -1,19 +0,0 @@
<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

@@ -1,16 +0,0 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>Delete Snippet</h4>
</div>
<div class="modal-body">
<p>
Are you sure to delete it?
</p>
</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

@@ -1,60 +0,0 @@
<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

@@ -1,49 +0,0 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>Edit Snippet</h4>
</div>
<div class="modal-body">
<div class="form-group">
<textarea ng-model="vm.snippet.description" name="description" class="form-control" placeholder="Description..."></textarea>
</div>
<div class="form-group">
<input ng-model="vm.snippet.callSign" type="text" name="callSign" class="inline-form-control" placeholder="Callsign">
<ui-select ng-model="vm.snippet.mode" style="display: inline-block;" theme="bootstrap">
<ui-select-match placeholder="Select Type">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="mode in vm.aceModes | filter:$select.search">
<div ng-bind-html="mode | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>
<div class="form-group">
<div
ui-ace="{
mode: vm.snippet.mode.toLowerCase(),
theme:'solarized_dark',
useWrapMode : true
}"
ng-model="vm.snippet.content"
></div>
</div>
<div class="form-group">
<ui-select multiple tagging="vm.transform" tagging-tokens="SPACE|,|/" ng-model="vm.snippet.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="200">
<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

@@ -1,37 +0,0 @@
<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

@@ -1,60 +0,0 @@
<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

@@ -1,49 +0,0 @@
<div class="new-snippet-modal">
<div class="modal-header">
<h4>New Snippet</h4>
</div>
<div class="modal-body">
<div class="form-group">
<textarea ng-model="vm.description" name="description" class="form-control" placeholder="Description..."></textarea>
</div>
<div class="form-group">
<input ng-model="vm.callSign" type="text" name="callSign" class="inline-form-control" placeholder="Callsign">
<ui-select ng-model="vm.mode" style="display: inline-block;" on-select="vm.log(vm.mode.name.toLowerCase())" theme="bootstrap">
<ui-select-match placeholder="Select Type">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="mode in vm.aceModes | filter: $select.search">
<div ng-bind="::mode"></div>
</ui-select-choices>
</ui-select>
</div>
<div class="form-group">
<div
ui-ace="{
mode: vm.mode.toLowerCase(),
theme:'solarized_dark',
useWrapMode : true
}"
ng-model="vm.content"
></div>
</div>
<div class="form-group">
<ui-select multiple tagging="vm.transform" tagging-tokens="SPACE|,|/" ng-model="vm.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

@@ -1,25 +0,0 @@
<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

@@ -1,16 +0,0 @@
<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,54 +0,0 @@
<form novalidate name="registerForm" ng-submit="registerForm.$valid?vm.signup():null">
<!-- Email -->
<div class="form-group">
<label for="email">E-mail</label>
<input ng-model="vm.email" type="email" id="email" name="email" class="form-control" placeholder="E-mail" required>
<div class="alert alert-danger" ng-if="registerForm.$submitted && !vm.isEmpty(registerForm.email.$error)">
<div ng-show="registerForm.email.$error.required">No E-mail given.</div>
<div ng-show="registerForm.email.$error.email">Invalid Address.</div>
</div>
</div>
<!-- Password -->
<div class="form-group">
<label for="password">Password</label>
<input ng-model="vm.password" type="password" id="password" name="password" class="form-control" placeholder="Password" required>
<div class="alert alert-danger" ng-if="registerForm.$submitted && !vm.isEmpty(registerForm.password.$error)">
<div ng-show="registerForm.password.$error.required">No password given.</div>
</div>
</div>
<hr>
<!-- Username -->
<div class="form-group">
<label for="name">Username</label>
<input ng-model="vm.name" ng-pattern="'^[A-Za-z0-9\-\_]+$'" type="text" id="name" name="name" class="form-control" required>
<div class="alert alert-danger" ng-if="registerForm.$submitted && !vm.isEmpty(registerForm.name.$error)">
<div ng-show="registerForm.name.$error.required">No Username given.</div>
<div ng-show="registerForm.name.$error.pattern">Username should be ^[A-Za-z0-9\-\_]+$ (only alphanumeric, hyphen, underscore characters)</div>
</div>
</div>
<!-- Profile name -->
<div class="form-group">
<label for="profileName">Profile name</label>
<input ng-model="vm.profileName" type="text" name="profileName" class="form-control" required>
<div class="alert alert-danger" ng-if="registerForm.$submitted && !vm.isEmpty(registerForm.profileName.$error)">
<div ng-show="registerForm.profileName.$error.required">No Profile name given.</div>
</div>
</div>
<div class="form-group">
<button ng-class="{'btn-danger':registerForm.$invalid, 'btn-primary':registerForm.$valid}" type="submit" class="btn form-control">Register</button>
</div>
</form>

View File

@@ -1,18 +0,0 @@
<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">
</div>
<div class="form-group">
<label for="password">Password</label>
<input ng-model="vm.password" type="password" id="password" name="name" class="form-control" placeholder="Password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">Sign In</button>
</div>
</form>

View File

@@ -1,19 +0,0 @@
<div class="auth-state container-fluid">
<div class="row">
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 col-lg-6 col-lg-offset-3 panel panel-default">
<div class="text-center">
<h1>Authentication</h1>
<div class="auth-control">
<a class="btn btn-default" ui-sref-active="active" ui-sref="auth.register"><i class="fa fa-user-plus fa-fw"></i> Register</a> or <a class="btn btn-default" ui-sref-active="active" ui-sref="auth.signin"><i class="fa fa-sign-in fa-fw"></i> Sign In</a>
</div>
</div>
<ui-view></ui-view>
</div>
</div>
</div>

View File

@@ -1,33 +0,0 @@
<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

@@ -1,62 +0,0 @@
<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

@@ -1,33 +0,0 @@
<div class="settings-state container-fluid">
<div class="row">
<div class="col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 col-lg-6 col-lg-offset-3 panel panel-default">
<h1><i class="fa fa-gears"></i> Settings</h1>
<p>
Some settings...
</p>
<hr>
<div class="section">
<h4>Change Password</h4>
<form ng-submit="vm.changePassword()">
<alert type="success" ng-show="vm.isSuccess" close="vm.isSuccess=false">
Successfully changed!!
</alert>
<alert type="danger" ng-show="vm.isError" close="vm.isError=false">
Request failed!!
</alert>
<div class="form-group">
<label for="password">Current Password</label>
<input ng-model="vm.password" class="form-control" type="password" name="password" placeholder="Current Password">
</div>
<div class="form-group">
<label for="newPassword"> New Password</label>
<input ng-model="vm.newPassword" class="form-control" type="password" name="newPassword" placeholder="New Password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">Change Password</button>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@@ -1,41 +0,0 @@
<div class="snippets-detail-state">
<div class="detail-header">
<span class="detail-header-title">
<small>callsign</small>
<span ng-bind="vm.snippet.callSign"></span>
<small><span ng-bind="vm.snippet.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-snippet="vm.snippet" type="button" name="button" class="btn btn-default"><i class="fa fa-edit"></i></button>
<button btn-delete-snippet="vm.snippet" 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="">
<p ng-bind="vm.snippet.description"></p>
<div tag-list="vm.snippet.Tags"></div>
<div ui-ace="{
showGutter: false,
useWrapMode : true,
mode:vm.snippet.mode.toLowerCase(),
maxLines: -1,
theme:'solarized_dark',
rendererOptions: {
maxLinks: Infinity
}
}"
readonly
ng-model="vm.snippet.content"></div>
</div>
</div>
</div>

View File

@@ -1,64 +0,0 @@
<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.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">
<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 snippet-item="snippet" ng-repeat="snippet in vm.filtered" ui-sref="snippets.detail({id:snippet.id})" ng-class="{active:vm.snippetId===snippet.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="snippet.callSign" class="call-sign">
</p>
<p ng-bind="snippet.description">
</p>
<p class="created-at">
<span ng-bind="snippet.updatedAt|fromNow"></span>
</p>
</div>
</div>
<div tag-list="snippet.Tags"></div>
</li>
</ul>
</div>
<div class="right-pane">
<div ng-if="'snippets'|isState">
No snippet selected.
</div>
<div ui-view></div>
</div>
</div>

View File

@@ -1,66 +0,0 @@
<!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

@@ -1,56 +0,0 @@
<!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 -->
<!-- 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 -->
<!-- endinject -->
</body>
</html>

View File

@@ -1,192 +0,0 @@
/* global angular */
var remote = require('remote')
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 () {
if (!$auth.isAuthenticated()) return hidePopUp()
$scope.$apply(focusSearchInput)
loadSnippets()
})
hotkeys.bindTo($scope)
.add('down', function (e) {
nextSnippet()
e.preventDefault()
})
.add('up', function (e) {
priorSnippet()
e.preventDefault()
})
.add('right', function (e) {
e.preventDefault()
})
.add('left', function (e) {
e.preventDefault()
})
.add('esc', function (e) {
hidePopUp()
})
.add('shift+tab', function (e) {
e.preventDefault()
})
.add('tab', function (e) {
e.preventDefault()
})
.add('enter', function (e) {
writeCode($scope.selectedItem.content)
e.preventDefault()
})
$scope.aceLoaded = function (editor) {
editor.commands.addCommand({
name: 'escape',
bindKey: {win: 'esc', mac: 'esc'},
exec: function (editor) {
editor.blur()
$scope.$apply()
},
readOnly: true
})
}
$scope.$on('nextSnippetRequested', function (e) {
e.stopPropagation()
nextSnippet()
})
$scope.$on('priorSnippetRequested', function (e) {
e.stopPropagation()
priorSnippet()
})
$scope.$on('snippetSubmitted', function (e) {
if ($scope.filteredSnippets.length > 0) ipc.send('writeCode', $scope.selectedItem.content)
else console.log('\x07')
e.stopPropagation()
})
// Init Data
$scope.snippets = []
Snippet.findMine()
.success(function (data) {
$scope.snippets = data
filterList()
})
// Result Item control
$scope.selectIndex = 0
$scope.selectSnippet = selectSnippet
$scope.filterList = filterList
$scope.writeCode = writeCode
$scope.focusSearchInput = focusSearchInput
// Search Filter
function loadSnippets () {
Snippet.findMine()
.success(function (data) {
$scope.snippets = data
filterList()
})
}
function filterList (needle) {
$scope.filteredSnippets = $filter('filter')($scope.snippets, needle)
firstSnippet()
}
function selectSnippet (index) {
if (index !== undefined) $scope.selectIndex = index
$scope.selectedItem = $scope.filteredSnippets[$scope.selectIndex]
}
function firstSnippet () {
$scope.selectIndex = 0
selectSnippet($scope.selectIndex)
}
function priorSnippet () {
if ($scope.selectIndex > 0) $scope.selectIndex -= 1
if (resultList.children[$scope.selectIndex].offsetTop < resultList.scrollTop) {
resultList.scrollTop -= 33
}
selectSnippet()
}
function nextSnippet () {
if ($scope.selectIndex < $scope.filteredSnippets.length - 1) {
$scope.selectIndex += 1
}
if (resultList.clientHeight - 33 < resultList.children[$scope.selectIndex].offsetTop - resultList.scrollTop) {
resultList.scrollTop += 33
}
selectSnippet()
}
function writeCode (code) {
ipc.send('writeCode', code)
}
// Focusing Search Input
function focusSearchInput () {
document.getElementById('search-input').focus()
}
function hidePopUp () {
ipc.send('hidePopUp')
}
})
.directive('searchInput', function () {
return {
restrict: 'A',
link: function (scope, el, attr) {
el.on('keydown', function (e) {
// Down key => Focus on Result list
if (e.keyCode === 40) {
scope.$emit('nextSnippetRequested')
// e.preventDefault()
}
// Up key => Focus on Result list
if (e.keyCode === 38) {
scope.$emit('priorSnippetRequested')
// e.preventDefault()
}
// Up key => Focus on Result list
if (e.keyCode === 13) {
scope.$emit('snippetSubmitted')
}
// Esc key => Dismiss popup
if (e.keyCode === 27) {
ipc.send('hidePopUp')
e.preventDefault()
}
// TODO: Tab key => Auto complete
if (e.keyCode === 9) {
e.preventDefault()
}
})
}
}
})

View File

@@ -1,62 +0,0 @@
/* global angular */
angular.module('codexen.popup')
.constant('apiUrl', 'http://codexen-server-dev.elasticbeanstalk.com/')
.config(function ($authProvider, $httpProvider, apiUrl) {
$authProvider.baseUrl = apiUrl
$httpProvider.defaults.useXDomain = true
delete $httpProvider.defaults.headers.common['X-Requested-With']
})
angular.module('codexen.popup')
.factory('Snippet', function ($http, $auth, apiUrl) {
var findByUser = function (user) {
var url = apiUrl + 'snippets/search'
return $http.get(url, {
params: {
user: user
}
})
}
var findMine = function (params) {
var url = apiUrl + 'snippets/my'
return $http.get(url, {params: params})
}
var create = function (params) {
var url = apiUrl + 'snippets/create'
return $http.post(url, params)
}
var show = function (id, params) {
var url = apiUrl + 'snippets/id/' + id
return $http.get(url, {params: params})
}
var update = function (id, params) {
var url = apiUrl + 'snippets/id/' + id
return $http.put(url, params)
}
var destroy = function (id) {
var url = apiUrl + 'snippets/id/' + id
return $http.delete(url)
}
return {
findByUser: findByUser,
findMine: findMine,
create: create,
show: show,
delete: destroy,
update: update
}
})

View File

@@ -1,60 +0,0 @@
.popup-body
.search-block
padding: 5px
height:44px
position:absolute
top: 0
width: 100%
.result-block
position:absolute
top: 44px
bottom: 0
width: 100%
overflow: hidden
.left-pane
margin: 0
position: absolute
left: 0
top: 0
bottom: 0
width: 40%
overflow-y: auto
overflow-x: hidden
.result-list
list-style:none
padding: 0
border-right: 1px solid $baseBorderColor
li
white-space nowrap
&:nth-child(even)
background-color $baseBackgroundColor
&:nth-child(odd)
background-color lighten($baseBackgroundColor, 2%)
&.active
color: $textColorSelected
background-color: $btnPrimary
a
display:block
padding: 5px 10px
border-bottom 1px solid $baseBorderColor
.right-pane
position: absolute
left: 40%
top: 0
bottom: 0
width: 60%
overflow-y: auto
overflow-x: hidden
.result-detail-control
position: absolute
top: 0
width: 100%
height: 34px
.result-detail-content
position: absolute
top: 34px
bottom: 0
width: 100%

View File

@@ -1,68 +0,0 @@
.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

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

View File

@@ -1,3 +0,0 @@
/* global angular */
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

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

View File

@@ -1,8 +0,0 @@
/* 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

@@ -1,386 +0,0 @@
/* global angular */
'use strict'
/**
* Binds a ACE Editor widget
*/
angular.module('ui.ace', [])
.constant('uiAceConfig', {})
.directive('uiAce', ['uiAceConfig', function (uiAceConfig) {
if (angular.isUndefined(window.ace)) {
throw new Error('ui-ace need ace to work... (o rly?)')
}
/**
* Sets editor options such as the wrapping mode or the syntax checker.
*
* The supported options are:
*
* <ul>
* <li>showGutter</li>
* <li>useWrapMode</li>
* <li>onLoad</li>
* <li>theme</li>
* <li>mode</li>
* </ul>
*
* @param acee
* @param session ACE editor session
* @param {object} opts Options to be set
*/
var setOptions = function (acee, session, opts) {
// sets the ace worker path, if running from concatenated
// or minified source
if (angular.isDefined(opts.workerPath)) {
var config = window.ace.require('ace/config')
config.set('workerPath', opts.workerPath)
}
// ace requires loading
if (angular.isDefined(opts.require)) {
opts.require.forEach(function (n) {
window.ace.require(n)
})
}
// Boolean options
if (angular.isDefined(opts.showGutter)) {
acee.renderer.setShowGutter(opts.showGutter)
}
if (angular.isDefined(opts.useWrapMode)) {
session.setUseWrapMode(opts.useWrapMode)
}
if (angular.isDefined(opts.showInvisibles)) {
acee.renderer.setShowInvisibles(opts.showInvisibles)
}
if (angular.isDefined(opts.showIndentGuides)) {
acee.renderer.setDisplayIndentGuides(opts.showIndentGuides)
}
if (angular.isDefined(opts.useSoftTabs)) {
session.setUseSoftTabs(opts.useSoftTabs)
}
if (angular.isDefined(opts.showPrintMargin)) {
acee.setShowPrintMargin(opts.showPrintMargin)
}
if (angular.isDefined(opts.maxLines)) {
if (opts.maxLines < 0) opts.maxLines = Infinity
acee.setOptions({
maxLines: opts.maxLines
})
}
// commands
if (angular.isDefined(opts.disableSearch) && opts.disableSearch) {
acee.commands.addCommands([
{
name: 'unfind',
bindKey: {
win: 'Ctrl-F',
mac: 'Command-F'
},
exec: function () {
return false
},
readOnly: true
}
])
}
// Basic options
if (angular.isString(opts.theme)) {
acee.setTheme('ace/theme/' + opts.theme)
}
if (angular.isString(opts.mode)) {
session.setMode('ace/mode/' + opts.mode)
}
// Advanced options
if (angular.isDefined(opts.firstLineNumber)) {
if (angular.isNumber(opts.firstLineNumber)) {
session.setOption('firstLineNumber', opts.firstLineNumber)
} else if (angular.isFunction(opts.firstLineNumber)) {
session.setOption('firstLineNumber', opts.firstLineNumber())
}
}
// advanced options
var key, obj
if (angular.isDefined(opts.advanced)) {
for (key in opts.advanced) {
// create a javascript object with the key and value
obj = { name: key, value: opts.advanced[key] }
// try to assign the option to the ace editor
acee.setOption(obj.name, obj.value)
}
}
// advanced options for the renderer
if (angular.isDefined(opts.rendererOptions)) {
for (key in opts.rendererOptions) {
// create a javascript object with the key and value
obj = { name: key, value: opts.rendererOptions[key] }
// try to assign the option to the ace editor
acee.renderer.setOption(obj.name, obj.value)
}
}
// onLoad callbacks
angular.forEach(opts.callbacks, function (cb) {
if (angular.isFunction(cb)) {
cb(acee)
}
})
}
return {
restrict: 'EA',
require: '?ngModel',
link: function (scope, elm, attrs, ngModel) {
/**
* Corresponds the uiAceConfig ACE configuration.
* @type object
*/
var options = uiAceConfig.ace || {}
/**
* uiAceConfig merged with user options via json in attribute or data binding
* @type object
*/
var opts = angular.extend({}, options, scope.$eval(attrs.uiAce))
/**
* ACE editor
* @type object
*/
var acee = window.ace.edit(elm[0])
acee.$blockScrolling = Infinity
/**
* ACE editor session.
* @type object
* @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session}
*/
var session = acee.getSession()
/**
* Reference to a change listener created by the listener factory.
* @function
* @see listenerFactory.onChange
*/
var onChangeListener
/**
* Reference to a blur listener created by the listener factory.
* @function
* @see listenerFactory.onBlur
*/
var onBlurListener
/**
* Calls a callback by checking its existing. The argument list
* is variable and thus this function is relying on the arguments
* object.
* @throws {Error} If the callback isn't a function
*/
var executeUserCallback = function () {
/**
* The callback function grabbed from the array-like arguments
* object. The first argument should always be the callback.
*
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
* @type {*}
*/
var callback = arguments[0]
/**
* Arguments to be passed to the callback. These are taken
* from the array-like arguments object. The first argument
* is stripped because that should be the callback function.
*
* @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments}
* @type {Array}
*/
var args = Array.prototype.slice.call(arguments, 1)
if (angular.isDefined(callback)) {
scope.$evalAsync(function () {
if (angular.isFunction(callback)) {
callback(args)
} else {
throw new Error('ui-ace use a function as callback.')
}
})
}
}
/**
* Listener factory. Until now only change listeners can be created.
* @type object
*/
var listenerFactory = {
/**
* Creates a change listener which propagates the change event
* and the editor session to the callback from the user option
* onChange. It might be exchanged during runtime, if this
* happens the old listener will be unbound.
*
* @param callback callback function defined in the user options
* @see onChangeListener
*/
onChange: function (callback) {
return function (e) {
var newValue = session.getValue()
if (ngModel && newValue !== ngModel.$viewValue &&
// HACK make sure to only trigger the apply outside of the
// digest loop 'cause ACE is actually using this callback
// for any text transformation !
!scope.$$phase && !scope.$root.$$phase) {
scope.$evalAsync(function () {
ngModel.$setViewValue(newValue)
})
}
executeUserCallback(callback, e, acee)
}
},
/**
* Creates a blur listener which propagates the editor session
* to the callback from the user option onBlur. It might be
* exchanged during runtime, if this happens the old listener
* will be unbound.
*
* @param callback callback function defined in the user options
* @see onBlurListener
*/
onBlur: function (callback) {
return function () {
executeUserCallback(callback, acee)
}
}
}
attrs.$observe('readonly', function (value) {
acee.setReadOnly(!!value || value === '')
})
// Value Blind
if (ngModel) {
ngModel.$formatters.push(function (value) {
if (angular.isUndefined(value) || value === null) {
return ''
} else if (angular.isObject(value) || angular.isArray(value)) {
throw new Error('ui-ace cannot use an object or an array as a model')
}
return value
})
ngModel.$render = function () {
session.setValue(ngModel.$viewValue)
}
}
// Listen for option updates
var updateOptions = function (current, previous) {
if (current === previous) return
opts = angular.extend({}, options, scope.$eval(attrs.uiAce))
opts.callbacks = [ opts.onLoad ]
if (opts.onLoad !== options.onLoad) {
// also call the global onLoad handler
opts.callbacks.unshift(options.onLoad)
}
// EVENTS
// unbind old change listener
session.removeListener('change', onChangeListener)
// bind new change listener
onChangeListener = listenerFactory.onChange(opts.onChange)
session.on('change', onChangeListener)
// unbind old blur listener
// session.removeListener('blur', onBlurListener)
acee.removeListener('blur', onBlurListener)
// bind new blur listener
onBlurListener = listenerFactory.onBlur(opts.onBlur)
acee.on('blur', onBlurListener)
setOptions(acee, session, opts)
}
scope.$watch(attrs.uiAce, updateOptions, /* deep watch */ true)
// set the options here, even if we try to watch later, if this
// line is missing things go wrong (and the tests will also fail)
updateOptions(options)
elm.on('$destroy', function () {
acee.session.$stopWorker()
acee.destroy()
})
scope.$watch(function () {
return [elm[0].offsetWidth, elm[0].offsetHeight]
}, function () {
acee.resize()
acee.renderer.updateFull()
}, true)
scope.Infinity = -1
scope.focus = function () {
acee.focus()
}
scope.addCommand = acee.commands.addCommand
elm.on('click', function () {
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,52 +0,0 @@
/* global angular */
angular.module('codexen.shared')
.factory('Snippet', function ($http, $auth, apiUrl) {
var findByUser = function (user) {
var url = apiUrl + 'snippets/search'
return $http.get(url, {
params: {
user: user
}
})
}
var findMine = function (params) {
var url = apiUrl + 'snippets/my'
return $http.get(url, {params: params})
}
var create = function (params) {
var url = apiUrl + 'snippets/create'
return $http.post(url, params)
}
var show = function (id, params) {
var url = apiUrl + 'snippets/id/' + id
return $http.get(url, {params: params})
}
var update = function (id, params) {
var url = apiUrl + 'snippets/id/' + id
return $http.put(url, params)
}
var destroy = function (id) {
var url = apiUrl + 'snippets/id/' + id
return $http.delete(url)
}
return {
findByUser: findByUser,
findMine: findMine,
create: create,
show: show,
delete: destroy,
update: update
}
})

View File

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

View File

@@ -1,24 +0,0 @@
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

@@ -1,50 +0,0 @@
.alert
margin: 5px 0
input.form-control, textarea.form-control, input.inline-form-control
&::-webkit-input-placeholder
color $textColor
&:-moz-placeholder /* Firefox 18- */
color $textColor
&::-moz-placeholder /* Firefox 19+ */
color $textColor
&:-ms-input-placeholder
color $textColor
.inline-form-control
@extend .form-control
width: auto
display: inline-block
.btn.btn-default
border-style solid
border-width 1px
btn-color($btn-default-color, $btn-default-bg, $btn-default-border)
.btn.btn-primary
btn-color($btn-primary-color, $btn-primary-bg, $btn-primary-border)
.btn.btn-info
btn-color($btn-info-color, $btn-info-bg, $btn-info-border)
.btn.btn-success
btn-color($btn-success-color, $btn-success-bg, $btn-success-border)
.btn.btn-danger
btn-color($btn-danger-color, $btn-danger-bg, $btn-danger-border)
.btn.btn-warning
btn-color($btn-warning-color, $btn-warning-bg, $btn-warning-border)
textarea.form-control, .ace_editor
border-radius $input-border-radius
.ace_editor
border solid 1px $input-border
box-shadow inset 0 1px 1px rgba(0, 0, 0, .075)
font-family: 'Lucida Grande'
.ace_editor.ace_focus
controlGlow()
.modal-content
background-color $bg
.jumbotron
padding 48px 10px

View File

@@ -1,99 +0,0 @@
// Basic Vars(MUST BE CAMELCASED ATOM VARS)
$textColor= #99B2B8
$textColorHighlight= #D5DFE2
$textColorSelected = #FFFFFF
$textColorInfo= #6494ED
$textColorSuccess= #73C990
$textColorWarning= #E2C08D
$textColorError= #FF6347
$backgroundColorHighlight= #003B4A
$backgroundColorSelected= #004B5F
$appBackgroundColor= #001F27
$baseBackgroundColor= #002B36
$baseBorderColor= #001A20
$inputBackgroundColor= #00222B
$inputBorderColor= #001A20
$buttonBackgroundColor= #004355
$buttonBackgroundColorHover= #004B5F
$buttonBackgroundColorSelected= #52DCFF
$buttonBorderColor= $baseBorderColor
$block= #00222B
//buttons
$btnPrimary= #088CFF
$btnInfo= #5BDEFF
$btnSuccess= #22BD89
$btnWarning= #CD8737
$btnError= #DA2828
// Bootstrap Overrides(MUST BE BUILT WITH BASIC VALUE ONLY)
$brand-primary= $btnPrimary
$brand-info= $btnInfo
$brand-success= $btnSuccess
$brand-warning= $btnWarning
$brand-danger= $btnError
$btn-default-bg= $buttonBackgroundColor
$btn-default-color= $textColor
$btn-default-border= $baseBorderColor
$link-color= $textColorHighlight
$nav-link-active-link-hover-bg= $backgroundColorHighlight
$nav-pills-active-link-hover-color= $textColorHighlight
$nav-link-hover-bg= $backgroundColorHighlight
$input-bg= $backgroundColorHighlight
$input-border= $baseBorderColor
$input-border-focus= $buttonBackgroundColorSelected
$input-color= $textColorSelected
$dropdown-bg= $baseBackgroundColor
$dropdown-border= $baseBorderColor
$dropdown-link-color= $textColor
$dropdown-link-hover-bg= $backgroundColorSelected
$dropdown-link-hover-color= $textColorSelected
$modal-content-bg= $baseBackgroundColor
$modal-content-border-color= $modal-header-border-color= $modal-footer-border-color= $baseBorderColor
$jumbotron-bg= $backgroundColorHighlight
$alert-danger-bg= $textColorError
$alert-danger-border= dark($alert-danger-bg) ? darken($alert-danger-bg, 5%) : lighten($alert-danger-bg, 5%)
$alert-danger-text= $textColorSelected
$alert-info-bg= $textColorInfo
$alert-info-border= dark($alert-info-bg) ? darken($alert-info-bg, 5%) : lighten($alert-info-bg, 5%)
$alert-info-text= $textColorSelected
$alert-success-bg= $textColorSuccess
$alert-success-border= dark($alert-success-bg) ? darken($alert-success-bg, 5%) : lighten($alert-success-bg, 5%)
$alert-success-text= $textColorSelected
$alert-warning-bg= $textColorWarning
$alert-warning-border= dark($alert-warning-bg) ? darken($alert-warning-bg, 5%) : lighten($alert-warning-bg, 5%)
$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

File diff suppressed because it is too large Load Diff

View File

@@ -1,57 +0,0 @@
// 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'

View File

@@ -1,35 +0,0 @@
btn-color($color, $background, $border)
color $color
background-color $background
border-color $border
&:hover,
&:focus,
&.focus,
&:active,
&.active,
.open > .dropdown-toggle&
color dark($background) ? lighten($color, 10%) : darken($color, 10%)
background-color dark($background) ? lighten($background, 10%) : darken($background, 10%)
border-color dark($border) ? lighten($border, 12%) : darken($border, 12%)
&:active,
&.active,
.open > .dropdown-toggle&
background-image none
&.disabled,
&[disabled],
fieldset[disabled] &
&,
&:hover,
&:focus,
&.focus,
&:active,
&.active
background-color $background
border-color $border
.badge
color $background
background-color $color

View File

@@ -1,5 +0,0 @@
controlGlow($color = $input-border-focus)
$color-rgba = rgba(red($color), green($color), blue($color), .6)
border-color $color
outline 0
box-shadow inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px $color-rgba

View File

@@ -1,247 +0,0 @@
var app = require('app') // Module to control application life.
var BrowserWindow = require('browser-window') // Module to create native browser window.
// Report crashes to our server.
require('crash-reporter').start()
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
var mainWindow = null
// app.on('window-all-closed', function () {
// if (process.platform !== 'darwin') app.quit()
// })
var clipboard = require('clipboard')
var Tray = require('tray')
var notifier = require('node-notifier')
var appIcon = null
app.on('ready', function () {
appIcon = new Tray(__dirname + '/tray-icon.png')
appIcon.setToolTip('This is my application.')
appIcon.on('clicked', function () {
if (mainWindow == null) {
makeNewMainWindow()
}
mainWindow.show()
})
makeNewMainWindow()
var globalShortcut = require('global-shortcut')
var popUpWindow = new BrowserWindow({
width: 600,
height: 400,
show: false,
frame: false,
'web-preferences': {
'overlay-scrollbars': true,
'skip-taskbar': true
}
})
popUpWindow.loadUrl('file://' + __dirname + '/browser/popup/index.html')
app.on('activate-with-no-open-windows', function () {
if (mainWindow == null) {
makeNewMainWindow()
}
mainWindow.show()
})
popUpWindow.on('blur', function () {
popUpWindow.hide()
})
popUpWindow.setVisibleOnAllWorkspaces(true)
var hidePopUp = function () {
if (fromMain) {
} else {
mainWindow ? mainWindow.hide() : null
Menu.sendActionToFirstResponder('hide:')
}
popUpWindow.hide()
}
var ipc = require('ipc')
ipc.on('hidePopUp', function () {
hidePopUp()
})
ipc.on('writeCode', function (e, code) {
clipboard.writeText(code)
notifier.notify({
title: 'Write on clipboard!',
message: 'Ready to paste',
wait: false
}, function (err, res) {
})
hidePopUp()
})
var fromMain
// Register a 'ctrl+x' shortcut listener.
globalShortcut.register('ctrl+tab+shift', function () {
if (popUpWindow.isVisible()) {
hidePopUp()
return
}
fromMain = mainWindow ? mainWindow.isFocused() : false
popUpWindow.show()
})
// MENU
var Menu = require('menu')
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',
click: function () { app.quit() }
}
]
},
{
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().reloadIgnoringCache() }
},
{
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)
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.html')
mainWindow.on('closed', function () {
console.log('main closed')
mainWindow = null
app.dock.hide()
})
app.dock.show()
}
})

View File

@@ -1,32 +0,0 @@
{
"name": "codexen-app",
"version": "0.2.0",
"description": "CodeXen App",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"codexen",
"snippet",
"template",
"task",
"runner",
"remote",
"automator",
"code",
"storage",
"short code"
],
"author": "Dick Choi <fluke8259@gmail.com> (http://kazup.co)",
"license": "No License",
"bugs": {
"url": "https://github.com/Rokt33r/codexen-app/issues"
},
"homepage": "https://codexen.github.io",
"dependencies": {
"dotenv": "^1.1.0",
"robotjs": "^0.1.2",
"node-notifier": "^4.2.1"
},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB