From 1e531a90919e0754f28c973c7b566bcaa0a60f96 Mon Sep 17 00:00:00 2001 From: Johannes Millan Date: Fri, 30 Dec 2016 17:53:18 +0100 Subject: [PATCH] initial commit --- .bowerrc | 3 + .editorconfig | 26 ++ .gitattributes | 21 ++ .gitignore | 12 + .jscsrc | 120 ++++++++ .jshintrc | 35 +++ .travis.yml | 6 + .yo-rc.json | 66 +++++ README.md | 48 ++++ app/index.html | 70 +++++ app/scripts/_app.js | 20 ++ app/scripts/_app.spec.js | 10 + app/scripts/routes.js | 29 ++ app/scripts/routes.spec.js | 9 + app/styles/_functions/_some-function.scss | 0 app/styles/_mixins/_some-mixin.scss | 3 + .../_placeholders/_some-placeholder.scss | 3 + app/styles/_variables.scss | 0 app/styles/base/_buttons.scss | 13 + app/styles/base/_fonts.scss | 0 app/styles/base/_forms.scss | 35 +++ app/styles/base/_icons.scss | 12 + app/styles/base/_lists.scss | 11 + app/styles/base/_page.scss | 26 ++ app/styles/base/_tables.scss | 23 ++ app/styles/base/_typography.scss | 12 + app/styles/main.scss | 36 +++ bower.json | 31 +++ config.xml | 12 + electron/main.js | 104 +++++++ gulpfile.js | 4 + karma-e2e.conf.js | 27 ++ karma.conf.js | 80 ++++++ package.json | 61 ++++ tasks/build.js | 93 +++++++ tasks/config.js | 56 ++++ tasks/cordova.js | 108 ++++++++ tasks/deploy.js | 27 ++ tasks/dev.js | 262 ++++++++++++++++++ tasks/e2e.js | 36 +++ wallaby.js | 52 ++++ 41 files changed, 1602 insertions(+) create mode 100644 .bowerrc create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .jscsrc create mode 100644 .jshintrc create mode 100644 .travis.yml create mode 100644 .yo-rc.json create mode 100644 README.md create mode 100644 app/index.html create mode 100644 app/scripts/_app.js create mode 100644 app/scripts/_app.spec.js create mode 100644 app/scripts/routes.js create mode 100644 app/scripts/routes.spec.js create mode 100644 app/styles/_functions/_some-function.scss create mode 100644 app/styles/_mixins/_some-mixin.scss create mode 100644 app/styles/_placeholders/_some-placeholder.scss create mode 100644 app/styles/_variables.scss create mode 100644 app/styles/base/_buttons.scss create mode 100644 app/styles/base/_fonts.scss create mode 100644 app/styles/base/_forms.scss create mode 100644 app/styles/base/_icons.scss create mode 100644 app/styles/base/_lists.scss create mode 100644 app/styles/base/_page.scss create mode 100644 app/styles/base/_tables.scss create mode 100644 app/styles/base/_typography.scss create mode 100644 app/styles/main.scss create mode 100644 bower.json create mode 100644 config.xml create mode 100644 electron/main.js create mode 100644 gulpfile.js create mode 100644 karma-e2e.conf.js create mode 100644 karma.conf.js create mode 100644 package.json create mode 100644 tasks/build.js create mode 100644 tasks/config.js create mode 100644 tasks/cordova.js create mode 100644 tasks/deploy.js create mode 100644 tasks/dev.js create mode 100644 tasks/e2e.js create mode 100755 wallaby.js diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 00000000000..ba0accc5a30 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "app/bower_components" +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..9ce427de694 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.js] +indent_size = 2 + +[*.json] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[{package.json,bower.json,.travis.yml}] +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..473b3eaf665 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# Automatically normalize line endings for all text-based files +# http://git-scm.com/docs/gitattributes#_end_of_line_conversion +* text=auto + +# For the following file types, normalize line endings to LF on +# checkin and prevent conversion to CRLF when they are checked out +# (this is required in order to prevent newline related issues like, +# for example, after the build script is run) +.* text eol=lf +*.css text eol=lf +*.html text eol=lf +*.js text eol=lf +*.json text eol=lf +*.md text eol=lf +*.sh text eol=lf +*.txt text eol=lf +*.xml text eol=lf + +# Exclude the `.htaccess` file from GitHub's language statistics +# https://github.com/github/linguist#using-gitattributes +dist/.htaccess linguist-vendored \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..ffa677c9f83 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +node_modules +dist +www +platforms +release +.tmp +app/styles/**/*.css +app/styles/**/*.css.map +.sass-cache +bower_components +app/bower_components +*.log diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 00000000000..6c6424331be --- /dev/null +++ b/.jscsrc @@ -0,0 +1,120 @@ +{ + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireOperatorBeforeLineBreak": true, + "requireCamelCaseOrUpperCaseIdentifiers": { + "allowedPrefixes": [ + "opt_" + ], + "allExcept": [ + "var_args" + ] + }, + "maximumLineLength": false, + "validateIndentation": 2, + "validateQuoteMarks": "'", + "disallowMultipleLineStrings": true, + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowSpaceAfterPrefixUnaryOperators": true, + "disallowMultipleVarDecl": true, + "disallowKeywordsOnNewLine": [ + "else" + ], + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBinaryOperators": [ + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "<<=", + ">>=", + ">>>=", + "&=", + "|=", + "^=", + "+=", + "+", + "-", + "*", + "/", + "%", + "<<", + ">>", + ">>>", + "&", + "|", + "^", + "&&", + "||", + "===", + "==", + ">=", + "<=", + "<", + ">", + "!=", + "!==" + ], + "requireSpaceAfterBinaryOperators": true, + "requireSpacesInConditionalExpression": true, + "requireSpaceBeforeBlockStatements": true, + "requireSpacesInForStatement": true, + "requireLineFeedAtFileEnd": true, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "disallowSpacesInAnonymousFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInsideObjectBrackets": "all", + "disallowSpacesInsideArrayBrackets": "all", + "disallowSpacesInsideParentheses": true, + "disallowMultipleLineBreaks": false, + "disallowNewlineBeforeBlockStatements": true, + "disallowKeywords": [ + "with" + ], + "disallowSpacesInFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInFunctionDeclaration": { + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInCallExpression": true, + "disallowSpaceAfterObjectKeys": true, + "requireSpaceBeforeObjectValues": true, + "requireCapitalizedConstructors": true, + "requireDotNotation": true, + "requireSemicolons": true, + "validateParameterSeparator": ", ", + "jsDoc": { + "checkParamNames": true, + "requireParamTypes": true, + "checkRedundantParams": true, + "checkReturnTypes": true, + "checkRedundantReturns": true, + "requireReturnTypes": true, + "checkTypes": true, + "checkRedundantAccess": true + } +} diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000000..3644eff88e8 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,35 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "indent": 4, + "latedef": "nofunc", + "noarg": true, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + "globals": { + "angular": false, + "browser": false, + "jasmine": false, + "describe": false, + "xdescribe": false, + "before": false, + "beforeEach": false, + "after": false, + "afterEach": false, + "it": false, + "xit": false, + "it": false, + "inject": false, + "expect": false, + "spyOn": false + } +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..a80b6e0388e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - '0.10' +before_script: + - 'npm install -g bower grunt-cli' + - 'bower install' diff --git a/.yo-rc.json b/.yo-rc.json new file mode 100644 index 00000000000..6e5678d826b --- /dev/null +++ b/.yo-rc.json @@ -0,0 +1,66 @@ +{ + "generator-moda": { + "testSuffix": ".spec", + "testPassOnDefault": true, + "alwaysSkipDialog": false, + "stylePrefix": "_", + "editorCommand": "idea", + "uiRouter": true, + "pathOutputStyle": "dasherize", + "routesFile": "app/scripts/routes.js", + "fileExt": { + "script": ".js", + "tpl": ".html", + "style": ".scss" + }, + "dirs": { + "app": "app", + "appModules": "scripts", + "globalComponents": "main", + "routes": "routes" + }, + "subGenerators": { + "directive": { + "suffix": "-d", + "globalDir": "", + "createDirectory": true + }, + "controller": { + "suffix": "-c", + "nameSuffix": "Ctrl", + "globalDir": "", + "createDirectory": true + }, + "component": { + "suffix": "-cp", + "globalDir": "", + "createDirectory": true + }, + "service": { + "suffix": "-s", + "globalDir": "main/global-services" + }, + "factory": { + "suffix": "-f", + "globalDir": "main/global-services" + }, + "filter": { + "suffix": "-filter", + "globalDir": "main/global-filters" + }, + "provider": { + "suffix": "-p", + "globalDir": "main/global-services" + }, + "decorator": { + "suffix": "-decorator", + "nameSuffix": "Decorator", + "globalDir": "main/global-services" + }, + "mod": { + "prefix": "_", + "createDirectory": true + } + } + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000000..688ac32b8d3 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# superProductvity + +This project was generated with [yo angular modular generator](https://github.com/johannesjo/generator-modular-angular) +version 1.2.4. + +## Build & development + +Run `gulp` for development, `gulp build` for building and `gulp buildCordova` for building the hybrid-app. + +## Testing + +Unit tests are automatically run with the default task. End-to-End tests are run via `gulp e2e`. + +## The gulp tasks +As per default the following tasks are available at your convenience: + +* `gulp`: The development task. Runs all the injectors on file-change, file-creation or file-deletion. Unit-tests are run in parallel, as well as the sass-compilation. +* `gulp injectAll`: Runs all the injectors once. +* `gulp build`: Minifies your JavaScript via ng-annotate, your css, your images and your html files and copies everything to the www-folder. +* `gulp test`: Runs your unit tests with the keep-alive option. +* `gulp testSingle`: Runs your unit tests once. +* `gulp e2e`: Runs your end to end tests once. + +The mobile tasks require a little preparation described in the next section. + +* `gulp cordovaDev`: Symlinks your app-folder to www and runs the emulator for easy live development. +* `gulp cordovaRun`: Symlinks your app-folder to www and runs it on your device if connected. + +Of course there are also all the [standard cordova commands](https://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html) available as well. If you want to build a release run: + ``` + gulp build + cordova build android --release + ``` + +For all cordova related commands there is an optional platform parameter you can use to specify the platform for the cordova task. E.g. `gulp cordovaDev --platform=android` to run the android emulator. Alternatively you can edit the config.js to change the default platform. + +All tasks can be edited freely and can be found in the /tasks folder. + +## Setting up the hybrid build +Compiling your app to a hybrid app requires a little bit of configuration and you need to have cordova installed. Fortunately [that is quite easy](http://cordova.apache.org/docs/en/4.0.0/guide_cli_index.md.html#The%20Command-Line%20Interface). + +If everything is in place, you need to add the platforms you want to build your app on. For Android you would run: +``` +cordova platform add android +``` +If you get the message `Current working directory is not a Cordova-based project` you need to create the www-folder first (e.g.: `mkdir www` from your projects root directory). + +After that you should build your current state via `gulp build` then you can run `gulp run` or `gulp emulate` to check out your app on your device or in the emulator. \ No newline at end of file diff --git a/app/index.html b/app/index.html new file mode 100644 index 00000000000..403d7911683 --- /dev/null +++ b/app/index.html @@ -0,0 +1,70 @@ + + + + Super productvity + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/scripts/_app.js b/app/scripts/_app.js new file mode 100644 index 00000000000..9f98afebef2 --- /dev/null +++ b/app/scripts/_app.js @@ -0,0 +1,20 @@ +/** + * @ngdoc overview + * @name superProductvity + * @description + * # superProductvity + * + * Main module of the application. + */ + +(function () { + 'use strict'; + + angular + .module('superProductvity', [ + 'ngAnimate', + 'ngAria', + 'ngResource', + 'ui.router' + ]); +})(); diff --git a/app/scripts/_app.spec.js b/app/scripts/_app.spec.js new file mode 100644 index 00000000000..5d99b7903ad --- /dev/null +++ b/app/scripts/_app.spec.js @@ -0,0 +1,10 @@ +describe('superProductvity', function () { + 'use strict'; + + beforeEach(module('superProductvity')); + + it('should always work', function () { + expect(true) + .toBe(true); + }); +}); diff --git a/app/scripts/routes.js b/app/scripts/routes.js new file mode 100644 index 00000000000..c8127be2a04 --- /dev/null +++ b/app/scripts/routes.js @@ -0,0 +1,29 @@ +/** + * @ngdoc overview + * @name superProductvity.routes + * @description + * # superProductvity.routes + * + * Routes module. All app states are defined here. + */ + +(function () { + 'use strict'; + + angular + .module('superProductvity') + .config(routerHelperProvider); + + /* @ngInject */ + function routerHelperProvider($stateProvider, $urlRouterProvider) { + + $urlRouterProvider.otherwise('/'); + + $stateProvider + .state('home', { + url: '/', + template: '

Hello!

All clean here, as intended! Why not build some routes via "yo moda:r my-route"?

' + }) + /* STATES-NEEDLE - DO NOT REMOVE THIS */; + } +})(); diff --git a/app/scripts/routes.spec.js b/app/scripts/routes.spec.js new file mode 100644 index 00000000000..4e8e7e1a778 --- /dev/null +++ b/app/scripts/routes.spec.js @@ -0,0 +1,9 @@ +describe('superProductvity.routes', function () { + 'use strict'; + + beforeEach(module('superProductvity')); + + it('should be defined', function () { + expect(true).toBe(true); + }); +}); diff --git a/app/styles/_functions/_some-function.scss b/app/styles/_functions/_some-function.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/styles/_mixins/_some-mixin.scss b/app/styles/_mixins/_some-mixin.scss new file mode 100644 index 00000000000..c838d88def8 --- /dev/null +++ b/app/styles/_mixins/_some-mixin.scss @@ -0,0 +1,3 @@ +@mixin some-mixin() { + +} diff --git a/app/styles/_placeholders/_some-placeholder.scss b/app/styles/_placeholders/_some-placeholder.scss new file mode 100644 index 00000000000..5fcafcfe637 --- /dev/null +++ b/app/styles/_placeholders/_some-placeholder.scss @@ -0,0 +1,3 @@ +%some-placeholder { + +} diff --git a/app/styles/_variables.scss b/app/styles/_variables.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/styles/base/_buttons.scss b/app/styles/base/_buttons.scss new file mode 100644 index 00000000000..df838df7ea7 --- /dev/null +++ b/app/styles/base/_buttons.scss @@ -0,0 +1,13 @@ +button { + text-align: center; + + &:hover { + + } + &:active { + + } + &:focus { + + } +} diff --git a/app/styles/base/_fonts.scss b/app/styles/base/_fonts.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/styles/base/_forms.scss b/app/styles/base/_forms.scss new file mode 100644 index 00000000000..dab348d8ab7 --- /dev/null +++ b/app/styles/base/_forms.scss @@ -0,0 +1,35 @@ +form { + +} + +fieldset { + +} + +input { + &[type="text"], + &[type="password"], + &[type="email"] { + + } + + &[type="radio"] { + + } + + &[type="checkbox"] { + + } + + &[type="number"] { + + } +} + +select { + +} + +textarea { + +} diff --git a/app/styles/base/_icons.scss b/app/styles/base/_icons.scss new file mode 100644 index 00000000000..b7cb907980f --- /dev/null +++ b/app/styles/base/_icons.scss @@ -0,0 +1,12 @@ +[class^="icon-"], [class*=" icon-"] { + font-family: 'icon-font'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/app/styles/base/_lists.scss b/app/styles/base/_lists.scss new file mode 100644 index 00000000000..cf61e63af86 --- /dev/null +++ b/app/styles/base/_lists.scss @@ -0,0 +1,11 @@ +ul { + li { + + } +} + +ol { + li { + + } +} diff --git a/app/styles/base/_page.scss b/app/styles/base/_page.scss new file mode 100644 index 00000000000..8d3d220c0cb --- /dev/null +++ b/app/styles/base/_page.scss @@ -0,0 +1,26 @@ +* { + // global reset and border-box + &, + &:after, + &:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } +} + +body, +html { + // prevent overflow + width: 100%; + max-width: 100%; + overflow-x: hidden; +} + +main { + +} + +article { + +} diff --git a/app/styles/base/_tables.scss b/app/styles/base/_tables.scss new file mode 100644 index 00000000000..ca43e24aabb --- /dev/null +++ b/app/styles/base/_tables.scss @@ -0,0 +1,23 @@ +table { + +} + +thead { + +} + +tbody { + +} + +tfoot { + +} + +tr { + +} + +td { + +} diff --git a/app/styles/base/_typography.scss b/app/styles/base/_typography.scss new file mode 100644 index 00000000000..bcbdae4ec2b --- /dev/null +++ b/app/styles/base/_typography.scss @@ -0,0 +1,12 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + +} + +p { + +} diff --git a/app/styles/main.scss b/app/styles/main.scss new file mode 100644 index 00000000000..28358ac258d --- /dev/null +++ b/app/styles/main.scss @@ -0,0 +1,36 @@ +/* +IMPORTANT NOTE: + This file SHOULD NOT BE EDITED MANUALLY, as its purpose + is to be the point where all your stylesheet-files will + be imported +*/ + + + +// inject:sass + +@import '_functions/_some-function.scss'; + +@import '_mixins/_some-mixin.scss'; + +@import '_placeholders/_some-placeholder.scss'; + +@import '_variables.scss'; + +@import 'base/_buttons.scss'; + +@import 'base/_fonts.scss'; + +@import 'base/_forms.scss'; + +@import 'base/_icons.scss'; + +@import 'base/_lists.scss'; + +@import 'base/_page.scss'; + +@import 'base/_tables.scss'; + +@import 'base/_typography.scss'; + +// endinject diff --git a/bower.json b/bower.json new file mode 100644 index 00000000000..c71559415d0 --- /dev/null +++ b/bower.json @@ -0,0 +1,31 @@ +{ + "name": "superProductvity", + "version": "0.0.0", + "authors": [ + ], + "license": "none", + "private": true, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "json3": "latest", + "es5-shim": "latest", + "animate.css-scss": "latest", + "angular": "^1.5.0", + "angular-animate": "^1.5.0", + "angular-aria": "^1.5.0", + "angular-resource": "^1.5.0", + "angular-ui-router": "latest" +}, + "devDependencies": { + "angular-mocks": "^1.5.0" + }, + "scripts":{ + "postinstall": "gulp wiredep" + } +} diff --git a/config.xml b/config.xml new file mode 100644 index 00000000000..753e23bbd9b --- /dev/null +++ b/config.xml @@ -0,0 +1,12 @@ + + + Super productvity + + Super productvity is fabulous + + + Your Name + + + + diff --git a/electron/main.js b/electron/main.js new file mode 100644 index 00000000000..0821fbfb8f5 --- /dev/null +++ b/electron/main.js @@ -0,0 +1,104 @@ +'use strict'; + +const electron = require('electron') +// Module to control application life. +const app = electron.app; +// Module to create native browser window. +const BrowserWindow = electron.BrowserWindow; + +const path = require('path'); +const url = require('url'); + +// Keep a global reference of the window object, if you don't, the window will +// be closed automatically when the JavaScript object is garbage collected. +let mainWindow + +function createWindow() { + // Create the browser window. + mainWindow = new BrowserWindow({ width: 800, height: 600 }); + + // and load the index.html of the app. + mainWindow.loadURL(url.format({ + pathname: path.join(__dirname, '../app/index.html'), + protocol: 'file:', + slashes: true + })); + + // Open the DevTools. + mainWindow.webContents.openDevTools(); + + // Emitted when the window is closed. + mainWindow.on('closed', function () { + // Dereference the window object, usually you would store windows + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + mainWindow = null; + }) +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +// Some APIs can only be used after this event occurs. +app.on('ready', createWindow); + +// Quit when all windows are closed. +app.on('window-all-closed', function () { + // On OS X it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +let appIcon = null; +app.on('ready', () => { + console.log(electron.dialog.showOpenDialog({ properties: ['openFile', 'openDirectory', 'multiSelections'] })); + appIcon = new electron.Tray('ico.png'); + let contextMenu = electron.Menu.buildFromTemplate([ + { label: 'Item1', type: 'radio' }, + { label: 'Item2', type: 'radio' }, + { label: 'Item3', type: 'radio', clicked: true }, + { label: 'Item4', type: 'radio' }, + ]); + appIcon.setToolTip('This is my application.'); + appIcon.setContextMenu(contextMenu); + appIcon.setTitle('test'); + + console.log(appIcon.setTitle); + + appIcon.displayBalloon({ + icon: 'ico.png', + title: 'TIIITLE', + content: 'COOOOnten' + }); + // Make a change to the context menu + contextMenu.items[1].checked = false + + // Call this again for Linux because we modified the context menu + appIcon.setContextMenu(contextMenu) +}); + +app.on('ready', () => { + // Register a 'CommandOrControl+X' shortcut listener. + const ret = electron.globalShortcut.register('CommandOrControl+X', () => { + console.log('CommandOrControl+X is pressed'); + }); + + if (!ret) { + console.log('registration failed'); + } + + // Check whether a shortcut is registered. + console.log(electron.globalShortcut.isRegistered('CommandOrControl+X')); +}); + +app.on('activate', function () { + // On OS X it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (mainWindow === null) { + createWindow(); + } +}); + +// In this file you can include the rest of your app's specific main process +// code. You can also put them in separate files and require them here. diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 00000000000..02bef188f06 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,4 @@ +'use strict'; +// require all task files +var requireDir = require('require-dir'); +requireDir('./tasks'); diff --git a/karma-e2e.conf.js b/karma-e2e.conf.js new file mode 100644 index 00000000000..a5cf04ee57f --- /dev/null +++ b/karma-e2e.conf.js @@ -0,0 +1,27 @@ +// An example configuration file. +'use strict'; + +exports.config = { + // The address of a running selenium server. + seleniumAddress: 'http://localhost:4444/wd/hub', + + // Spec patterns are relative to the current working directly when + // protractor is called. + specs: ['e2e-tests/**/*.js'], + + // Options to be passed to Jasmine-node. + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + isVerbose: true + }, + + onPrepare: function() { + browser.manage() + .window() + .setSize(1360, 768); + browser.manage() + .timeouts() + .setScriptTimeout(20000); + } + }; diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 00000000000..dc73888fde7 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,80 @@ +// Karma configuration +'use strict'; + +module.exports = function(config) { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine'], + + + // list of files / patterns to load in the browser + files: [ + // bower:js + 'app/bower_components/angular/angular.js', + 'app/bower_components/angular-animate/angular-animate.js', + 'app/bower_components/angular-aria/angular-aria.js', + 'app/bower_components/angular-resource/angular-resource.js', + 'app/bower_components/angular-ui-router/release/angular-ui-router.js', + 'app/bower_components/angular-mocks/angular-mocks.js', + // endbower + + // modules first + 'app/scripts/**/_*.js', + // all the rest of the files + 'app/scripts/**/*.js', + // load html as well as required for karma-ng-html2js-preprocessor + 'app/scripts/**/*.html' + ], + + + // list of files to exclude + exclude: [], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + plugins: [ + 'karma-jasmine', + //'karma-coverage', + 'karma-phantomjs-launcher', + 'karma-ng-html2js-preprocessor' + ], + + preprocessors: { + //'**/app/scripts/**/!(*spec).js': 'coverage', + '**/app/scripts/**/*.html': 'ng-html2js' + }, + + ngHtml2JsPreprocessor: { + moduleName: 'templates', + stripPrefix: 'app/' + }, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }); + }; diff --git a/package.json b/package.json new file mode 100644 index 00000000000..e74d2b45c66 --- /dev/null +++ b/package.json @@ -0,0 +1,61 @@ +{ + "name": "superProductvity", + "version": "0.0.0", + "description": "", + "main": "gulpfile.js", + "repository": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "electron ./electron/main.js" + }, + "author": "", + "license": "none", + "devDependencies": { + "browser-sync": "latest", + "del": "latest", + "ecstatic": "latest", + "gulp": "latest", + "gulp-autoprefixer": "latest", + "gulp-clean-css": "latest", + "gulp-if": "latest", + "gulp-imagemin": "latest", + "gulp-inject": "latest", + "gulp-jscs": "latest", + "gulp-jshint": "latest", + "gulp-livereload": "latest", + "gulp-minify-html": "latest", + "gulp-natural-sort": "latest", + "gulp-ng-annotate": "latest", + "gulp-ng-config": "latest", + "gulp-plumber": "latest", + "gulp-protractor": "latest", + "gulp-sass": "latest", + "gulp-shell": "latest", + "gulp-sourcemaps": "latest", + "gulp-symlink": "latest", + "gulp-uglify": "latest", + "gulp-useref": "latest", + "gulp-util": "latest", + "gulp-watch": "latest", + "jasmine-core": "latest", + "jshint": "latest", + "jshint-stylish": "latest", + "karma": "latest", + "karma-jasmine": "latest", + "karma-ng-html2js-preprocessor": "latest", + "karma-phantomjs-launcher": "latest", + "lazypipe": "latest", + "merge-stream": "latest", + "node-sass": "latest", + "protractor": "latest", + "phantomjs-prebuilt": "latest", + "require-dir": "latest", + "run-sequence": "latest", + "wiredep": "latest", + "yargs": "latest" + }, + "dependencies": { + "electron": "^1.4.1", + "electron-inspector": "^0.1.4" + } +} diff --git a/tasks/build.js b/tasks/build.js new file mode 100644 index 00000000000..30f2db35ff6 --- /dev/null +++ b/tasks/build.js @@ -0,0 +1,93 @@ +var config = require('./config'); +var gulp = require('gulp'); + +/** + * Build-Task Files + * + * NOTE: Depends on sme of the dev-tasks as well + */ + + +var del = require('del'); +var gulpif = require('gulp-if'); +var minifyHtml = require('gulp-minify-html'); +var cleanCSS = require('gulp-clean-css'); +var useref = require('gulp-useref'); +var sourcemaps = require('gulp-sourcemaps'); +var ngAnnotate = require('gulp-ng-annotate'); +var uglify = require('gulp-uglify'); +var imagemin = require('gulp-imagemin'); +var runSequence = require('run-sequence') + .use(gulp); +var wiredep = require('wiredep').stream; + +var merge = require('merge-stream'); +var lazypipe = require('lazypipe'); + + +// main task +gulp.task('build', function(callback) { + runSequence( + 'cleanDist', + 'wiredepBuild', + 'injectAll', + 'testSingle', + 'lint', + 'sass', + 'minFiles', + 'copy', + // reset config + //'ngConfig', + callback); +}); + +gulp.task('wiredepBuild', function() { + return gulp.src([config.karmaConf, config.mainFile], {base: './'}) + .pipe(wiredep({ + exclude: [ + // TODO inject excluded + ], + devDependencies: false + })) + .pipe(gulp.dest('./')); +}); + +gulp.task('cleanDist', function() { + return del.sync(config.dist); +}); + + +gulp.task('copy', function() { + var html = gulp.src(config.htmlF, {base: config.base}) + .pipe(minifyHtml({ + conditionals: true, + loose: true, + empty: true, + quotes: true + })) + .pipe(gulp.dest(config.dist)); + + var fonts = gulp.src(config.fontsF, {base: config.base}) + .pipe(gulp.dest(config.dist)); + + // TODO this ain't perfect + var images = gulp.src(config.imagesF, {base: config.base}) + .pipe(imagemin({ + progressive: true, + svgoPlugins: [{removeViewBox: false}] + })) + .pipe(gulp.dest(config.dist)); + + return merge(html, fonts, images); +}); + + +gulp.task('minFiles', function() { + return gulp.src(config.mainFile) + .pipe(useref({}, lazypipe() + .pipe(sourcemaps.init, {loadMaps: true}))) + .pipe(gulpif('*.js', ngAnnotate())) + .pipe(gulpif('*.js', uglify({preserveComments: 'license'}))) + .pipe(gulpif('*.css', cleanCSS())) + .pipe(gulp.dest(config.dist)); +}); diff --git a/tasks/config.js b/tasks/config.js new file mode 100644 index 00000000000..fc6e2c9f7d7 --- /dev/null +++ b/tasks/config.js @@ -0,0 +1,56 @@ +module.exports = (function() { + 'use strict'; + + // config vars + var base = './app'; + var scripts = base + '/scripts'; + var sass = base + '/styles'; + + var data = { + browserSyncPort: 3000, + cordovaPath: 'cordova', + defaultPlatform: 'ios', + excludedBowerComponents: ['es5-shim', 'json3'], + base: base, + mainFile: base + '/index.html', + mainSassFile: sass + '/main.scss', + routesFiles: base + '/scripts/_routes.js', + e2eBaseUrl: 'http://localhost:3000/', + styles: base + '/styles/', + stylesF: [ + base + '/styles/**/_*.{scss,sass,less}', + scripts + '/**/*.{scss,sass,less}' + ], + stylesAllF: [ + base + '/styles/**/*.{scss,sass,less}', + scripts + '/**/*.{scss,sass,less}' + ], + scripts: base + '/scripts/', + scriptsF: [ + // modules first + base + '/scripts/**/_*.js', + base + '/scripts/**/*.js', + '!' + base + '/scripts/**/*.spec.js' + ], + scriptsAllF: base + '/scripts/**/*.js', + scriptTestsF: base + '/scripts/**/*.spec.js', + html: base + '/scripts/', + htmlF: [ + base + '/scripts/**/*.html' + ], + images: base + '/images/', + imagesF: base + '/images/**/*.*', + fonts: base + '/fonts/', + fontsF: base + '/fonts/**/*.*', + tmp: './.tmp', + dist: 'www', + wwwDestination: '', + karmaConf: './karma.conf.js', + karmaConfE2E: './karma-e2e.conf.js' + }; + + data.allHtmlF = data.htmlF.slice() + data.allHtmlF.push(data.mainFile); + + return data; +})(); diff --git a/tasks/cordova.js b/tasks/cordova.js new file mode 100644 index 00000000000..0bd6b9d76cb --- /dev/null +++ b/tasks/cordova.js @@ -0,0 +1,108 @@ +var config = require('./config'); +var gulp = require('gulp'); + +/** + * Cordova-Build-Task Files + * + * NOTE: Depends on some of the build-tasks as well + * inspired by: + * @url https://github.com/kamrik/CordovaGulpTemplate + */ + +var plugins = ['org.apache.cordova.file']; + +var path = require('path'); +var shell = require('gulp-shell'); +var runSequence = require('run-sequence') + .use(gulp); +var symlink = require('gulp-symlink'); +var argv = require('yargs').argv; + +var watch = require('gulp-watch'); +var livereload = require('gulp-livereload'); +var http = require('http'); +var ecstatic = require('ecstatic'); +var gutil = require('gulp-util'); +var sass = require('gulp-sass'); + +function platformArg() { + return (argv.platform || config.defaultPlatform); +} + +gulp.task('cordovaDev', function(cb) { + //gulp.start('test'); + + runSequence( + 'cleanDist', + 'symlinkApp', + 'ngConfig', + 'injectAll', + 'buildStyles', + 'browserSync', + 'cordovaServer', + 'cordovaEmulate', + ['watchForCordova', 'watch'], + cb + ); +}); + + +gulp.task('cordovaRun', function(cb) { + runSequence( + 'cleanDist', + 'symlinkApp', + 'ngConfig', + 'injectAll', + 'buildStyles', + 'browserSync', + 'cordovaServer', + 'cordovaRunOnDevice', + ['watchForCordova', 'watch'], + cb + ); +}); + + +gulp.task('watchForCordova', function() { + livereload.listen(); + var projectFiles = config.base + '/**/*.*'; + return gulp.src(projectFiles) + .pipe(watch(projectFiles)) + .pipe(gulp.dest('./platforms/' + platformArg() + '/www/')) + .pipe(livereload()); +}); + + +gulp.task('cordovaServer', function() { + var port = 8000; + var url = "http://localhost:" + port + "/"; + http.createServer(ecstatic({ + root: "platforms", + cache: 0 + })) + .listen(port); + + gutil.log(gutil.colors.blue("HTTP server listening on " + port)); +}); + + +gulp.task('cordovaEmulate', shell.task([ + config.cordovaPath + ' emulate ' + platformArg() + ' -l -s -c' +])); + + +gulp.task('cordovaRunOnDevice', shell.task([ + config.cordovaPath + ' run ' + platformArg() + ' -l -s -c' +])); + + +gulp.task('symlinkApp', function() { + return gulp.src(config.base) + .pipe(symlink(config.dist)); +}); + + +gulp.task('buildCordova', shell.task([ + config.cordovaPath + ' build ' + platformArg() + '' +])); + diff --git a/tasks/deploy.js b/tasks/deploy.js new file mode 100644 index 00000000000..67a884c03d8 --- /dev/null +++ b/tasks/deploy.js @@ -0,0 +1,27 @@ +var config = require('./config'); +var gulp = require('gulp'); +//var rsync = require('rsyncwrapper').rsync; + +/** + * Build-Task Files + * + * NOTE: Hard to make assumptions about this one + * so be creative ;) + */ + +//gulp.task('deploy', function () +//{ +// rsync({ +// ssh: true, +// src: config.dist, +// recursive: true, +// dest: config.wwwDestination, +// syncDest: true, +// args: ['--verbose'] +// }, function (error, stdout, stderr) +// { +// console.log(error); +// console.log(stdout); +// console.log(stderr); +// }); +//}); \ No newline at end of file diff --git a/tasks/dev.js b/tasks/dev.js new file mode 100644 index 00000000000..031e90ecc85 --- /dev/null +++ b/tasks/dev.js @@ -0,0 +1,262 @@ +'use strict'; +/* jshint camelcase: false */ + +var config = require('./config'); +var gulp = require('gulp'); + +/** + * Dev Task File + * + */ + + +var sass = require('gulp-sass').sync; +var autoprefixer = require('gulp-autoprefixer'); +var sourcemaps = require('gulp-sourcemaps'); +var wiredep = require('wiredep').stream; +var inj = require('gulp-inject'); + +var browserSync = require('browser-sync'); +var reload = browserSync.reload; +var watch = require('gulp-watch'); +var runSequence = require('run-sequence') + .use(gulp); + +var jshint = require('gulp-jshint'); +var jscs = require('gulp-jscs'); +var KarmaServer = require('karma').Server; + +// var gulpNgConfig = require('gulp-ng-config'); + +var merge = require('merge-stream'); +var plumber = require('gulp-plumber'); +var sort = require('gulp-natural-sort'); + +// main task +gulp.task('default', function(cb) { + runSequence( + //'ngConfig', + 'wiredep', + 'lint', + 'beautify', + 'injectAll', + 'buildStyles', + 'browserSync', + 'watch', + function() { + // run in parallel but afterwards + gulp.start('test'); + cb(); + } + ); +}); +gulp.task('serve', ['default']); +gulp.task('server', ['default']); + + +gulp.task('injectAll', function(callback) { + runSequence( + 'wiredep', + 'injectScripts', + 'injectStyles', + 'beautify', + callback + ); +}); + + +gulp.task('watch', function(cb) { + watch(config.stylesF, function() { + gulp.start('buildStyles') + .on('end', cb); + }); + watch(config.scriptsF, function() { + gulp.start('injectScripts') + .on('end', cb); + }); + watch(config.scriptsAllF, function() { + gulp.start('lint') + .on('end', cb); + }); + watch(config.allHtmlF, function() { + gulp.start('html') + .on('end', cb); + }); + + //gulp.watch('bower.json', ['wiredep']); + + // enable at your convenience + //watch(config.scripts + '*.json', function() { + // gulp.start('ngConfig') + // .on('end', cb); + //}); +}); + + +gulp.task('buildStyles', function(cb) { + runSequence( + 'injectStyles', + 'sass', + cb + ); +}); + + +gulp.task('injectStyles', function() { + var sources = gulp.src(config.stylesF, {read: false}) + .pipe(sort()); + var target = gulp.src(config.mainSassFile); + var outputFolder = gulp.dest(config.styles); + + return target + .pipe(inj(sources, + { + starttag: '// inject:sass', + endtag: '// endinject', + ignorePath: [config.base.replace('./', ''), 'styles'], + relative: true, + addRootSlash: false, + transform: function(filepath) { + if (filepath) { + return '@import \'' + filepath + '\';'; + } + } + } + )) + .pipe(outputFolder); +}); + + +gulp.task('injectScripts', function() { + var sources = gulp.src(config.scriptsF, {read: true}) + .pipe(sort()); + var target = gulp.src(config.mainFile); + return target + .pipe(inj(sources, + { + ignorePath: config.base.replace('./', ''), + addRootSlash: false + } + )) + .pipe(gulp.dest(config.base)); +}); + + +gulp.task('sass', function() { + var sources = gulp.src(config.mainSassFile); + var outputFolder = gulp.dest(config.styles); + + return sources + .pipe(plumber({ + handleError: function(err) { + console.log(err); + this.emit('end'); + } + })) + .pipe(sourcemaps.init()) + .pipe(sass({errLogToConsole: true})) + .pipe(autoprefixer({ + browsers: ['> 0.1%'] + })) + .pipe(sourcemaps.write('.')) + .pipe(gulp.dest(config.tmp)) + .pipe(outputFolder) + .pipe(browserSync.stream()); +}); + + +gulp.task('browserSync', function() { + browserSync({ + port: config.browserSyncPort, + server: { + baseDir: config.base, + livereload: true + } + }); +}); + + +gulp.task('html', function() { + return gulp.src(config.allHtmlF) + .pipe(reload({stream: true})); +}); + + +gulp.task('wiredep', ['wirdepKarma', 'wiredepIndex']); + +gulp.task('wirdepKarma', function() { + return gulp.src(config.karmaConf, {base: './'}) + .pipe(wiredep({ + devDependencies: true, + exclude: config.excludedBowerComponents + })) + // required as weird workaround for not messing up the files + .pipe(gulp.dest(config.tmp)) + .pipe(gulp.dest('./')); +}); + +gulp.task('wiredepIndex', function() { + return gulp.src(config.mainFile, {base: './'}) + .pipe(wiredep({ + devDependencies: false, + exclude: config.excludedBowerComponents + })) + // required as weird workaround for not messing up the files + .pipe(gulp.dest(config.tmp)) + .pipe(gulp.dest('./')); +}); + + +gulp.task('test', function(done) { + new KarmaServer({ + configFile: __dirname + '/../karma.conf.js', + action: 'watch', + autoWatch: true, + singleRun: false + }, done).start(); +}); + + +gulp.task('testSingle', function(done) { + new KarmaServer({ + configFile: __dirname + '/../karma.conf.js', + action: 'run', + autoWatch: false, + singleRun: true + }, done).start(); +}); + + +gulp.task('lint', function() { + return gulp.src([ + config.scriptsAllF, + './karma-e2e.conf.js', + './karma.conf.js', + './gulpfile.js' + ], {base: './'}) + .pipe(jshint()) + .pipe(jshint.reporter('jshint-stylish')) + .pipe(jscs()); +}); + +gulp.task('beautify', function() { + return gulp.src([ + config.scriptsAllF, + './karma-e2e.conf.js', + './karma.conf.js', + './gulpfile.js' + ], {base: './'}) + .pipe(jscs({fix: true})) + .pipe(gulp.dest('./')); +}); + + +//gulp.task('ngConfig', function () { +// return gulp.src(config.scripts + 'constants.json') +// .pipe(gulpNgConfig('config', { +// wrap: '(function () {\n\'use strict\';\n/*jshint ignore:start*/\n return <%= module %> /*jshint ignore:end*/\n})();', +// environment: 'dev' +// })) +// .pipe(gulp.dest(config.scripts)) +//}); + diff --git a/tasks/e2e.js b/tasks/e2e.js new file mode 100644 index 00000000000..25590e96c46 --- /dev/null +++ b/tasks/e2e.js @@ -0,0 +1,36 @@ +'use strict'; +/* jshint camelcase: false */ + +var config = require('./config'); +var gulp = require('gulp'); + +var protractor = require('gulp-protractor'); +var browserSync = require('browser-sync'); + + +gulp.task('protractor', ['protractor:src']); +gulp.task('e2e', [ + 'browserSync', + 'webdriver-update' +], runProtractor); + + +gulp.task('webdriver-update', protractor.webdriver_update); +gulp.task('webdriver-standalone', protractor.webdriver_standalone); + +function runProtractor(done) { + gulp.src('.nonononoNOTHING') + .pipe(protractor.protractor({ + configFile: './karma-e2e.conf.js' + })) + .on('error', function(err) { + // Make sure failed tests cause gulp to exit non-zero + throw err; + }) + .on('end', function() { + // Close browser sync server + browserSync.exit(); + done(); + }); +} + diff --git a/wallaby.js b/wallaby.js new file mode 100755 index 00000000000..d23a55a6d14 --- /dev/null +++ b/wallaby.js @@ -0,0 +1,52 @@ +// wallaby.conf.js +// for frontend + +var angularTemplatePreprocessor = require('wallaby-ng-html2js-preprocessor'); +module.exports = function() { + return { + files: [ + // bower:js + 'app/bower_components/angular/angular.js', + 'app/bower_components/angular-animate/angular-animate.js', + 'app/bower_components/angular-aria/angular-aria.js', + 'app/bower_components/angular-bootstrap/ui-bootstrap-tpls.js', + 'app/bower_components/angular-resource/angular-resource.js', + 'app/bower_components/respimage/respimage.min.js', + 'app/bower_components/angular-touch/angular-touch.js', + 'app/bower_components/lodash/lodash.js', + 'app/bower_components/fastclick/lib/fastclick.js', + 'app/bower_components/hammerjs/hammer.js', + 'app/bower_components/angular-inview/angular-inview.js', + 'app/bower_components/angular-gestures/dist/gestures.js', + 'app/bower_components/angular-messages/angular-messages.js', + 'app/bower_components/ng-fab-form/dist/ng-fab-form.js', + 'app/bower_components/Stickyfill/dist/stickyfill.js', + 'app/bower_components/waypoints/lib/noframework.waypoints.js', + 'app/bower_components/angular-mocks/angular-mocks.js', + // endbower + + 'app/scripts/**/*.html', + // modules first + 'app/scripts/**/_*.js', + 'app/scripts/**/*.js', + '!app/scripts/styleguide-only.js', + {pattern: 'app/scripts/**/*spec.js', ignore: true} + + ], + tests: [ + 'app/scripts/**/*spec.js' + ], + preprocessors: { + 'app/scripts/**/*.html': function(file) { + return angularTemplatePreprocessor.transform(file, { + // strip this from the file path + stripPrefix: 'app/', + + // setting this option will create only a single module that contains templates + // from all the files, so you can load them all with module('foo') + moduleName: 'templates' + }) + } + } + } +};