├── .bowerrc ├── .editorconfig ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .travis.yml ├── README.md ├── bower.json ├── gulp.config.js ├── gulp.png ├── gulpfile.js ├── jsconfig.json ├── karma.conf.js ├── package.json ├── src ├── client │ ├── app │ │ ├── app.module.js │ │ ├── blocks │ │ │ ├── diagnostics │ │ │ │ ├── diagnostics.decorator.js │ │ │ │ └── diagnostics.module.js │ │ │ ├── exception │ │ │ │ ├── exception-handler.provider.js │ │ │ │ ├── exception-handler.provider.spec.js │ │ │ │ ├── exception.js │ │ │ │ └── exception.module.js │ │ │ ├── logger │ │ │ │ ├── logger.js │ │ │ │ └── logger.module.js │ │ │ └── router │ │ │ │ ├── router-helper.provider.js │ │ │ │ └── router.module.js │ │ ├── core │ │ │ ├── 404.html │ │ │ ├── config.js │ │ │ ├── constants.js │ │ │ ├── core.module.js │ │ │ ├── core.route.js │ │ │ ├── core.route.spec.js │ │ │ ├── dataservice.js │ │ │ └── dataservice.spec.js │ │ ├── customers │ │ │ ├── customer-detail.controller.js │ │ │ ├── customer-detail.controller.spec.js │ │ │ ├── customer-detail.html │ │ │ ├── customers.controller.js │ │ │ ├── customers.controller.spec.js │ │ │ ├── customers.html │ │ │ ├── customers.module.js │ │ │ ├── customers.route.js │ │ │ └── customers.route.spec.js │ │ ├── dashboard │ │ │ ├── dashboard.controller.js │ │ │ ├── dashboard.controller.spec.js │ │ │ ├── dashboard.html │ │ │ ├── dashboard.module.js │ │ │ ├── dashboard.route.js │ │ │ └── dashboard.route.spec.js │ │ ├── layout │ │ │ ├── ht-sidebar.directive.js │ │ │ ├── ht-sidebar.directive.spec.js │ │ │ ├── ht-top-nav.directive.js │ │ │ ├── ht-top-nav.html │ │ │ ├── layout.module.js │ │ │ ├── shell.controller.js │ │ │ ├── shell.controller.spec.js │ │ │ ├── shell.html │ │ │ ├── sidebar.controller.js │ │ │ ├── sidebar.controller.spec.js │ │ │ └── sidebar.html │ │ └── widgets │ │ │ ├── ht-img-person.directive.js │ │ │ ├── ht-widget-header.directive.js │ │ │ ├── widget-header.html │ │ │ └── widgets.module.js │ ├── images │ │ ├── AngularJS-small.png │ │ ├── busy.gif │ │ ├── gulp-tiny.png │ │ └── photos │ │ │ ├── aaron_skonnard.jpg │ │ │ ├── anant-narayanan.png │ │ │ ├── ari-lerner.png │ │ │ ├── ben-clinkinbeard.png │ │ │ ├── ben-teese.png │ │ │ ├── brad_green.jpg │ │ │ ├── brian-ford.png │ │ │ ├── burke-holland.png │ │ │ ├── cat.jpg │ │ │ ├── christian-lilley.png │ │ │ ├── colleen_papa.jpg │ │ │ ├── craig_shoemaker.jpg │ │ │ ├── dan_wahlin.jpg │ │ │ ├── dave-smith.png │ │ │ ├── dave_ward.jpg │ │ │ ├── elijah_manor.jpg │ │ │ ├── eric_barnard.jpg │ │ │ ├── esteban_garcia.jpg │ │ │ ├── felix_fanboi.jpg │ │ │ ├── fritz_onion.jpg │ │ │ ├── glenn_block.jpg │ │ │ ├── hans_fjallemark.jpg │ │ │ ├── howard_dierking.jpg │ │ │ ├── igor_minar.jpg │ │ │ ├── james-deboer.png │ │ │ ├── jason-aden.png │ │ │ ├── jason_salmond.jpg │ │ │ ├── jeff-cross.png │ │ │ ├── jesse_liberty.jpg │ │ │ ├── jim_cowart.jpg │ │ │ ├── john-lindquist.png │ │ │ ├── john_papa.jpg │ │ │ ├── john_smith.jpg │ │ │ ├── john_sonmez.jpg │ │ │ ├── julie-ralph.png │ │ │ ├── julie_lerman.jpg │ │ │ ├── keith_sparkjoy.jpg │ │ │ ├── lukas-ruebbelke.png │ │ │ ├── mads_kristensen.jpg │ │ │ ├── matias-niemela.png │ │ │ ├── max-lynch.png │ │ │ ├── megan_russell.jpg │ │ │ ├── mike_callaghan.jpg │ │ │ ├── mike_woodring.jpg │ │ │ ├── misko-hevery.png │ │ │ ├── pete_brown.jpg │ │ │ ├── rey_bango.jpg │ │ │ ├── rob_eisenberg.jpg │ │ │ ├── ron-evans.png │ │ │ ├── ryan_niemeyer.jpg │ │ │ ├── scott_guthrie.jpg │ │ │ ├── scott_hanselman.jpg │ │ │ ├── scott_hunter.jpg │ │ │ ├── sean-hess.png │ │ │ ├── sharon-diorio.png │ │ │ ├── shawn_wildermuth.jpg │ │ │ ├── silvano-luciani.png │ │ │ ├── steve_sanderson.jpg │ │ │ ├── sue_menot.jpg │ │ │ ├── thomas-burleson.png │ │ │ ├── tim_heuer.jpg │ │ │ ├── unknown_person.jpg │ │ │ ├── vojta-jina.png │ │ │ ├── ward-bell.png │ │ │ └── ward_bell.jpg │ ├── index.html │ ├── specs.html │ ├── stubs │ │ ├── pass-throughs.js │ │ ├── stubs.config.js │ │ └── stubs.js │ ├── styles │ │ └── styles.less │ ├── test-helpers │ │ ├── bind-polyfill.js │ │ └── mock-data.js │ └── tests │ │ └── server-integration │ │ └── dataservice.spec.js └── server │ ├── app.js │ ├── data │ └── customers.json │ ├── favicon.ico │ ├── routes │ └── index.js │ └── utils │ ├── 404.js │ ├── errorHandler.js │ └── jsonfileservice.js ├── tsd.json └── typings ├── angular-ui-router └── angular-ui-router.d.ts ├── angularjs ├── angular-animate.d.ts ├── angular-mocks.d.ts ├── angular-sanitize.d.ts └── angular.d.ts ├── bardjs └── bardjs.d.ts ├── bootstrap └── bootstrap.d.ts ├── chai-shim.d.ts ├── chai └── chai.d.ts ├── jquery └── jquery.d.ts ├── mocha └── mocha.d.ts ├── moment ├── moment-node.d.ts └── moment.d.ts ├── sinon └── sinon.d.ts ├── toastr └── toastr.d.ts └── tsd.d.ts /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "scripts": { 4 | "postinstall": "gulp wiredep" 5 | } 6 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Visual Studio Project # 2 | ################### 3 | *.user 4 | *.gpState 5 | *.suo 6 | bin 7 | obj 8 | /packages 9 | 10 | # Ignore Node, Bower & TSD 11 | ########################## 12 | node_modules 13 | bower_components 14 | #typings 15 | build 16 | .tmp 17 | 18 | # Ignore Test reporters 19 | ################### 20 | **/test/coverage 21 | report 22 | 23 | 24 | # mongo db 25 | ################### 26 | #Don't commit Mongo Database files 27 | *.lock 28 | *.0 29 | *.1 30 | *.ns 31 | journal 32 | 33 | # Ignore Web Storm # 34 | .idea 35 | 36 | # Compiled source # 37 | ################### 38 | *.com 39 | *.class 40 | *.dll 41 | *.exe 42 | *.o 43 | *.so 44 | 45 | # Packages # 46 | ############ 47 | # it's better to unpack these files and commit the raw source 48 | # git has its own built in compression methods 49 | *.7z 50 | *.dmg 51 | *.gz 52 | *.iso 53 | *.jar 54 | *.rar 55 | *.tar 56 | *.xap 57 | *.zip 58 | 59 | # Logs and databases # 60 | ###################### 61 | *.log 62 | *.sql 63 | *.sqlite 64 | # *.sdf 65 | *.mdf 66 | *.ldf 67 | 68 | # OS generated files # 69 | ###################### 70 | .DS_Store* 71 | ehthumbs.db 72 | Icon? 73 | Thumbs.db 74 | 75 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": ["node_modules/**", "bower_components/**"], 3 | 4 | "requireCurlyBraces": [ 5 | "if", 6 | "else", 7 | "for", 8 | "while", 9 | "do", 10 | "try", 11 | "catch" 12 | ], 13 | "requireOperatorBeforeLineBreak": true, 14 | "requireCamelCaseOrUpperCaseIdentifiers": true, 15 | "maximumLineLength": { 16 | "value": 100, 17 | "allowComments": true, 18 | "allowRegex": true 19 | }, 20 | "validateIndentation": 4, 21 | "validateQuoteMarks": "'", 22 | 23 | "disallowMultipleLineStrings": true, 24 | "disallowMixedSpacesAndTabs": true, 25 | "disallowTrailingWhitespace": true, 26 | "disallowSpaceAfterPrefixUnaryOperators": true, 27 | "disallowMultipleVarDecl": null, 28 | 29 | "requireSpaceAfterKeywords": [ 30 | "if", 31 | "else", 32 | "for", 33 | "while", 34 | "do", 35 | "switch", 36 | "return", 37 | "try", 38 | "catch" 39 | ], 40 | "requireSpaceBeforeBinaryOperators": [ 41 | "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", 42 | "&=", "|=", "^=", "+=", 43 | 44 | "+", "-", "*", "/", "%", "<<", ">>", ">>>", "&", 45 | "|", "^", "&&", "||", "===", "==", ">=", 46 | "<=", "<", ">", "!=", "!==" 47 | ], 48 | "requireSpaceAfterBinaryOperators": true, 49 | "requireSpacesInConditionalExpression": true, 50 | "requireSpaceBeforeBlockStatements": true, 51 | "requireLineFeedAtFileEnd": true, 52 | "disallowSpacesInsideObjectBrackets": "all", 53 | "disallowSpacesInsideArrayBrackets": "all", 54 | "disallowSpacesInsideParentheses": true, 55 | 56 | "jsDoc": { 57 | "checkAnnotations": true, 58 | "checkParamNames": true, 59 | "requireParamTypes": true, 60 | "checkReturnTypes": true, 61 | "checkTypes": true 62 | }, 63 | 64 | "disallowMultipleLineBreaks": true, 65 | 66 | "disallowCommaBeforeLineBreak": null, 67 | "disallowDanglingUnderscores": null, 68 | "disallowEmptyBlocks": null, 69 | "disallowMultipleLineStrings": null, 70 | "disallowTrailingComma": null, 71 | "requireCommaBeforeLineBreak": null, 72 | "requireDotNotation": null, 73 | "requireMultipleVarDecl": null, 74 | "requireParenthesesAroundIIFE": true 75 | } 76 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "camelcase": true, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "es3": false, 7 | "forin": true, 8 | "freeze": true, 9 | "immed": true, 10 | "indent": 4, 11 | "latedef": "nofunc", 12 | "newcap": true, 13 | "noarg": true, 14 | "noempty": true, 15 | "nonbsp": true, 16 | "nonew": true, 17 | "plusplus": false, 18 | "quotmark": "single", 19 | "undef": true, 20 | "unused": false, 21 | "strict": false, 22 | "maxparams": 10, 23 | "maxdepth": 5, 24 | "maxstatements": 40, 25 | "maxcomplexity": 8, 26 | "maxlen": 120, 27 | 28 | "asi": false, 29 | "boss": false, 30 | "debug": false, 31 | "eqnull": true, 32 | "esnext": false, 33 | "evil": false, 34 | "expr": false, 35 | "funcscope": false, 36 | "globalstrict": false, 37 | "iterator": false, 38 | "lastsemic": false, 39 | "laxbreak": false, 40 | "laxcomma": false, 41 | "loopfunc": true, 42 | "maxerr": 50, 43 | "moz": false, 44 | "multistr": false, 45 | "notypeof": false, 46 | "proto": false, 47 | "scripturl": false, 48 | "shadow": false, 49 | "sub": true, 50 | "supernew": false, 51 | "validthis": false, 52 | "noyield": false, 53 | 54 | "browser": true, 55 | "node": true, 56 | 57 | "globals": { 58 | "angular": false 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | before_install: 10 | - npm install bower -g 11 | - npm install gulp -g 12 | 13 | script: 14 | - npm install 15 | - bower install 16 | - gulp test --verbose 17 | 18 | cache: 19 | directories: 20 | - bower_components 21 | - node_modules 22 | 23 | notifications: 24 | email: 25 | - wardbell@hotmail.com 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-patterns 2 | You've built your JavaScript application but how do you automate testing, code analysis, running it locally or deploying it? These redundant tasks can consume valuable time and resources. Stop working so hard and take advantage of JavaScript task automation using Gulp to streamline these tasks and give you back more time in the day. Studying this repo can help clarify how Gulp works, jump-start task automation with Gulp, find and resolve issues faster, and be a more productive. 3 | 4 | [![Build Status](https://travis-ci.org/johnpapa/gulp-patterns.svg?branch=master)](https://travis-ci.org/johnpapa/gulp-patterns) 5 | 6 | [![Codeship Status for johnpapa/gulp-patterns](https://codeship.io/projects/46913320-7139-0132-3214-62f5102d8589/status)](https://codeship.io/projects/54583) 7 | 8 | ## Requirements 9 | 10 | - Install Node 11 | - on OSX install [home brew](http://brew.sh/) and type `brew install node` 12 | - on Windows install [chocolatey](https://chocolatey.org/) 13 | - More tips on [Windows with node](http://jpapa.me/winnode) 14 | - open command prompt as administrator 15 | - type `choco install nodejs` 16 | - type `choco install nodejs.install` 17 | - On OSX you can alleviate the need to run as sudo by [following these instructions](http://jpapa.me/nomoresudo). I highly recommend this step on OSX 18 | - Open terminal 19 | - Type `npm install -g node-inspector bower gulp tsd` 20 | 21 | ## Quick Start 22 | Clone this repo and run the content locally 23 | ```bash 24 | $ npm install 25 | $ bower install 26 | $ tsd install -r -o --save 27 | $ gulp serve-dev 28 | ``` 29 | 30 | ## Tasks 31 | 32 | ### Task Listing 33 | 34 | - `gulp help` 35 | 36 | Displays all of the available gulp tasks. 37 | 38 | ### Code Analysis 39 | 40 | - `gulp vet` 41 | 42 | Performs static code analysis on all javascript files. Runs jshint and jscs. 43 | 44 | - `gulp vet --verbose` 45 | 46 | Displays all files affected and extended information about the code analysis. 47 | 48 | - `gulp plato` 49 | 50 | Performs code analysis using plato on all javascript files. Plato generates a report in the reports folder. 51 | 52 | ### Testing 53 | 54 | - `gulp serve-specs` 55 | 56 | Serves and browses to the spec runner html page and runs the unit tests in it. Injects any changes on the fly and re runs the tests. Quick and easy view of tests as an alternative to terminal via `gulp test`. 57 | 58 | - `gulp test` 59 | 60 | Runs all unit tests using karma runner, mocha, chai and sinon with phantomjs. Depends on vet task, for code analysis. 61 | 62 | - `gulp test --startServers` 63 | 64 | Runs all unit tests and midway tests. Cranks up a second node process to run a server for the midway tests to hit a web api. 65 | 66 | - `gulp autotest` 67 | 68 | Runs a watch to run all unit tests. 69 | 70 | - `gulp autotest --startServers` 71 | 72 | Runs a watch to run all unit tests and midway tests. Cranks up a second node process to run a server for the midway tests to hit a web api. 73 | 74 | ### Cleaning Up 75 | 76 | - `gulp clean` 77 | 78 | Remove all files from the build and temp folders 79 | 80 | - `gulp clean-images` 81 | 82 | Remove all images from the build folder 83 | 84 | - `gulp clean-code` 85 | 86 | Remove all javascript and html from the build folder 87 | 88 | - `gulp clean-fonts` 89 | 90 | Remove all fonts from the build folder 91 | 92 | - `gulp clean-styles` 93 | 94 | Remove all styles from the build folder 95 | 96 | ### Fonts and Images 97 | 98 | - `gulp fonts` 99 | 100 | Copy all fonts from source to the build folder 101 | 102 | - `gulp images` 103 | 104 | Copy all images from source to the build folder 105 | 106 | ### Styles 107 | 108 | - `gulp styles` 109 | 110 | Compile less files to CSS, add vendor prefixes, and copy to the build folder 111 | 112 | ### Bower Files 113 | 114 | - `gulp wiredep` 115 | 116 | Looks up all bower components' main files and JavaScript source code, then adds them to the `index.html`. 117 | 118 | The `.bowerrc` file also runs this as a postinstall task whenever `bower install` is run. 119 | 120 | ### Angular HTML Templates 121 | 122 | - `gulp templatecache` 123 | 124 | Create an Angular module that adds all HTML templates to Angular's $templateCache. This pre-fetches all HTML templates saving XHR calls for the HTML. 125 | 126 | - `gulp templatecache --verbose` 127 | 128 | Displays all files affected by the task. 129 | 130 | ### Serving Development Code 131 | 132 | - `gulp serve-dev` 133 | 134 | Serves the development code and launches it in a browser. The goal of building for development is to do it as fast as possible, to keep development moving efficiently. This task serves all code from the source folders and compiles less to css in a temp folder. 135 | 136 | - `gulp serve-dev --nosync` 137 | 138 | Serves the development code without launching the browser. 139 | 140 | - `gulp serve-dev --debug` 141 | 142 | Launch debugger with node-inspector. 143 | 144 | - `gulp serve-dev --debug-brk` 145 | 146 | Launch debugger and break on 1st line with node-inspector. 147 | 148 | - `gulp serve-dev --stubs` 149 | 150 | Serves the development code with the stubs to avoid hitting a real backend 151 | 152 | ### Building Production Code 153 | 154 | - `gulp optimize` 155 | 156 | Optimize all javascript and styles, move to a build folder, and inject them into the new index.html 157 | 158 | - `gulp build` 159 | 160 | Copies all fonts, copies images and runs `gulp optimize` to build the production code to the build folder. 161 | 162 | ### Serving Production Code 163 | 164 | - `gulp serve-build` 165 | 166 | Serve the optimized code from the build folder and launch it in a browser. 167 | 168 | - `gulp serve-build --nosync` 169 | 170 | Serve the optimized code from the build folder and manually launch the browser. 171 | 172 | - `gulp serve-build --debug` 173 | 174 | Launch debugger with node-inspector. 175 | 176 | - `gulp serve-build --debug-brk` 177 | 178 | Launch debugger and break on 1st line with node-inspector. 179 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Gulp-Patterns-Demo", 3 | "version": "0.1.1", 4 | "description": "Gulp Patterns Demo", 5 | "authors": [ 6 | "John Papa" 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/johnpapa/gulp-patterns", 10 | "ignore": [ 11 | "**/.*", 12 | "node_modules", 13 | "bower_components", 14 | "test", 15 | "tests" 16 | ], 17 | "devDependencies": { 18 | "angular-mocks": "~1.3.8", 19 | "sinon": "http://sinonjs.org/releases/sinon-1.12.1.js", 20 | "bardjs": "~0.0.8" 21 | }, 22 | "dependencies": { 23 | "jquery": "~2.1.1", 24 | "angular": "~1.3.8", 25 | "angular-sanitize": "~1.3.8", 26 | "bootstrap": "~3.3.1", 27 | "extras.angular.plus": "~0.9.2", 28 | "font-awesome": "~4.2.0", 29 | "moment": "~2.8.4", 30 | "angular-ui-router": "~0.2.13", 31 | "toastr": "~2.1.0", 32 | "angular-animate": "~1.3.8" 33 | }, 34 | "overrides": { 35 | "bootstrap": { 36 | "main": "dist/css/bootstrap.css", 37 | "dist": "dist/js/bootstrap.js" 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /gulp.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var client = './src/client/'; 3 | var server = './src/server/'; 4 | var clientApp = client + 'app/'; 5 | var report = './report/'; 6 | var root = './'; 7 | var specRunnerFile = 'specs.html'; 8 | var temp = './.tmp/'; 9 | var wiredep = require('wiredep'); 10 | var bowerFiles = wiredep({devDependencies: true})['js']; 11 | var bower = { 12 | json: require('./bower.json'), 13 | directory: './bower_components/', 14 | ignorePath: '../..' 15 | }; 16 | var nodeModules = 'node_modules'; 17 | 18 | var config = { 19 | /** 20 | * File paths 21 | */ 22 | // all javascript that we want to vet 23 | alljs: [ 24 | './src/**/*.js', 25 | './*.js' 26 | ], 27 | build: './build/', 28 | client: client, 29 | css: temp + 'styles.css', 30 | fonts: bower.directory + 'font-awesome/fonts/**/*.*', 31 | html: client + '**/*.html', 32 | htmltemplates: clientApp + '**/*.html', 33 | images: client + 'images/**/*.*', 34 | index: client + 'index.html', 35 | // app js, with no specs 36 | js: [ 37 | clientApp + '**/*.module.js', 38 | clientApp + '**/*.js', 39 | '!' + clientApp + '**/*.spec.js' 40 | ], 41 | jsOrder: [ 42 | '**/app.module.js', 43 | '**/*.module.js', 44 | '**/*.js' 45 | ], 46 | less: client + 'styles/styles.less', 47 | report: report, 48 | root: root, 49 | server: server, 50 | source: 'src/', 51 | stubsjs: [ 52 | bower.directory + 'angular-mocks/angular-mocks.js', 53 | client + 'stubs/**/*.js' 54 | ], 55 | temp: temp, 56 | 57 | /** 58 | * optimized files 59 | */ 60 | optimized: { 61 | app: 'app.js', 62 | lib: 'lib.js' 63 | }, 64 | 65 | /** 66 | * plato 67 | */ 68 | plato: {js: clientApp + '**/*.js'}, 69 | 70 | /** 71 | * browser sync 72 | */ 73 | browserReloadDelay: 1000, 74 | 75 | /** 76 | * template cache 77 | */ 78 | templateCache: { 79 | file: 'templates.js', 80 | options: { 81 | module: 'app.core', 82 | root: 'app/', 83 | standAlone: false 84 | } 85 | }, 86 | 87 | /** 88 | * Bower and NPM files 89 | */ 90 | bower: bower, 91 | packages: [ 92 | './package.json', 93 | './bower.json' 94 | ], 95 | 96 | /** 97 | * specs.html, our HTML spec runner 98 | */ 99 | specRunner: client + specRunnerFile, 100 | specRunnerFile: specRunnerFile, 101 | 102 | /** 103 | * The sequence of the injections into specs.html: 104 | * 1 testlibraries 105 | * mocha setup 106 | * 2 bower 107 | * 3 js 108 | * 4 spechelpers 109 | * 5 specs 110 | * 6 templates 111 | */ 112 | testlibraries: [ 113 | nodeModules + '/mocha/mocha.js', 114 | nodeModules + '/chai/chai.js', 115 | nodeModules + '/sinon-chai/lib/sinon-chai.js' 116 | ], 117 | specHelpers: [client + 'test-helpers/*.js'], 118 | specs: [clientApp + '**/*.spec.js'], 119 | serverIntegrationSpecs: [client + '/tests/server-integration/**/*.spec.js'], 120 | 121 | /** 122 | * Node settings 123 | */ 124 | nodeServer: './src/server/app.js', 125 | defaultPort: '7203' 126 | }; 127 | 128 | /** 129 | * wiredep and bower settings 130 | */ 131 | config.getWiredepDefaultOptions = function() { 132 | var options = { 133 | bowerJson: config.bower.json, 134 | directory: config.bower.directory, 135 | ignorePath: config.bower.ignorePath 136 | }; 137 | return options; 138 | }; 139 | 140 | /** 141 | * karma settings 142 | */ 143 | config.karma = getKarmaOptions(); 144 | 145 | return config; 146 | 147 | //////////////// 148 | 149 | function getKarmaOptions() { 150 | var options = { 151 | files: [].concat( 152 | bowerFiles, 153 | config.specHelpers, 154 | clientApp + '**/*.module.js', 155 | clientApp + '**/*.js', 156 | temp + config.templateCache.file, 157 | config.serverIntegrationSpecs 158 | ), 159 | exclude: [], 160 | coverage: { 161 | dir: report + 'coverage', 162 | reporters: [ 163 | // reporters not supporting the `file` property 164 | {type: 'html', subdir: 'report-html'}, 165 | {type: 'lcov', subdir: 'report-lcov'}, 166 | // reporters supporting the `file` property, use `subdir` to directly 167 | // output them in the `dir` directory. 168 | // omit `file` to output to the console. 169 | // {type: 'cobertura', subdir: '.', file: 'cobertura.txt'}, 170 | // {type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt'}, 171 | // {type: 'teamcity', subdir: '.', file: 'teamcity.txt'}, 172 | //{type: 'text'}, //, subdir: '.', file: 'text.txt'}, 173 | {type: 'text-summary'} //, subdir: '.', file: 'text-summary.txt'} 174 | ] 175 | }, 176 | preprocessors: {} 177 | }; 178 | options.preprocessors[clientApp + '**/!(*.spec)+(.js)'] = ['coverage']; 179 | return options; 180 | } 181 | }; 182 | -------------------------------------------------------------------------------- /gulp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/gulp.png -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES5" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function(config) { 2 | var gulpConfig = require('./gulp.config')(); 3 | 4 | config.set({ 5 | // base path that will be used to resolve all patterns (eg. files, exclude) 6 | basePath: './', 7 | 8 | // frameworks to use 9 | // some available frameworks: https://npmjs.org/browse/keyword/karma-adapter 10 | frameworks: ['mocha', 'chai', 'sinon', 'chai-sinon'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: gulpConfig.karma.files, 14 | 15 | // list of files to exclude 16 | exclude: gulpConfig.karma.exclude, 17 | 18 | proxies: { 19 | '/': 'http://localhost:8888/' 20 | }, 21 | 22 | // preprocess matching files before serving them to the browser 23 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 24 | preprocessors: gulpConfig.karma.preprocessors, 25 | 26 | // test results reporter to use 27 | // possible values: 'dots', 'progress', 'coverage' 28 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 29 | reporters: ['progress', 'coverage'], 30 | 31 | coverageReporter: { 32 | dir: gulpConfig.karma.coverage.dir, 33 | reporters: gulpConfig.karma.coverage.reporters 34 | }, 35 | 36 | // web server port 37 | port: 9876, 38 | 39 | // enable / disable colors in the output (reporters and logs) 40 | colors: true, 41 | 42 | // level of logging 43 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || 44 | // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 45 | logLevel: config.LOG_INFO, 46 | 47 | // enable / disable watching file and executing tests whenever any file changes 48 | autoWatch: true, 49 | 50 | // start these browsers 51 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 52 | // browsers: ['Chrome', 'ChromeCanary', 'FirefoxAurora', 'Safari', 'PhantomJS'], 53 | browsers: ['PhantomJS'], 54 | 55 | // Continuous Integration mode 56 | // if true, Karma captures browsers, runs the tests and exits 57 | singleRun: false 58 | }); 59 | }; 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Gulp-Patterns", 3 | "version": "0.2.0", 4 | "description": "Gulp Patterns", 5 | "authors": [ 6 | "John Papa" 7 | ], 8 | "license": "MIT", 9 | "homepage": "https://github.com/johnpapa/gulp-patterns", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/johnpapa/gulp-patterns.git" 13 | }, 14 | "scripts": { 15 | "init": "npm install", 16 | "install": "bower install && tsd install -r -o --save-dev", 17 | "start": "node src/server/app.js", 18 | "test": "gulp test" 19 | }, 20 | "dependencies": { 21 | "body-parser": "^1.8.2", 22 | "compression": "^1.1.0", 23 | "cors": "^2.2.0", 24 | "express": "^4.9.3", 25 | "morgan": "^1.1.1", 26 | "serve-favicon": "^2.0.1" 27 | }, 28 | "devDependencies": { 29 | "browser-sync": "^2.5.0", 30 | "chai": "^2.2.0", 31 | "chai-as-promised": "^4.3.0", 32 | "chalk": "^1.0.0", 33 | "dateformat": "^1.0.8-1.2.3", 34 | "debug": "^2.1.3", 35 | "del": "^1.1.1", 36 | "glob": "^5.0.3", 37 | "gulp": "^3.8.11", 38 | "gulp-angular-templatecache": "^1.6.0", 39 | "gulp-autoprefixer": "^2.1.0", 40 | "gulp-bump": "^0.3.0", 41 | "gulp-bytediff": "^0.2.1", 42 | "gulp-concat": "^2.5.2", 43 | "gulp-csso": "^1.0.0", 44 | "gulp-filter": "^2.0.2", 45 | "gulp-header": "^1.2.2", 46 | "gulp-if": "^1.2.5", 47 | "gulp-imagemin": "^2.2.1", 48 | "gulp-inject": "^1.2.0", 49 | "gulp-jscs": "^2.0.0", 50 | "gulp-jshint": "^1.7.1", 51 | "gulp-less": "^3.0.2", 52 | "gulp-load-plugins": "^0.9.0", 53 | "gulp-minify-html": "^1.0.1", 54 | "gulp-ng-annotate": "^0.5.2", 55 | "gulp-nodemon": "^2.0.2", 56 | "gulp-order": "^1.1.1", 57 | "gulp-plumber": "^1.0.0", 58 | "gulp-print": "^1.1.0", 59 | "gulp-rev": "^3.0.1", 60 | "gulp-rev-replace": "^0.4.0", 61 | "gulp-sourcemaps": "^1.5.1", 62 | "gulp-task-listing": "^1.0.0", 63 | "gulp-uglify": "^1.0.1", 64 | "gulp-useref": "^1.0.2", 65 | "gulp-util": "^3.0.4", 66 | "jshint-stylish": "^1.0.1", 67 | "karma": "^0.12.32", 68 | "karma-chai": "^0.1.0", 69 | "karma-chai-sinon": "^0.1.3", 70 | "karma-chrome-launcher": "^0.1.4", 71 | "karma-coverage": "^0.2.4", 72 | "karma-firefox-launcher": "^0.1.4", 73 | "karma-growl-reporter": "^0.1.1", 74 | "karma-mocha": "^0.1.4", 75 | "karma-phantomjs-launcher": "^0.1.4", 76 | "karma-safari-launcher": "^0.1.1", 77 | "karma-sinon": "^1.0.3", 78 | "lodash": "^3.6.0", 79 | "method-override": "^2.3.2", 80 | "minimist": "^1.1.1", 81 | "mocha": "^2.2.1", 82 | "node-notifier": "^4.1.2", 83 | "phantomjs": "^1.9.16", 84 | "plato": "^1.4.0", 85 | "q": "^1.2.0", 86 | "sinon": "^1.14.1", 87 | "sinon-chai": "^2.7.0", 88 | "wiredep": "^2.2.2", 89 | "yargs": "^3.6.0" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/client/app/app.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('app', [ 6 | /* Shared modules */ 7 | 'app.core', 8 | 'app.widgets', 9 | 10 | /* Feature areas */ 11 | 'app.customers', 12 | 'app.dashboard', 13 | 'app.layout' 14 | ]); 15 | 16 | })(); 17 | -------------------------------------------------------------------------------- /src/client/app/blocks/diagnostics/diagnostics.decorator.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | var diagnostics = { 5 | enable: true // default 6 | }; 7 | 8 | angular 9 | .module('blocks.diagnostics') 10 | .constant('diagnostics', diagnostics) 11 | .config(bindingDecorator); 12 | 13 | /** 14 | * Add binding diaganostics to the console 15 | * @param {Object} $provide 16 | */ 17 | /* @ngInject */ 18 | bindingDecorator.$inject = ['$provide']; 19 | 20 | function bindingDecorator($provide) { 21 | $provide.decorator('$interpolate', extendInterpolater); 22 | } 23 | 24 | /* @ngInject */ 25 | extendInterpolater.$inject = ['$delegate', '$log', 'diagnostics']; 26 | 27 | function extendInterpolater($delegate, $log, diagnostics) { 28 | if (diagnostics.enable) { 29 | angular.extend(interpolatorWrapper, $delegate); 30 | return interpolatorWrapper; 31 | } 32 | return $delegate; 33 | 34 | //////////////// 35 | 36 | function interpolatorWrapper() { 37 | /* jshint validthis:true */ 38 | var bindingFunction = $delegate.apply(this, arguments); 39 | var bindingExpression = arguments[0]; 40 | if (angular.isFunction(bindingFunction) && bindingExpression) { 41 | return bindingWrapper(bindingFunction, bindingExpression.trim()); 42 | } 43 | return bindingFunction; 44 | 45 | function bindingWrapper(bindingFunction, bindingExpression) { 46 | return bindingInspector; 47 | 48 | function bindingInspector() { 49 | var result = bindingFunction.apply(this, arguments); 50 | var trimmedResult = result.trim(); 51 | var log = trimmedResult ? $log.info : $log.warn; 52 | var msg = 'Binding: ' + 53 | bindingExpression + ' = ' + trimmedResult; 54 | log.call($log, msg); 55 | return result; 56 | } 57 | } 58 | } 59 | 60 | } 61 | })(); 62 | -------------------------------------------------------------------------------- /src/client/app/blocks/diagnostics/diagnostics.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('blocks.diagnostics', []); 5 | })(); 6 | -------------------------------------------------------------------------------- /src/client/app/blocks/exception/exception-handler.provider.js: -------------------------------------------------------------------------------- 1 | // Include in index.html so that app level exceptions are handled. 2 | // Exclude from testRunner.html which should run exactly what it wants to run 3 | (function() { 4 | 'use strict'; 5 | 6 | angular 7 | .module('blocks.exception') 8 | .provider('exceptionHandler', exceptionHandlerProvider) 9 | .config(config); 10 | 11 | /** 12 | * Must configure the exception handling 13 | */ 14 | function exceptionHandlerProvider() { 15 | /* jshint validthis:true */ 16 | this.config = { 17 | appErrorPrefix: undefined 18 | }; 19 | 20 | this.configure = function (appErrorPrefix) { 21 | this.config.appErrorPrefix = appErrorPrefix; 22 | }; 23 | 24 | this.$get = function() { 25 | return {config: this.config}; 26 | }; 27 | } 28 | 29 | /** 30 | * Configure by setting an optional string value for appErrorPrefix. 31 | * Accessible via config.appErrorPrefix (via config value). 32 | * @param {Object} $provide 33 | */ 34 | /* @ngInject */ 35 | function config($provide) { 36 | $provide.decorator('$exceptionHandler', extendExceptionHandler); 37 | } 38 | 39 | /** 40 | * Extend the $exceptionHandler service to also display a toast. 41 | * @param {Object} $delegate 42 | * @param {Object} exceptionHandler 43 | * @param {Object} logger 44 | * @return {Function} the decorated $exceptionHandler service 45 | */ 46 | function extendExceptionHandler($delegate, exceptionHandler, logger) { 47 | return function(exception, cause) { 48 | var appErrorPrefix = exceptionHandler.config.appErrorPrefix || ''; 49 | var errorData = {exception: exception, cause: cause}; 50 | exception.message = appErrorPrefix + exception.message; 51 | $delegate(exception, cause); 52 | /** 53 | * Could add the error to a service's collection, 54 | * add errors to $rootScope, log errors to remote web server, 55 | * or log locally. Or throw hard. It is entirely up to you. 56 | * throw exception; 57 | * 58 | * @example 59 | * throw { message: 'error message we added' }; 60 | */ 61 | logger.error(exception.message, errorData); 62 | }; 63 | } 64 | })(); 65 | -------------------------------------------------------------------------------- /src/client/app/blocks/exception/exception-handler.provider.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('blocks.exception', function() { 3 | var exceptionHandlerProvider; 4 | var mocks = { 5 | errorMessage: 'fake error', 6 | prefix: '[TEST]: ' 7 | }; 8 | 9 | beforeEach(function() { 10 | bard.appModule('blocks.exception', function(_exceptionHandlerProvider_) { 11 | exceptionHandlerProvider = _exceptionHandlerProvider_; 12 | }); 13 | bard.inject(this, '$rootScope'); 14 | }); 15 | 16 | bard.verifyNoOutstandingHttpRequests(); 17 | 18 | describe('$exceptionHandler', function() { 19 | it('should have a dummy test', inject(function() { 20 | expect(true).to.equal(true); 21 | })); 22 | 23 | it('should be defined', inject(function($exceptionHandler) { 24 | expect($exceptionHandler).to.be.defined; 25 | })); 26 | 27 | it('should have configuration', inject(function($exceptionHandler) { 28 | expect($exceptionHandler.config).to.be.defined; 29 | })); 30 | 31 | describe('with appErrorPrefix', function() { 32 | beforeEach(function() { 33 | exceptionHandlerProvider.configure(mocks.prefix); 34 | }); 35 | 36 | it('should have exceptionHandlerProvider defined', inject(function() { 37 | expect(exceptionHandlerProvider).to.be.defined; 38 | })); 39 | 40 | it('should have appErrorPrefix defined', inject(function() { 41 | expect(exceptionHandlerProvider.$get().config.appErrorPrefix).to.be.defined; 42 | })); 43 | 44 | it('should have appErrorPrefix set properly', inject(function() { 45 | expect(exceptionHandlerProvider.$get().config.appErrorPrefix) 46 | .to.equal(mocks.prefix); 47 | })); 48 | 49 | it('should throw an error when forced', inject(function() { 50 | expect(functionThatWillThrow).to.throw(); 51 | })); 52 | 53 | it('manual error is handled by decorator', function() { 54 | var exception; 55 | exceptionHandlerProvider.configure(mocks.prefix); 56 | try { 57 | $rootScope.$apply(functionThatWillThrow); 58 | } 59 | catch (ex) { 60 | exception = ex; 61 | expect(ex.message).to.equal(mocks.prefix + mocks.errorMessage); 62 | } 63 | }); 64 | }); 65 | }); 66 | 67 | function functionThatWillThrow() { 68 | throw new Error(mocks.errorMessage); 69 | } 70 | }); 71 | -------------------------------------------------------------------------------- /src/client/app/blocks/exception/exception.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('blocks.exception') 6 | .factory('exception', exception); 7 | 8 | /* @ngInject */ 9 | function exception($q, logger) { 10 | var service = { 11 | catcher: catcher 12 | }; 13 | return service; 14 | 15 | function catcher(message) { 16 | return function(e) { 17 | var thrownDescription; 18 | var newMessage; 19 | if (e.data && e.data.description) { 20 | thrownDescription = '\n' + e.data.description; 21 | newMessage = message + thrownDescription; 22 | } 23 | e.data.description = newMessage; 24 | logger.error(newMessage); 25 | return $q.reject(e); 26 | }; 27 | } 28 | } 29 | })(); 30 | -------------------------------------------------------------------------------- /src/client/app/blocks/exception/exception.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('blocks.exception', ['blocks.logger']); 5 | })(); 6 | -------------------------------------------------------------------------------- /src/client/app/blocks/logger/logger.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('blocks.logger') 6 | .factory('logger', logger); 7 | 8 | logger.$inject = ['$log', 'toastr']; 9 | 10 | function logger($log, toastr) { 11 | var service = { 12 | showToasts: true, 13 | 14 | error : error, 15 | info : info, 16 | success : success, 17 | warning : warning, 18 | 19 | // straight to console; bypass toastr 20 | log : $log.log 21 | }; 22 | 23 | return service; 24 | ///////////////////// 25 | 26 | function error(message, data, title) { 27 | toastr.error(message, title); 28 | $log.error('Error: ' + message, data); 29 | } 30 | 31 | function info(message, data, title) { 32 | toastr.info(message, title); 33 | $log.info('Info: ' + message, data); 34 | } 35 | 36 | function success(message, data, title) { 37 | toastr.success(message, title); 38 | $log.info('Success: ' + message, data); 39 | } 40 | 41 | function warning(message, data, title) { 42 | toastr.warning(message, title); 43 | $log.warn('Warning: ' + message, data); 44 | } 45 | } 46 | }()); 47 | -------------------------------------------------------------------------------- /src/client/app/blocks/logger/logger.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('blocks.logger', []); 5 | })(); 6 | -------------------------------------------------------------------------------- /src/client/app/blocks/router/router-helper.provider.js: -------------------------------------------------------------------------------- 1 | /* Help configure the state-base ui.router */ 2 | (function() { 3 | 'use strict'; 4 | 5 | angular 6 | .module('blocks.router') 7 | .provider('routerHelper', routerHelperProvider); 8 | 9 | routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider']; 10 | /* @ngInject */ 11 | function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) { 12 | /* jshint validthis:true */ 13 | var config = { 14 | docTitle: undefined, 15 | resolveAlways: {} 16 | }; 17 | 18 | $locationProvider.html5Mode(true); 19 | 20 | this.configure = function(cfg) { 21 | angular.extend(config, cfg); 22 | }; 23 | 24 | this.$get = RouterHelper; 25 | RouterHelper.$inject = ['$location', '$rootScope', '$state', 'logger']; 26 | /* @ngInject */ 27 | function RouterHelper($location, $rootScope, $state, logger) { 28 | var handlingStateChangeError = false; 29 | var hasOtherwise = false; 30 | var stateCounts = { 31 | errors: 0, 32 | changes: 0 33 | }; 34 | 35 | var service = { 36 | configureStates: configureStates, 37 | getStates: getStates, 38 | stateCounts: stateCounts 39 | }; 40 | 41 | init(); 42 | 43 | return service; 44 | 45 | /////////////// 46 | 47 | function configureStates(states, otherwisePath) { 48 | states.forEach(function(state) { 49 | state.config.resolve = 50 | angular.extend(state.config.resolve || {}, config.resolveAlways); 51 | $stateProvider.state(state.state, state.config); 52 | }); 53 | if (otherwisePath && !hasOtherwise) { 54 | hasOtherwise = true; 55 | $urlRouterProvider.otherwise(otherwisePath); 56 | } 57 | } 58 | 59 | function handleRoutingErrors() { 60 | // Route cancellation: 61 | // On routing error, go to the dashboard. 62 | // Provide an exit clause if it tries to do it twice. 63 | $rootScope.$on('$stateChangeError', 64 | function(event, toState, toParams, fromState, fromParams, error) { 65 | if (handlingStateChangeError) { 66 | return; 67 | } 68 | stateCounts.errors++; 69 | handlingStateChangeError = true; 70 | var destination = (toState && 71 | (toState.title || toState.name || toState.loadedTemplateUrl)) || 72 | 'unknown target'; 73 | var msg = 'Error routing to ' + destination + '. ' + 74 | (error.data || '') + '.
' + (error.statusText || '') + 75 | ': ' + (error.status || ''); 76 | logger.warning(msg, [toState]); 77 | $location.path('/'); 78 | } 79 | ); 80 | } 81 | 82 | function init() { 83 | handleRoutingErrors(); 84 | updateDocTitle(); 85 | } 86 | 87 | function getStates() { return $state.get(); } 88 | 89 | function updateDocTitle() { 90 | $rootScope.$on('$stateChangeSuccess', 91 | function(event, toState, toParams, fromState, fromParams) { 92 | stateCounts.changes++; 93 | handlingStateChangeError = false; 94 | var title = config.docTitle + ' ' + (toState.title || ''); 95 | $rootScope.title = title; // data bind to 96 | } 97 | ); 98 | } 99 | } 100 | } 101 | })(); 102 | -------------------------------------------------------------------------------- /src/client/app/blocks/router/router.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('blocks.router', [ 5 | 'ui.router', 6 | 'blocks.logger' 7 | ]); 8 | })(); 9 | -------------------------------------------------------------------------------- /src/client/app/core/404.html: -------------------------------------------------------------------------------- 1 | <section id="dashboard-view" class="mainbar"> 2 | <section class="matter"> 3 | <div class="container"> 4 | <div class="row"> 5 | <div class="col-md-12"> 6 | <ul class="today-datas"> 7 | <li class="bred"> 8 | <div class="pull-left"><i class="fa fa-warning"></i></div> 9 | <div class="datas-text pull-right"> 10 | <a><span class="bold">404</span></a>Page Not Found 11 | </div> 12 | <div class="clearfix"></div> 13 | </li> 14 | </ul> 15 | </div> 16 | </div> 17 | <div class="row"> 18 | <div class="widget wblue"> 19 | <div ht-widget-header title="Page Not Found" 20 | allow-collapse="true"></div> 21 | <div class="widget-content text-center text-info"> 22 | <div class="container"> 23 | No soup for you! 24 | </div> 25 | </div> 26 | <div class="widget-foot"> 27 | <div class="clearfix"></div> 28 | </div> 29 | </div> 30 | </div> 31 | </div> 32 | </div> 33 | </section> 34 | </section> 35 | -------------------------------------------------------------------------------- /src/client/app/core/config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | var core = angular.module('app.core'); 5 | 6 | core.config(toastrConfig); 7 | 8 | /* @ngInject */ 9 | function toastrConfig(toastr) { 10 | toastr.options.timeOut = 4000; 11 | toastr.options.positionClass = 'toast-bottom-right'; 12 | } 13 | 14 | var config = { 15 | appErrorPrefix: '[GulpPatterns Error] ', //Configure the exceptionHandler decorator 16 | appTitle: 'Gulp Patterns Demo', 17 | imageBasePath: '/images/photos/', 18 | unknownPersonImageSource: 'unknown_person.jpg' 19 | }; 20 | 21 | core.value('config', config); 22 | 23 | core.config(configure); 24 | 25 | configure.$inject = ['$compileProvider', '$logProvider', 26 | 'diagnostics', 'exceptionHandlerProvider', 'routerHelperProvider']; 27 | /* @ngInject */ 28 | function configure ($compileProvider, $logProvider, 29 | diagnostics, exceptionHandlerProvider, routerHelperProvider) { 30 | 31 | diagnostics.enable = false; 32 | 33 | $compileProvider.debugInfoEnabled(false); 34 | 35 | // turn debugging off/on (no info or warn) 36 | if ($logProvider.debugEnabled) { 37 | $logProvider.debugEnabled(true); 38 | } 39 | exceptionHandlerProvider.configure(config.appErrorPrefix); 40 | configureStateHelper(); 41 | 42 | //////////////// 43 | 44 | function configureStateHelper() { 45 | var resolveAlways = { /* @ngInject */ 46 | ready: function(dataservice) { 47 | return dataservice.ready(); 48 | } 49 | }; 50 | 51 | routerHelperProvider.configure({ 52 | docTitle: 'Gulp: ', 53 | resolveAlways: resolveAlways 54 | }); 55 | } 56 | } 57 | })(); 58 | -------------------------------------------------------------------------------- /src/client/app/core/constants.js: -------------------------------------------------------------------------------- 1 | /* global toastr:false, moment:false */ 2 | (function() { 3 | 'use strict'; 4 | 5 | angular 6 | .module('app.core') 7 | .constant('toastr', toastr) 8 | .constant('moment', moment); 9 | })(); 10 | -------------------------------------------------------------------------------- /src/client/app/core/core.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.core', [ 6 | /* Angular modules */ 7 | 'ngAnimate', 8 | 'ngSanitize', 9 | /* Cross-app modules */ 10 | 'blocks.diagnostics', 11 | 'blocks.exception', 12 | 'blocks.logger', 13 | 'blocks.router', 14 | /* 3rd-party modules */ 15 | 'ui.router', 16 | 'ngplus' 17 | ]); 18 | 19 | })(); 20 | -------------------------------------------------------------------------------- /src/client/app/core/core.route.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.core') 6 | .run(appRun); 7 | 8 | /* @ngInject */ 9 | function appRun(routerHelper) { 10 | var otherwise = '/404'; 11 | routerHelper.configureStates(getStates(), otherwise); 12 | } 13 | 14 | function getStates() { 15 | return [ 16 | { 17 | state: '404', 18 | config: { 19 | url: '/404', 20 | templateUrl: 'app/core/404.html', 21 | title: '404' 22 | } 23 | } 24 | ]; 25 | } 26 | })(); 27 | -------------------------------------------------------------------------------- /src/client/app/core/core.route.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('core', function() { 3 | describe('state', function() { 4 | var views = { 5 | four0four: 'app/core/404.html' 6 | }; 7 | 8 | beforeEach(function() { 9 | module('app.core', bard.fakeToastr); 10 | bard.inject(this, '$location', '$rootScope', '$state', '$templateCache'); 11 | $templateCache.put(views.core, ''); 12 | }); 13 | 14 | it('should map /404 route to 404 View template', function() { 15 | expect($state.get('404').templateUrl).to.equal(views.four0four); 16 | }); 17 | 18 | it('of dashboard should work with $state.go', function() { 19 | $state.go('404'); 20 | $rootScope.$apply(); 21 | expect($state.is('404')); 22 | }); 23 | 24 | it('should route /invalid to the otherwise (404) route', function() { 25 | $location.path('/invalid'); 26 | $rootScope.$apply(); 27 | expect($state.current.templateUrl).to.equal(views.four0four); 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/client/app/core/dataservice.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.core') 6 | .factory('dataservice', dataservice); 7 | 8 | /* @ngInject */ 9 | function dataservice($http, $location, $q, exception, logger) { 10 | /* jshint validthis:true */ 11 | var readyPromise; 12 | 13 | var service = { 14 | getCustomer: getCustomer, 15 | getCustomers: getCustomers, 16 | ready: ready 17 | }; 18 | 19 | return service; 20 | 21 | function getCustomer(id) { 22 | return $http.get('/api/customer/' + id) 23 | .then(getCustomerComplete) 24 | .catch(getCustomerFailed); 25 | 26 | function getCustomerComplete(data, status, headers, config) { 27 | return data.data; 28 | } 29 | 30 | function getCustomerFailed(e) { 31 | $location.url('/'); 32 | return exception.catcher('XHR Failed for getCustomer')(e); 33 | } 34 | } 35 | 36 | function getCustomers() { 37 | return $http.get('/api/customers') 38 | .then(getCustomersComplete) 39 | .catch(getCustomersFailed); 40 | 41 | function getCustomersComplete(data, status, headers, config) { 42 | return data.data; 43 | } 44 | 45 | function getCustomersFailed(e) { 46 | $location.url('/'); 47 | return exception.catcher('XHR Failed for getCustomers')(e); 48 | } 49 | } 50 | 51 | function getReady() { 52 | if (!readyPromise) { 53 | // Apps often pre-fetch session data ("prime the app") 54 | // before showing the first view. 55 | // This app doesn't need priming but we add a 56 | // no-op implementation to show how it would work. 57 | logger.info('Primed the app data'); 58 | readyPromise = $q.when(service); 59 | } 60 | return readyPromise; 61 | } 62 | 63 | function ready(promisesArray) { 64 | return getReady() 65 | .then(function() { 66 | return promisesArray ? $q.all(promisesArray) : readyPromise; 67 | }) 68 | .catch(exception.catcher('"ready" function failed')); 69 | } 70 | } 71 | })(); 72 | -------------------------------------------------------------------------------- /src/client/app/core/dataservice.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('dataservice', function() { 3 | var customers = mockData.getMockCustomers(); 4 | var $httpFlush; 5 | 6 | beforeEach(function() { 7 | bard.appModule('app.core'); 8 | bard.inject(this, '$httpBackend', '$rootScope', 'dataservice'); 9 | }); 10 | 11 | beforeEach(function() { 12 | $httpBackend.when('GET', '/api/customers').respond(200, customers); 13 | $httpFlush = $httpBackend.flush; 14 | }); 15 | 16 | bard.verifyNoOutstandingHttpRequests(); 17 | 18 | it('should be registered', function() { 19 | expect(dataservice).not.to.equal(null); 20 | }); 21 | 22 | describe('getCustomers function', function() { 23 | it('should exist', function() { 24 | expect(dataservice.getCustomers).not.to.equal(null); 25 | }); 26 | 27 | it('should return 5 Customers', function(done) { 28 | dataservice.getCustomers().then(function(data) { 29 | expect(data.length).to.equal(5); 30 | }).then(done, done); 31 | $httpFlush(); 32 | }); 33 | 34 | it('should contain Black Widow', function(done) { 35 | dataservice.getCustomers().then(function(data) { 36 | var hasBlackWidow = data.some(function isPrime(element, index, array) { 37 | return element.firstName.indexOf('Black') >= 0; 38 | }); 39 | expect(hasBlackWidow).to.be.true; 40 | }).then(done, done); 41 | $httpFlush(); 42 | }); 43 | }); 44 | 45 | describe('ready function', function() { 46 | it('should exist', function() { 47 | expect(dataservice.ready).to.be.defined; 48 | }); 49 | 50 | it('should return a resolved promise with the dataservice itself', function(done) { 51 | dataservice.ready().then(function(data) { 52 | expect(data).to.equal(dataservice); 53 | }) 54 | .then(done, done); 55 | $rootScope.$apply(); // no $http so just flush 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /src/client/app/customers/customer-detail.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.customers') 6 | .controller('CustomerDetail', CustomerDetail); 7 | 8 | /* @ngInject */ 9 | function CustomerDetail($stateParams, $window, dataservice, logger) { 10 | var vm = this; 11 | vm.cancel = cancel; 12 | vm.customer = undefined; 13 | vm.goBack = goBack; 14 | vm.isUnchanged = isUnchanged; 15 | vm.getFullName = getFullName; 16 | vm.save = save; 17 | vm.title = 'Customer Detail'; 18 | 19 | activate(); 20 | 21 | function activate() { 22 | return getCustomer($stateParams.id).then(function() { 23 | logger.info('Activated Customer Detail View'); 24 | }); 25 | } 26 | 27 | function cancel() { 28 | vm.customer = angular.copy(vm.original); 29 | } 30 | 31 | function getCustomer(id) { 32 | return dataservice.getCustomer(id).then(function(data) { 33 | vm.customer = data; 34 | vm.original = angular.copy(vm.customer); 35 | return vm.customer; 36 | }); 37 | } 38 | 39 | function goBack() { 40 | $window.history.back(); 41 | } 42 | 43 | function isUnchanged() { 44 | return angular.equals(vm.customer, vm.original); 45 | } 46 | 47 | function getFullName() { 48 | return vm.customer && vm.customer.firstName + ' ' + vm.customer.lastName; 49 | } 50 | 51 | function save() { 52 | vm.original = angular.copy(vm.customer); 53 | logger.success('Saving Customer (not really)'); 54 | } 55 | } 56 | })(); 57 | -------------------------------------------------------------------------------- /src/client/app/customers/customer-detail.controller.spec.js: -------------------------------------------------------------------------------- 1 | 2 | /* jshint -W117, -W030 */ 3 | describe('app.customers', function() { 4 | var controller; 5 | var customers = mockData.getMockCustomers(); 6 | var id = mockData.blackWidow.id; 7 | 8 | beforeEach(function() { 9 | bard.appModule('app.customers'); 10 | bard.inject(this, '$controller', '$log', '$q', '$rootScope', '$stateParams', 'dataservice'); 11 | }); 12 | 13 | beforeEach(function() { 14 | sinon.stub(dataservice, 'getCustomer') 15 | .returns($q.when(mockData.blackWidow)) 16 | .withArgs(id); 17 | controller = $controller('CustomerDetail'); 18 | $rootScope.$apply(); 19 | }); 20 | 21 | bard.verifyNoOutstandingHttpRequests(); 22 | 23 | describe('CustomerDetail controller', function() { 24 | it('should be created successfully', function() { 25 | expect(controller).to.be.defined; 26 | }); 27 | 28 | describe('after activate', function() { 29 | describe('should have called dataservice.getCustomer', function() { 30 | beforeEach(function() { 31 | $stateParams.id = id; 32 | }); 33 | 34 | it('1 time', function() { 35 | expect(dataservice.getCustomer).to.have.been.calledOnce; 36 | }); 37 | 38 | it('with id ' + id, function() { 39 | expect(dataservice.getCustomer).to.have.been.calledWith(id); 40 | }); 41 | }); 42 | 43 | it('should have title of Customer Detail', function() { 44 | expect(controller.title).to.equal('Customer Detail'); 45 | }); 46 | 47 | it('should have a Customer', function() { 48 | expect(controller.customer).to.be.defined; 49 | }); 50 | 51 | it('should have a requested Customer', function() { 52 | var name = controller.customer.firstName + ' ' + controller.customer.lastName; 53 | expect(name).to.be.equal('Black Widow'); 54 | }); 55 | 56 | it('should have logged "Activated"', function() { 57 | expect($log.info.logs).to.match(/Activated/); 58 | }); 59 | }); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /src/client/app/customers/customer-detail.html: -------------------------------------------------------------------------------- 1 | <section class="mainbar"> 2 | <section class="matter"> 3 | <div class="container"> 4 | <div> 5 | <button class="btn btn-info btn-form-md" 6 | ng-click="vm.goBack()"> 7 | <i class="fa fa-hand-o-left"></i>Back 8 | </button> 9 | <button class="btn btn-info btn-form-md" 10 | ng-click="vm.cancel()" 11 | ng-disabled="vm.isUnchanged()"> 12 | <i class="fa fa-undo"></i>Cancel 13 | </button> 14 | <button class="btn btn-info btn-form-md" 15 | ng-click="vm.save()" 16 | ng-disabled="form.$invalid || vm.isUnchanged()"> 17 | <i class="fa fa-save"></i>Save 18 | </button> 19 | 20 | <!--Need ng-hide for show/hide animations--> 21 | <span ng-hide="vm.isUnchanged()" class="dissolve-animation ng-hide flag-haschanges"> 22 | <i class="fa fa-asterisk fa fa-asterisk-large" rel="tooltip" title="You have changes"></i> 23 | </span> 24 | </div> 25 | <div class="widget wblue"> 26 | <div ht-widget-header title="Edit {{vm.getFullName() || 'New Customer'}}"></div> 27 | <div class="widget-content user"> 28 | <div class="form-group"> 29 | <label class="control-label">ID: </label> 30 | <label class="control-label">{{vm.customer.id}}</label> 31 | </div> 32 | <div class="form-group"> 33 | <label class="control-label">First Name</label> 34 | <div> 35 | <input class="form-control" 36 | ng-model="vm.customer.firstName" 37 | placeholder="First Name"/> 38 | </div> 39 | </div> 40 | <div class="form-group"> 41 | <label class="control-label">Last Name</label> 42 | <div> 43 | <input class="form-control" 44 | ng-model="vm.customer.lastName" 45 | placeholder="Last Name"/> 46 | </div> 47 | </div> 48 | <div class="form-group"> 49 | <label class="control-label">City</label> 50 | <div> 51 | <input class="form-control" 52 | ng-model="vm.customer.city" 53 | placeholder="City"/> 54 | </div> 55 | </div> 56 | <div class="form-group"> 57 | <label class="control-label">State</label> 58 | <div> 59 | <input class="form-control" 60 | ng-model="vm.customer.state" 61 | placeholder="State"/> 62 | </div> 63 | </div> 64 | <div class="form-group"> 65 | <label class="control-label">Postal Code</label> 66 | <div> 67 | <input class="form-control" 68 | ng-model="vm.customer.zip" 69 | placeholder="Postal Code"/> 70 | </div> 71 | </div> 72 | <div class="form-group"> 73 | <img ht-img-person="{{vm.customer.thumbnail}}" class="img-thumbnail"/> 74 | </div> 75 | </div> 76 | </div> 77 | </div> 78 | </section> 79 | </section> 80 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.controller.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.customers') 6 | .controller('Customers', Customers); 7 | 8 | /* @ngInject */ 9 | function Customers($state, dataservice, logger) { 10 | var vm = this; 11 | vm.customers = []; 12 | vm.gotoCustomer = gotoCustomer; 13 | vm.title = 'Customers'; 14 | 15 | activate(); 16 | 17 | function activate() { 18 | return getCustomers().then(function () { 19 | logger.info('Activated Customers View'); 20 | }); 21 | } 22 | 23 | function getCustomers() { 24 | return dataservice.getCustomers().then(function (data) { 25 | vm.customers = data; 26 | return vm.customers; 27 | }); 28 | } 29 | 30 | function gotoCustomer(c) { 31 | $state.go('customer.detail', { 32 | id: c.id 33 | }); 34 | } 35 | } 36 | })(); 37 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.controller.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('app.customers', function() { 3 | var controller; 4 | var customers = mockData.getMockCustomers(); 5 | 6 | beforeEach(function() { 7 | bard.appModule('app.customers'); 8 | bard.inject(this, '$controller', '$log', '$q', '$rootScope', 'dataservice'); 9 | }); 10 | 11 | beforeEach(function() { 12 | sinon.stub(dataservice, 'getCustomers').returns($q.when(customers)); 13 | controller = $controller('Customers'); 14 | $rootScope.$apply(); 15 | }); 16 | 17 | bard.verifyNoOutstandingHttpRequests(); 18 | 19 | describe('Customers controller', function() { 20 | it('should be created successfully', function () { 21 | expect(controller).to.be.defined; 22 | }); 23 | 24 | describe('after activate', function() { 25 | it('should have called dataservice.getCustomers 1 time', function () { 26 | expect(dataservice.getCustomers).to.have.been.calledOnce; 27 | }); 28 | 29 | it('should have title of Customers', function() { 30 | expect(controller.title).to.equal('Customers'); 31 | }); 32 | 33 | it('should have 5 Customers', function() { 34 | expect(controller.customers).to.have.length(5); 35 | }); 36 | 37 | it('should have logged "Activated"', function() { 38 | expect($log.info.logs).to.match(/Activated/); 39 | }); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.html: -------------------------------------------------------------------------------- 1 | <section class="mainbar"> 2 | <section class="matter"> 3 | <div class="container"> 4 | <div class="row"> 5 | <div class="widget wblue"> 6 | <div ht-widget-header title="{{vm.title}}"></div> 7 | <div class="widget-content user"> 8 | <input ng-model="vm.filter" placeholder="Find customers" type="search"/> 9 | <table class="table table-condensed table-hover"> 10 | <thead> 11 | <tr> 12 | <th>Customer</th> 13 | <th>City</th> 14 | <th>State</th> 15 | </tr> 16 | </thead> 17 | <tbody> 18 | <tr ng-repeat="c in vm.customers | filter:vm.filter track by c.id" 19 | ng-click="vm.gotoCustomer(c)"> 20 | <td>{{c.firstName + ' ' + c.lastName}}</td> 21 | <td>{{c.city}}</td> 22 | <td>{{c.state}}</td> 23 | </tr> 24 | </tbody> 25 | </table> 26 | </div> 27 | <div class="widget-foot"> 28 | <div class="clearfix"></div> 29 | </div> 30 | </div> 31 | </div> 32 | </div> 33 | </section> 34 | </section> 35 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.customers', [ 5 | 'app.core', 6 | 'app.widgets' 7 | ]); 8 | 9 | })(); 10 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.route.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.customers') 6 | .run(appRun); 7 | 8 | /* @ngInject */ 9 | function appRun(routerHelper) { 10 | routerHelper.configureStates(getStates()); 11 | } 12 | 13 | function getStates() { 14 | return [ 15 | { 16 | state: 'customer', 17 | config: { 18 | abstract: true, 19 | template: '<ui-view class="shuffle-animation"/>', 20 | url: '/customer' 21 | } 22 | }, 23 | { 24 | state: 'customer.list', 25 | config: { 26 | url: '/list', 27 | templateUrl: 'app/customers/customers.html', 28 | controller: 'Customers', 29 | controllerAs: 'vm', 30 | title: 'Customers', 31 | settings: { 32 | nav: 2, 33 | content: '<i class="fa fa-group"></i> Customers' 34 | } 35 | } 36 | }, 37 | { 38 | state: 'customer.detail', 39 | config: { 40 | url: '/:id', 41 | templateUrl: 'app/customers/customer-detail.html', 42 | controller: 'CustomerDetail', 43 | controllerAs: 'vm', 44 | title: 'Customer Detail' 45 | } 46 | } 47 | ]; 48 | } 49 | })(); 50 | -------------------------------------------------------------------------------- /src/client/app/customers/customers.route.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('customers', function() { 3 | describe('state', function() { 4 | var views = { 5 | customers: 'app/customers/customers.html', 6 | customerdetail: 'app/customers/customer-detail.html' 7 | }; 8 | 9 | beforeEach(function() { 10 | module('app.customers', bard.fakeToastr); 11 | bard.inject(this, '$location', '$rootScope', '$state', '$templateCache'); 12 | }); 13 | 14 | beforeEach(function() { 15 | $templateCache.put(views.customers, ''); 16 | $templateCache.put(views.customerdetail, ''); 17 | }); 18 | 19 | it('should map state customer.list to url /customer/list ', function() { 20 | expect($state.href('customer.list', {})).to.equal('/customer/list'); 21 | }); 22 | 23 | it('should map state customer.detail to url /customer/:id ', function() { 24 | expect($state.href('customer.detail', {id: 7})).to.equal('/customer/7'); 25 | }); 26 | 27 | it('should map /customers route to customers View template', function() { 28 | expect($state.get('customer.list').templateUrl).to.equal(views.customers); 29 | }); 30 | 31 | it('should map /customer.details route to customers View template', function() { 32 | expect($state.get('customer.detail').templateUrl).to.equal(views.customerdetail); 33 | }); 34 | 35 | it('of customer.list should work with $state.go', function() { 36 | $state.go('customer.list'); 37 | $rootScope.$apply(); 38 | expect($state.is('customer.list')); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.controller.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.dashboard') 6 | .controller('Dashboard', Dashboard); 7 | 8 | function Dashboard($state, dataservice, logger) { 9 | var vm = this; 10 | vm.customers = []; 11 | vm.gotoCustomer = gotoCustomer; 12 | vm.title = 'Dashboard'; 13 | 14 | activate(); 15 | 16 | function activate() { 17 | return getCustomers().then(function () { 18 | logger.info('Activated Dashboard View'); 19 | }); 20 | } 21 | 22 | function getCustomers() { 23 | return dataservice.getCustomers().then(function (data) { 24 | vm.customers = data; 25 | return vm.customers; 26 | }); 27 | } 28 | 29 | function gotoCustomer(c) { 30 | $state.go('customer.detail', {id: c.id}); 31 | } 32 | } 33 | })(); 34 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.controller.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('Dashboard', function() { 3 | var controller; 4 | 5 | beforeEach(function() { 6 | bard.appModule('app.dashboard'); 7 | bard.inject(this, '$controller', '$q', '$rootScope', 'dataservice'); 8 | }); 9 | 10 | beforeEach(function() { 11 | sinon.stub(dataservice, 'getCustomers'). 12 | returns($q.when(mockData.getMockCustomers())); 13 | 14 | controller = $controller('Dashboard'); 15 | $rootScope.$apply(); 16 | }); 17 | 18 | bard.verifyNoOutstandingHttpRequests(); 19 | 20 | describe('Dashboard controller', function() { 21 | it('should be created successfully', function() { 22 | expect(controller).to.be.defined; 23 | }); 24 | 25 | describe('after activate', function() { 26 | it('should have title of Dashboard', function() { 27 | expect(controller.title).to.equal('Dashboard'); 28 | }); 29 | 30 | it('should have at least 1 customer', function() { 31 | expect(controller.customers).to.have.length.above(0); 32 | }); 33 | 34 | it('should have customer Count of 5', function() { 35 | expect(controller.customers).to.have.length(5); 36 | }); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.html: -------------------------------------------------------------------------------- 1 | <section id="dashboard-view" class="mainbar"> 2 | <section class="matter"> 3 | <div class="container"> 4 | <div class="row"> 5 | <div class="col-md-12"> 6 | <ul class="today-datas"> 7 | <li class="borange"> 8 | <div class="pull-left"><i class="fa fa-coffee"></i></div> 9 | <div class="datas-text pull-right"> 10 | <a href="http://www.gulpjs.com"><span class="bold">Gulp</span></a> 11 | </div> 12 | <div class="clearfix"></div> 13 | </li> 14 | 15 | <li class="bviolet"> 16 | <div class="pull-left"><i class="fa fa-users"></i></div> 17 | <div class="datas-text pull-right"> 18 | <span class="bold">{{vm.customers.length}}</span> Customers 19 | </div> 20 | <div class="clearfix"></div> 21 | </li> 22 | 23 | </ul> 24 | </div> 25 | </div> 26 | <div class="row"> 27 | <div class="widget wblue"> 28 | <div ht-widget-header title="Recent Customers" 29 | allow-collapse="true"></div> 30 | <div class="widget-content text-center text-info"> 31 | <div class="container"> 32 | <ul class="row image-group"> 33 | <li ng-repeat="c in vm.customers | limitTo:12 | orderBy:'name'" 34 | ng-click="vm.gotoCustomer(c)" 35 | class="col-lg-2 col-md-2 col-sm-3 col-xs-4"> 36 | <div class="user" title="Go to speaker details"> 37 | <img ht-img-person="{{c.thumbnail}}" 38 | class="img-thumbnail stacked"> 39 | <div> 40 | <small>{{c.firstName}}</small> 41 | </div> 42 | <div> 43 | <small>{{c.lastName}}</small> 44 | </div> 45 | </div> 46 | 47 | </li> 48 | </ul> 49 | </div> 50 | </div> 51 | <div class="widget-foot"> 52 | <div class="clearfix"></div> 53 | </div> 54 | </div> 55 | </div> 56 | </div> 57 | </div> 58 | </section> 59 | </section> 60 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.dashboard', [ 5 | 'app.core', 6 | 'app.widgets' 7 | ]); 8 | 9 | })(); 10 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.route.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.dashboard') 6 | .run(appRun); 7 | 8 | /* @ngInject */ 9 | function appRun(routerHelper) { 10 | routerHelper.configureStates(getStates()); 11 | } 12 | 13 | function getStates() { 14 | return [ 15 | { 16 | state: 'dashboard', 17 | config: { 18 | url: '/', 19 | templateUrl: 'app/dashboard/dashboard.html', 20 | controller: 'Dashboard', 21 | controllerAs: 'vm', 22 | title: 'dashboard', 23 | settings: { 24 | nav: 1, 25 | content: '<i class="fa fa-dashboard"></i> Dashboard' 26 | } 27 | } 28 | } 29 | ]; 30 | } 31 | })(); 32 | -------------------------------------------------------------------------------- /src/client/app/dashboard/dashboard.route.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('dashboard', function() { 3 | describe('state', function() { 4 | var views = { 5 | dashboard: 'app/dashboard/dashboard.html' 6 | }; 7 | 8 | beforeEach(function() { 9 | module('app.dashboard', bard.fakeToastr); 10 | bard.inject(this, '$location', '$rootScope', '$state', '$templateCache'); 11 | $templateCache.put(views.dashboard, ''); 12 | }); 13 | 14 | it('should map / route to dashboard View template', function() { 15 | expect($state.get('dashboard').templateUrl).to.equal(views.dashboard); 16 | }); 17 | 18 | it('should map state dashboard to url / ', function() { 19 | expect($state.href('dashboard', {})).to.equal('/'); 20 | }); 21 | 22 | it('of dashboard should work with $state.go', function() { 23 | $state.go('dashboard'); 24 | $rootScope.$apply(); 25 | expect($state.is('dashboard')); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /src/client/app/layout/ht-sidebar.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.layout') 6 | .directive('htSidebar', htSidebar); 7 | 8 | /* @ngInject */ 9 | function htSidebar () { 10 | // Opens and closes the sidebar menu. 11 | // Usage: 12 | // <div ht-sidebar"> 13 | // <div ht-sidebar whenDoneAnimating="vm.sidebarReady()"> 14 | // Creates: 15 | // <div ht-sidebar class="sidebar"> 16 | var directive = { 17 | bindToController: true, 18 | link: link, 19 | restrict: 'EA', 20 | scope: { 21 | whenDoneAnimating: '&?' 22 | } 23 | }; 24 | return directive; 25 | 26 | function link(scope, element, attrs) { 27 | var $sidebarInner = element.find('.sidebar-inner'); 28 | var $dropdownElement = element.find('.sidebar-dropdown a'); 29 | element.addClass('sidebar'); 30 | $dropdownElement.click(dropdown); 31 | 32 | function dropdown(e) { 33 | var dropClass = 'dropy'; 34 | e.preventDefault(); 35 | if (!$dropdownElement.hasClass(dropClass)) { 36 | $sidebarInner.slideDown(350, scope.whenDoneAnimating); 37 | $dropdownElement.addClass(dropClass); 38 | } else if ($dropdownElement.hasClass(dropClass)) { 39 | $dropdownElement.removeClass(dropClass); 40 | $sidebarInner.slideUp(350, scope.whenDoneAnimating); 41 | } 42 | } 43 | } 44 | } 45 | })(); 46 | -------------------------------------------------------------------------------- /src/client/app/layout/ht-sidebar.directive.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | /* jshint multistr:true */ 3 | describe('htSidebar directive: ', function () { 4 | var dropdownElement; 5 | var el; 6 | var innerElement; 7 | var isOpenClass = 'dropy'; 8 | var scope; 9 | 10 | beforeEach(module('app.layout')); 11 | 12 | beforeEach(function() { 13 | bard.inject(this, '$compile', '$rootScope'); 14 | // The minimum necessary template HTML for this spec. 15 | // Simulates a menu link that opens and closes a dropdown of menu items 16 | // The `when-done-animating` attribute is optional (as is the vm's implementation) 17 | // 18 | // N.B.: the attribute value is supposed to be an expression that invokes a $scope method 19 | // so make sure the expression includes '()', e.g., "vm.sidebarReady(42)" 20 | // no harm if the expression fails ... but then scope.sidebarReady will be undefined. 21 | // All parameters in the expression are passed to vm.sidebarReady ... if it exists 22 | // 23 | // N.B.: We do NOT add this element to the browser DOM (although we could). 24 | // spec runs faster if we don't touch the DOM (even the PhantomJS DOM). 25 | el = angular.element( 26 | '<ht-sidebar when-done-animating="vm.sidebarReady(42)" > \ 27 | <div class="sidebar-dropdown"><a href="">Menu</a></div> \ 28 | <div class="sidebar-inner" style="display: none"></div> \ 29 | </ht-sidebar>'); 30 | 31 | // The spec examines changes to these template parts 32 | dropdownElement = el.find('.sidebar-dropdown a'); // the link to click 33 | innerElement = el.find('.sidebar-inner'); // container of menu items 34 | 35 | // ng's $compile service resolves nested directives (there are none in this example) 36 | // and binds the element to the scope (which must be a real ng scope) 37 | scope = $rootScope; 38 | $compile(el)(scope); 39 | 40 | // tell angular to look at the scope values right now 41 | scope.$digest(); 42 | }); 43 | 44 | /// tests /// 45 | describe('the isOpenClass', function () { 46 | it('is absent for a closed menu', function () { 47 | hasIsOpenClass(false); 48 | }); 49 | 50 | it('is added to a closed menu after clicking', function () { 51 | clickIt(); 52 | hasIsOpenClass(true); 53 | }); 54 | 55 | it('is present for an open menu', function () { 56 | openDropdown(); 57 | hasIsOpenClass(true); 58 | }); 59 | 60 | it('is removed from a closed menu after clicking', function () { 61 | openDropdown(); 62 | clickIt(); 63 | hasIsOpenClass(false); 64 | }); 65 | }); 66 | 67 | describe('when animating w/ jQuery fx off', function () { 68 | beforeEach(function () { 69 | // remember current state of jQuery's global FX duration switch 70 | this.oldFxOff = $.fx.off; 71 | // when jQuery fx are of, there is zero animation time; no waiting for animation to complete 72 | $.fx.off = true; 73 | // must add to DOM when testing jQuery animation result 74 | el.appendTo(document.body); 75 | }); 76 | 77 | afterEach(function () { 78 | $.fx.off = this.oldFxOff; 79 | el.remove(); 80 | }); 81 | 82 | it('dropdown is visible after opening a closed menu', function () { 83 | dropdownIsVisible(false); // hidden before click 84 | clickIt(); 85 | dropdownIsVisible(true); // visible after click 86 | }); 87 | 88 | it('dropdown is hidden after closing an open menu', function () { 89 | openDropdown(); 90 | dropdownIsVisible(true); // visible before click 91 | clickIt(); 92 | dropdownIsVisible(false); // hidden after click 93 | }); 94 | 95 | it('click triggers "when-done-animating" expression', function () { 96 | 97 | // spy on directive's callback when the animation is done 98 | var spy = sinon.spy(); 99 | 100 | // Recall the pertinent tag in the template ... 101 | // ' <div ht-sidebar when-done-animating="vm.sidebarReady(42)" > 102 | // therefore, the directive looks for scope.vm.sidebarReady 103 | // and should call that method with the value '42' 104 | scope.vm = {sidebarReady: spy}; 105 | 106 | // tell angular to look again for that vm.sidebarReady property 107 | scope.$digest(); 108 | 109 | // spy not called until after click which triggers the animation 110 | expect(spy).not.to.have.been.called; 111 | 112 | // this click triggers an animation 113 | clickIt(); 114 | 115 | // verify that the vm's method (sidebarReady) was called with '42' 116 | // FYI: spy.args[0] is the array of args passed to sidebarReady() 117 | expect(spy).to.have.been.calledWith(42); 118 | }); 119 | }); 120 | 121 | /////// helpers ////// 122 | 123 | // put the dropdown in the 'menu open' state 124 | function openDropdown() { 125 | dropdownElement.addClass(isOpenClass); 126 | innerElement.css('display', 'block'); 127 | } 128 | 129 | // click the "menu" link 130 | function clickIt() { 131 | dropdownElement.trigger('click'); 132 | } 133 | 134 | // assert whether the "menu" link has the class that means 'is open' 135 | function hasIsOpenClass(isTrue) { 136 | var hasClass = dropdownElement.hasClass(isOpenClass); 137 | expect(hasClass).equal(!!isTrue, 138 | 'dropdown has the "is open" class is ' + hasClass); 139 | } 140 | 141 | // assert whether the dropdown container is 'block' (visible) or 'none' (hidden) 142 | function dropdownIsVisible(isTrue) { 143 | var display = innerElement.css('display'); 144 | expect(display).to.equal(isTrue ? 'block' : 'none', 145 | 'innerElement display value is ' + display); 146 | } 147 | }); 148 | -------------------------------------------------------------------------------- /src/client/app/layout/ht-top-nav.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.layout') 6 | .directive('htTopNav', htTopNav); 7 | 8 | /* @ngInject */ 9 | function htTopNav () { 10 | var directive = { 11 | bindToController: true, 12 | controller: TopNavController, 13 | controllerAs: 'vm', 14 | restrict: 'EA', 15 | scope: { 16 | 'tagline': '=', 17 | 'title': '=' 18 | }, 19 | templateUrl: 'app/layout/ht-top-nav.html' 20 | }; 21 | 22 | /* @ngInject */ 23 | function TopNavController() { 24 | var vm = this; 25 | } 26 | 27 | return directive; 28 | } 29 | })(); 30 | -------------------------------------------------------------------------------- /src/client/app/layout/ht-top-nav.html: -------------------------------------------------------------------------------- 1 | <nav class="navbar navbar-fixed-top navbar-inverse"> 2 | <div class="navbar-header"> 3 | <a href="/" class="navbar-brand"><span class="brand-title">{{vm.title}}</span></a> 4 | <a class="btn navbar-btn navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> 5 | <span class="icon-bar"></span> 6 | <span class="icon-bar"></span> 7 | <span class="icon-bar"></span> 8 | </a> 9 | </div> 10 | <div class="navbar-collapse collapse"> 11 | <div class="pull-right navbar-logo"> 12 | <ul class="nav navbar-nav pull-right"> 13 | <li> 14 | <a ng-href="{{vm.tagline.link}}" target="_blank"> 15 | {{vm.tagline.text}} 16 | </a> 17 | </li> 18 | <li class="dropdown dropdown-big"> 19 | <a href="http://www.angularjs.org" target="_blank"> 20 | <img src="images/AngularJS-small.png" /> 21 | </a> 22 | </li> 23 | <li> 24 | <a href="http://www.gulpjs.com/" target="_blank"> 25 | <img src="images/gulp-tiny.png" /> 26 | </a> 27 | </li> 28 | </ul> 29 | </div> 30 | </div> 31 | </nav> 32 | -------------------------------------------------------------------------------- /src/client/app/layout/layout.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.layout', ['app.core']); 5 | })(); 6 | -------------------------------------------------------------------------------- /src/client/app/layout/shell.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.layout') 6 | .controller('Shell', Shell); 7 | 8 | /* @ngInject */ 9 | function Shell($timeout, config, logger) { 10 | var vm = this; 11 | 12 | vm.title = config.appTitle; 13 | vm.busyMessage = 'Please wait ...'; 14 | vm.isBusy = true; 15 | vm.showSplash = true; 16 | vm.tagline = { 17 | text: 'Created by John Papa', 18 | link: 'http://twitter.com/john_papa' 19 | }; 20 | 21 | activate(); 22 | 23 | function activate() { 24 | logger.success(config.appTitle + ' loaded!', null); 25 | hideSplash(); 26 | } 27 | 28 | function hideSplash() { 29 | //Force a 1 second delay so we can see the splash. 30 | $timeout(function() { 31 | vm.showSplash = false; 32 | }, 1000); 33 | } 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /src/client/app/layout/shell.controller.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('Shell', function() { 3 | var controller; 4 | 5 | beforeEach(function() { 6 | bard.appModule('app.layout'); 7 | bard.inject(this, '$controller', '$rootScope', '$timeout'); 8 | }); 9 | 10 | beforeEach(function() { 11 | controller = $controller('Shell'); 12 | $rootScope.$apply(); 13 | }); 14 | 15 | bard.verifyNoOutstandingHttpRequests(); 16 | 17 | describe('Shell controller', function() { 18 | it('should be created successfully', function() { 19 | expect(controller).to.be.defined; 20 | }); 21 | 22 | it('should show splash screen', function() { 23 | expect(controller.showSplash).to.be.true; 24 | }); 25 | 26 | it('should hide splash screen after timeout', function(done) { 27 | $timeout(function() { 28 | expect(controller.showSplash).to.be.false; 29 | done(); 30 | }, 1000); 31 | $timeout.flush(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/client/app/layout/shell.html: -------------------------------------------------------------------------------- 1 | <div ng-controller="Shell as vm"> 2 | <header class="clearfix"> 3 | <ht-top-nav title="vm.title" tagline="vm.tagline"></ht-top-nav> 4 | </header> 5 | <section id="content" class="content"> 6 | <div ng-include="'app/layout/sidebar.html'"></div> 7 | 8 | <div ui-view class="shuffle-animation"></div> 9 | 10 | <div ngplus-overlay 11 | ngplus-overlay-delay-in="50" 12 | ngplus-overlay-delay-out="700" 13 | ngplus-overlay-animation="dissolve-animation"> 14 | <img src="images/busy.gif"/> 15 | 16 | <div class="page-spinner-message overlay-message">{{vm.busyMessage}}</div> 17 | </div> 18 | </section> 19 | </div> 20 | -------------------------------------------------------------------------------- /src/client/app/layout/sidebar.controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.layout') 6 | .controller('Sidebar', Sidebar); 7 | 8 | /* @ngInject */ 9 | function Sidebar($state, routerHelper) { 10 | var vm = this; 11 | var states = routerHelper.getStates(); 12 | vm.isCurrent = isCurrent; 13 | //vm.sidebarReady = function(){console.log('done animating menu')}; // example 14 | 15 | activate(); 16 | 17 | function activate() { getNavRoutes(); } 18 | 19 | function getNavRoutes() { 20 | vm.navRoutes = states.filter(function(r) { 21 | return r.settings && r.settings.nav; 22 | }).sort(function(r1, r2) { 23 | return r1.settings.nav - r2.settings.nav; 24 | }); 25 | } 26 | 27 | function isCurrent(route) { 28 | if (!route.title || !$state.current || !$state.current.title) { 29 | return ''; 30 | } 31 | var menuName = route.title; 32 | return $state.current.title.substr(0, menuName.length) === menuName ? 'current' : ''; 33 | } 34 | } 35 | })(); 36 | -------------------------------------------------------------------------------- /src/client/app/layout/sidebar.controller.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | describe('layout', function() { 3 | describe('sidebar', function() { 4 | var controller; 5 | var views = { 6 | dashboard: 'app/dashboard/dashboard.html', 7 | customers: 'app/customers/customers.html' 8 | }; 9 | 10 | beforeEach(function() { 11 | module('app.layout', bard.fakeToastr); 12 | bard.inject(this, '$controller', '$httpBackend', '$location', 13 | '$rootScope', '$state', 'routerHelper'); 14 | }); 15 | 16 | beforeEach(function() { 17 | routerHelper.configureStates(mockData.getMockStates(), '/'); 18 | controller = $controller('Sidebar'); 19 | $rootScope.$apply(); 20 | }); 21 | 22 | bard.verifyNoOutstandingHttpRequests(); 23 | 24 | it('should have isCurrent() for / to return `current`', function() { 25 | $location.path('/'); 26 | expect(controller.isCurrent($state.current)).to.equal('current'); 27 | }); 28 | 29 | it('should have isCurrent() for /customers to return `current`', function() { 30 | $location.path('/customers'); 31 | expect(controller.isCurrent($state.current)).to.equal('current'); 32 | }); 33 | 34 | it('should have isCurrent() for non route not return `current`', function() { 35 | $location.path('/invalid'); 36 | expect(controller.isCurrent({title: 'invalid'})).not.to.equal('current'); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /src/client/app/layout/sidebar.html: -------------------------------------------------------------------------------- 1 | <div ng-controller="Sidebar as vm"> 2 | <ht-sidebar when-done-animating="vm.sidebarReady()"> 3 | <div class="sidebar-filler"></div> 4 | <div class="sidebar-dropdown"><a href="#">Menu</a></div> 5 | <div class="sidebar-inner"> 6 | <div class="sidebar-widget"></div> 7 | <ul class="navi"> 8 | <li class="nlightblue fade-selection-animation" ng-class="vm.isCurrent(r)" 9 | ng-repeat="r in vm.navRoutes"> 10 | <a ui-sref="{{r.name}}" 11 | ng-bind-html="r.settings.content"></a> 12 | </li> 13 | </ul> 14 | </div> 15 | </ht-sidebar> 16 | </div> 17 | -------------------------------------------------------------------------------- /src/client/app/widgets/ht-img-person.directive.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.widgets') 6 | .directive('htImgPerson', htImgPerson); 7 | 8 | /* @ngInject */ 9 | function htImgPerson (config) { 10 | //Usage: 11 | //<img ht-img-person="{{person.imageSource}}"/> 12 | var basePath = config.imageBasePath; 13 | var unknownImage = config.unknownPersonImageSource; 14 | var directive = { 15 | link: link, 16 | restrict: 'A' 17 | }; 18 | return directive; 19 | 20 | function link(scope, element, attrs) { 21 | attrs.$observe('htImgPerson', function (value) { 22 | value = basePath + (value || unknownImage); 23 | attrs.$set('src', value); 24 | }); 25 | } 26 | } 27 | })(); 28 | -------------------------------------------------------------------------------- /src/client/app/widgets/ht-widget-header.directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular 5 | .module('app.widgets') 6 | .directive('htWidgetHeader', htWidgetHeader); 7 | 8 | /* @ngInject */ 9 | function htWidgetHeader () { 10 | //Usage: 11 | //<div ht-widget-header title="vm.map.title"></div> 12 | // Creates: 13 | // <div ht-widget-header="" 14 | // title="Movie" 15 | // allow-collapse="true" </div> 16 | var directive = { 17 | scope: { 18 | 'title': '@', 19 | 'subtitle': '@', 20 | 'rightText': '@', 21 | 'allowCollapse': '@' 22 | }, 23 | templateUrl: 'app/widgets/widget-header.html', 24 | restrict: 'EA' 25 | }; 26 | return directive; 27 | } 28 | })(); 29 | -------------------------------------------------------------------------------- /src/client/app/widgets/widget-header.html: -------------------------------------------------------------------------------- 1 | <div class="widget-head"> 2 | <div class="page-title pull-left">{{title}}</div> 3 | <small class="page-title-subtle" ng-show="subtitle">({{subtitle}})</small> 4 | <div class="widget-icons pull-right" ng-if="allowCollapse"> 5 | <a ht-widget-minimize></a> 6 | </div> 7 | <small class="pull-right page-title-subtle" ng-show="rightText">{{rightText}}</small> 8 | <div class="clearfix"></div> 9 | </div> 10 | -------------------------------------------------------------------------------- /src/client/app/widgets/widgets.module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 'use strict'; 3 | 4 | angular.module('app.widgets', []); 5 | })(); 6 | -------------------------------------------------------------------------------- /src/client/images/AngularJS-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/AngularJS-small.png -------------------------------------------------------------------------------- /src/client/images/busy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/busy.gif -------------------------------------------------------------------------------- /src/client/images/gulp-tiny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/gulp-tiny.png -------------------------------------------------------------------------------- /src/client/images/photos/aaron_skonnard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/aaron_skonnard.jpg -------------------------------------------------------------------------------- /src/client/images/photos/anant-narayanan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/anant-narayanan.png -------------------------------------------------------------------------------- /src/client/images/photos/ari-lerner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ari-lerner.png -------------------------------------------------------------------------------- /src/client/images/photos/ben-clinkinbeard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ben-clinkinbeard.png -------------------------------------------------------------------------------- /src/client/images/photos/ben-teese.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ben-teese.png -------------------------------------------------------------------------------- /src/client/images/photos/brad_green.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/brad_green.jpg -------------------------------------------------------------------------------- /src/client/images/photos/brian-ford.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/brian-ford.png -------------------------------------------------------------------------------- /src/client/images/photos/burke-holland.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/burke-holland.png -------------------------------------------------------------------------------- /src/client/images/photos/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/cat.jpg -------------------------------------------------------------------------------- /src/client/images/photos/christian-lilley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/christian-lilley.png -------------------------------------------------------------------------------- /src/client/images/photos/colleen_papa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/colleen_papa.jpg -------------------------------------------------------------------------------- /src/client/images/photos/craig_shoemaker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/craig_shoemaker.jpg -------------------------------------------------------------------------------- /src/client/images/photos/dan_wahlin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/dan_wahlin.jpg -------------------------------------------------------------------------------- /src/client/images/photos/dave-smith.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/dave-smith.png -------------------------------------------------------------------------------- /src/client/images/photos/dave_ward.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/dave_ward.jpg -------------------------------------------------------------------------------- /src/client/images/photos/elijah_manor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/elijah_manor.jpg -------------------------------------------------------------------------------- /src/client/images/photos/eric_barnard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/eric_barnard.jpg -------------------------------------------------------------------------------- /src/client/images/photos/esteban_garcia.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/esteban_garcia.jpg -------------------------------------------------------------------------------- /src/client/images/photos/felix_fanboi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/felix_fanboi.jpg -------------------------------------------------------------------------------- /src/client/images/photos/fritz_onion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/fritz_onion.jpg -------------------------------------------------------------------------------- /src/client/images/photos/glenn_block.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/glenn_block.jpg -------------------------------------------------------------------------------- /src/client/images/photos/hans_fjallemark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/hans_fjallemark.jpg -------------------------------------------------------------------------------- /src/client/images/photos/howard_dierking.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/howard_dierking.jpg -------------------------------------------------------------------------------- /src/client/images/photos/igor_minar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/igor_minar.jpg -------------------------------------------------------------------------------- /src/client/images/photos/james-deboer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/james-deboer.png -------------------------------------------------------------------------------- /src/client/images/photos/jason-aden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/jason-aden.png -------------------------------------------------------------------------------- /src/client/images/photos/jason_salmond.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/jason_salmond.jpg -------------------------------------------------------------------------------- /src/client/images/photos/jeff-cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/jeff-cross.png -------------------------------------------------------------------------------- /src/client/images/photos/jesse_liberty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/jesse_liberty.jpg -------------------------------------------------------------------------------- /src/client/images/photos/jim_cowart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/jim_cowart.jpg -------------------------------------------------------------------------------- /src/client/images/photos/john-lindquist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/john-lindquist.png -------------------------------------------------------------------------------- /src/client/images/photos/john_papa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/john_papa.jpg -------------------------------------------------------------------------------- /src/client/images/photos/john_smith.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/john_smith.jpg -------------------------------------------------------------------------------- /src/client/images/photos/john_sonmez.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/john_sonmez.jpg -------------------------------------------------------------------------------- /src/client/images/photos/julie-ralph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/julie-ralph.png -------------------------------------------------------------------------------- /src/client/images/photos/julie_lerman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/julie_lerman.jpg -------------------------------------------------------------------------------- /src/client/images/photos/keith_sparkjoy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/keith_sparkjoy.jpg -------------------------------------------------------------------------------- /src/client/images/photos/lukas-ruebbelke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/lukas-ruebbelke.png -------------------------------------------------------------------------------- /src/client/images/photos/mads_kristensen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/mads_kristensen.jpg -------------------------------------------------------------------------------- /src/client/images/photos/matias-niemela.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/matias-niemela.png -------------------------------------------------------------------------------- /src/client/images/photos/max-lynch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/max-lynch.png -------------------------------------------------------------------------------- /src/client/images/photos/megan_russell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/megan_russell.jpg -------------------------------------------------------------------------------- /src/client/images/photos/mike_callaghan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/mike_callaghan.jpg -------------------------------------------------------------------------------- /src/client/images/photos/mike_woodring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/mike_woodring.jpg -------------------------------------------------------------------------------- /src/client/images/photos/misko-hevery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/misko-hevery.png -------------------------------------------------------------------------------- /src/client/images/photos/pete_brown.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/pete_brown.jpg -------------------------------------------------------------------------------- /src/client/images/photos/rey_bango.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/rey_bango.jpg -------------------------------------------------------------------------------- /src/client/images/photos/rob_eisenberg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/rob_eisenberg.jpg -------------------------------------------------------------------------------- /src/client/images/photos/ron-evans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ron-evans.png -------------------------------------------------------------------------------- /src/client/images/photos/ryan_niemeyer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ryan_niemeyer.jpg -------------------------------------------------------------------------------- /src/client/images/photos/scott_guthrie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/scott_guthrie.jpg -------------------------------------------------------------------------------- /src/client/images/photos/scott_hanselman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/scott_hanselman.jpg -------------------------------------------------------------------------------- /src/client/images/photos/scott_hunter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/scott_hunter.jpg -------------------------------------------------------------------------------- /src/client/images/photos/sean-hess.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/sean-hess.png -------------------------------------------------------------------------------- /src/client/images/photos/sharon-diorio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/sharon-diorio.png -------------------------------------------------------------------------------- /src/client/images/photos/shawn_wildermuth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/shawn_wildermuth.jpg -------------------------------------------------------------------------------- /src/client/images/photos/silvano-luciani.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/silvano-luciani.png -------------------------------------------------------------------------------- /src/client/images/photos/steve_sanderson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/steve_sanderson.jpg -------------------------------------------------------------------------------- /src/client/images/photos/sue_menot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/sue_menot.jpg -------------------------------------------------------------------------------- /src/client/images/photos/thomas-burleson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/thomas-burleson.png -------------------------------------------------------------------------------- /src/client/images/photos/tim_heuer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/tim_heuer.jpg -------------------------------------------------------------------------------- /src/client/images/photos/unknown_person.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/unknown_person.jpg -------------------------------------------------------------------------------- /src/client/images/photos/vojta-jina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/vojta-jina.png -------------------------------------------------------------------------------- /src/client/images/photos/ward-bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ward-bell.png -------------------------------------------------------------------------------- /src/client/images/photos/ward_bell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/client/images/photos/ward_bell.jpg -------------------------------------------------------------------------------- /src/client/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html ng-app="app"> 3 | <head> 4 | <meta charset="utf-8" /> 5 | <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" /> 6 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> 7 | <title ng-bind="title"> 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 | Gulp Patterns Demo 36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /src/client/specs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | gulp-patterns 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

Spec Runner

24 |

Make sure the REMOTE server is running
25 | Click on a description title to narrow the scope to just its specs 26 | (see " 27 | ?grep" in address bar).
28 | Click on a spec title to see the test implementation.
29 | Click on page title to start over. 30 |

31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /src/client/stubs/pass-throughs.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | angular 3 | .module('app') 4 | .factory('passThroughs', passThroughs); 5 | 6 | passThroughs.$inject = ['$httpBackend']; 7 | /* @ngInject */ 8 | function passThroughs($httpBackend) { 9 | var apiUrl = new RegExp(/api\//); 10 | var service = { 11 | registerAPIs: registerAPIs, 12 | registerCatchAlls: registerCatchAlls, 13 | registerTemplates: registerTemplates 14 | }; 15 | 16 | return service; 17 | 18 | function registerCatchAlls() { 19 | registerTemplates(); 20 | registerAPIs(); 21 | } 22 | 23 | function registerTemplates() { 24 | var pattern = /\.html$/; 25 | $httpBackend.whenGET(pattern).passThrough(); 26 | } 27 | 28 | function registerAPIs() { 29 | //$httpBackend.whenGET(apiUrl).passThrough(); 30 | var url = new RegExp(apiUrl.source + /.*/); 31 | $httpBackend.whenGET(url).passThrough(); 32 | $httpBackend.whenPOST(url).passThrough(); 33 | $httpBackend.whenDELETE(url).passThrough(); 34 | $httpBackend.whenPUT(url).passThrough(); 35 | } 36 | } 37 | })(); 38 | -------------------------------------------------------------------------------- /src/client/stubs/stubs.config.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | if (!document.URL.match(/\?stubs$/)) { 4 | return; 5 | } 6 | 7 | console.log('* * * STUBBING with $httpBackend * * *'); 8 | 9 | angular 10 | .module('app') 11 | .config(configure) 12 | .run(registerStubs); 13 | 14 | //TODO: dynamically inject angular-mocks and stubs.js for dev stubbing mode only 15 | 16 | configure.$inject = ['$provide']; 17 | /* @ngInject */ 18 | function configure($provide) { 19 | $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); 20 | } 21 | 22 | registerStubs.$inject = ['passThroughs', 'stubs']; 23 | /* @ngInject */ 24 | function registerStubs(passThroughs, stubs) { 25 | if (true) { 26 | stubs.registerGetCustomers(); 27 | stubs.registerGetCustomer(); 28 | passThroughs.registerCatchAlls(); 29 | } 30 | } 31 | })(); 32 | -------------------------------------------------------------------------------- /src/client/stubs/stubs.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | angular 3 | .module('app') 4 | .factory('stubs', stubs); 5 | 6 | stubs.$inject = ['$httpBackend']; 7 | /* @ngInject */ 8 | function stubs($httpBackend) { 9 | var apiUrl = new RegExp(/api\//); 10 | var service = { 11 | registerAll: registerAll, 12 | registerGetCustomer: registerGetCustomer, 13 | registerGetCustomers: registerGetCustomers 14 | }; 15 | 16 | return service; 17 | 18 | function registerAll() { 19 | registerGetCustomers(); 20 | registerGetCustomer(); 21 | } 22 | 23 | function registerGetCustomers() { 24 | var pattern = new RegExp(apiUrl.source + 'customers'); 25 | $httpBackend.whenGET(pattern).respond(getCustomersCallback); 26 | 27 | function getCustomersCallback(method, url, data) { 28 | var customers = [ 29 | { 30 | 'id': 8349812, 31 | 'firstName': 'Madalana', 32 | 'lastName': '', 33 | 'city': 'Wickedia', 34 | 'state': 'UK', 35 | 'zip': '81239', 36 | 'thumbnail': 'colleen_papa.jpg' 37 | }, 38 | { 39 | 'id': 2387872, 40 | 'firstName': 'Galavant', 41 | 'lastName': '', 42 | 'city': 'Medievalia', 43 | 'state': 'UK', 44 | 'zip': '82828', 45 | 'thumbnail': 'john_papa.jpg' 46 | }]; 47 | return [200, customers, {}]; 48 | } 49 | } 50 | 51 | function registerGetCustomer(id) { 52 | var pattern = new RegExp(apiUrl.source + /customer\/\**/.source); 53 | $httpBackend.whenGET(pattern).respond(getCustomerCallback); 54 | 55 | function getCustomerCallback(method, url, data) { 56 | var customer = { 57 | 'id': 8349812, 58 | 'firstName': 'Madalana', 59 | 'lastName': '', 60 | 'city': 'Wickedia', 61 | 'state': 'UK', 62 | 'zip': '81239', 63 | 'thumbnail': 'colleen_papa.jpg' 64 | }; 65 | return [200, customer, {}]; 66 | } 67 | } 68 | } 69 | })(); 70 | -------------------------------------------------------------------------------- /src/client/test-helpers/bind-polyfill.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Phantom.js does not support Function.prototype.bind (at least not before v.2.0 3 | * That's just crazy. Everybody supports bind. 4 | * Read about it here: https://groups.google.com/forum/#!msg/phantomjs/r0hPOmnCUpc/uxusqsl2LNoJ 5 | * This polyfill is copied directly from MDN 6 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Compatibility 7 | */ 8 | if (!Function.prototype.bind) { 9 | /*jshint freeze: false */ 10 | Function.prototype.bind = function (oThis) { 11 | if (typeof this !== 'function') { 12 | // closest thing possible to the ECMAScript 5 13 | // internal IsCallable function 14 | var msg = 'Function.prototype.bind - what is trying to be bound is not callable'; 15 | throw new TypeError(msg); 16 | } 17 | 18 | var aArgs = Array.prototype.slice.call(arguments, 1), 19 | fToBind = this, 20 | FuncNoOp = function () {}, 21 | fBound = function () { 22 | return fToBind.apply(this instanceof FuncNoOp && oThis ? this : oThis, 23 | aArgs.concat(Array.prototype.slice.call(arguments))); 24 | }; 25 | 26 | FuncNoOp.prototype = this.prototype; 27 | fBound.prototype = new FuncNoOp(); 28 | 29 | return fBound; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/client/test-helpers/mock-data.js: -------------------------------------------------------------------------------- 1 | /* jshint -W079 */ 2 | var mockData = (function() { 3 | return { 4 | getMockCustomers: getMockCustomers, 5 | getMockStates: getMockStates, 6 | blackWidow: getMockCustomers()[0] 7 | }; 8 | 9 | function getMockStates() { 10 | return [ 11 | { 12 | state: 'dashboard', 13 | config: { 14 | url: '/', 15 | templateUrl: 'app/dashboard/dashboard.html', 16 | title: 'dashboard', 17 | settings: { 18 | nav: 1, 19 | content: ' Dashboard' 20 | } 21 | } 22 | } 23 | ]; 24 | } 25 | 26 | function getMockCustomers() { 27 | return [ 28 | { 29 | id: 1017109, 30 | firstName: 'Black', 31 | lastName: 'Widow', 32 | city: 'Albany', 33 | state: 'NY', 34 | zip: '12205', 35 | thumbnail: 'colleen_papa.jpg' 36 | }, 37 | { 38 | id: 1017105, 39 | firstName: 'Tony', 40 | lastName: 'Stark', 41 | city: 'Loudonville', 42 | state: 'NY', 43 | zip: '12211', 44 | thumbnail: 'john_papa.jpg' 45 | }, 46 | { 47 | id: 1017108, 48 | firstName: 'Clint', 49 | lastName: 'Barton', 50 | city: 'Bothell', 51 | state: 'WA', 52 | zip: '98012', 53 | thumbnail: 'ward_bell.jpg' 54 | }, 55 | { 56 | id: 1017104, 57 | firstName: 'Steve', 58 | lastName: 'Rogers', 59 | city: 'Orlando', 60 | state: 'FL', 61 | zip: '33746', 62 | thumbnail: 'jesse_liberty.jpg' 63 | }, 64 | { 65 | id: 1017106, 66 | firstName: 'Thor', 67 | lastName: 'of Asgard', 68 | city: 'Raleigh', 69 | state: 'NC', 70 | zip: '27601', 71 | thumbnail: 'jason_salmond.jpg' 72 | } 73 | ]; 74 | } 75 | })(); 76 | -------------------------------------------------------------------------------- /src/client/tests/server-integration/dataservice.spec.js: -------------------------------------------------------------------------------- 1 | /* jshint -W117, -W030 */ 2 | /** 3 | * Demonstrates use of bard's real $http and $q 4 | * restoring the ability to make AJAX calls to the server 5 | * while retaining all the goodness of ngMocks. 6 | * 7 | * An alternative to the ngMidwayTester 8 | */ 9 | 10 | describe('Server: dataservice', function() { 11 | var dataservice; 12 | 13 | beforeEach(bard.asyncModule('app')); 14 | 15 | beforeEach(inject(function(_dataservice_) { 16 | dataservice = _dataservice_; 17 | })); 18 | 19 | describe('when call getCustomers', function() { 20 | 21 | it('should get 16 Customers', function(done) { 22 | dataservice.getCustomers() 23 | .then(function(data) { 24 | expect(data).to.have.length(16); 25 | }) 26 | .then(done, done); 27 | }); 28 | 29 | it('should contain Black Widow', function(done) { 30 | dataservice.getCustomers() 31 | .then(function(data) { 32 | var hasBlackWidow = data && data.some(function foundHer(customer) { 33 | return customer.firstName.indexOf('Black') >= 0; 34 | }); 35 | expect(hasBlackWidow).to.be.true; 36 | }) 37 | .then(done, done); 38 | }); 39 | }); 40 | 41 | describe('when call getCustomer', function() { 42 | 43 | it('should get Black Widow', function(done) { 44 | dataservice.getCustomer('1017109') 45 | .then(function(customer) { 46 | var hasBlackWidow = customer.firstName === 'Black'; 47 | expect(hasBlackWidow).to.be.true; 48 | }) 49 | .then(done, done); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /src/server/app.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true*/ 2 | 'use strict'; 3 | 4 | var express = require('express'); 5 | var app = express(); 6 | var bodyParser = require('body-parser'); 7 | var compress = require('compression'); 8 | var cors = require('cors'); 9 | var errorHandler = require('./utils/errorHandler')(); 10 | var four0four = require('./utils/404')(); 11 | var favicon = require('serve-favicon'); 12 | var logger = require('morgan'); 13 | var port = process.env.PORT || 7203; 14 | var routes; 15 | 16 | var environment = process.env.NODE_ENV; 17 | 18 | app.use(favicon(__dirname + '/favicon.ico')); 19 | app.use(bodyParser.urlencoded({extended: true})); 20 | app.use(bodyParser.json()); 21 | app.use(compress()); 22 | app.use(logger('dev')); 23 | app.use(cors()); 24 | app.use(errorHandler.init); 25 | 26 | routes = require('./routes/index')(app); 27 | 28 | console.log('About to crank up node'); 29 | console.log('PORT=' + port); 30 | console.log('NODE_ENV=' + environment); 31 | 32 | app.get('/ping', function(req, res, next) { 33 | console.log(req.body); 34 | res.send('pong'); 35 | }); 36 | 37 | switch (environment) { 38 | case 'build': 39 | console.log('** BUILD **'); 40 | app.use(express.static('./build/')); 41 | // Any invalid calls for templateUrls are under app/* and should return 404 42 | app.use('/app/*', function(req, res, next) { 43 | four0four.send404(req, res); 44 | }); 45 | // Any deep link calls should return index.html 46 | app.use('/*', express.static('./build/index.html')); 47 | break; 48 | default: 49 | console.log('** DEV **'); 50 | app.use(express.static('./src/client/')); 51 | app.use(express.static('./')); 52 | app.use(express.static('./.tmp')); 53 | // All the assets are served at this point. 54 | // Any invalid calls for templateUrls are under app/* and should return 404 55 | app.use('/app/*', function(req, res, next) { 56 | four0four.send404(req, res); 57 | }); 58 | // Any deep link calls should return index.html 59 | app.use('/*', express.static('./src/client/index.html')); 60 | break; 61 | } 62 | 63 | app.listen(port, function() { 64 | console.log('Express server listening on port ' + port); 65 | console.log('env = ' + app.get('env') + 66 | '\n__dirname = ' + __dirname + 67 | '\nprocess.cwd = ' + process.cwd()); 68 | }); 69 | -------------------------------------------------------------------------------- /src/server/data/customers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1017109, 4 | "firstName": "Black", 5 | "lastName": "Widow", 6 | "city": "Albany", 7 | "state": "NY", 8 | "zip": "12205", 9 | "thumbnail": "colleen_papa.jpg" 10 | }, 11 | { 12 | "id": 1017105, 13 | "firstName": "Tony", 14 | "lastName": "Stark", 15 | "city": "Loudonville", 16 | "state": "NY", 17 | "zip": "12211", 18 | "thumbnail": "john_papa.jpg" 19 | }, 20 | { 21 | "id": 1017108, 22 | "firstName": "Clint", 23 | "lastName": "Barton", 24 | "city": "Bothell", 25 | "state": "WA", 26 | "zip": "98012", 27 | "thumbnail": "ward_bell.jpg" 28 | }, 29 | { 30 | "id": 1017104, 31 | "firstName": "Steve", 32 | "lastName": "Rogers", 33 | "city": "Orlando", 34 | "state": "FL", 35 | "zip": "33746", 36 | "thumbnail": "jesse_liberty.jpg" 37 | }, 38 | { 39 | "id": 1017106, 40 | "firstName": "Thor", 41 | "lastName": "of Asgard", 42 | "city": "Raleigh", 43 | "state": "NC", 44 | "zip": "27601", 45 | "thumbnail": "jason_salmond.jpg" 46 | }, 47 | { 48 | "id": 4444441, 49 | "firstName": "Bruce", 50 | "lastName": "Banner", 51 | "city": "Grand Rapids", 52 | "state": "MI", 53 | "zip": "49503", 54 | "thumbnail": "tim_heuer.jpg" 55 | }, 56 | { 57 | "id": 4444442, 58 | "firstName": "Harry", 59 | "lastName": "Potter", 60 | "city": "Seattle", 61 | "state": "WA", 62 | "zip": "98101", 63 | "thumbnail": "elijah_manor.jpg" 64 | }, 65 | { 66 | "id": 4444443, 67 | "firstName": "Bilbo", 68 | "lastName": "Baggins", 69 | "city": "Phoenix", 70 | "state": "AZ", 71 | "zip": "85007", 72 | "thumbnail": "esteban_garcia.jpg" 73 | }, 74 | { 75 | "id": 4444444, 76 | "firstName": "Elessar", 77 | "lastName": "Telcontar", 78 | "city": "Nome", 79 | "state": "AK", 80 | "zip": "99762", 81 | "thumbnail": "howard_dierking.jpg" 82 | }, 83 | { 84 | "id": 4444445, 85 | "firstName": "Percy", 86 | "lastName": "Jackson", 87 | "city": "Baltimore", 88 | "state": "MD", 89 | "zip": "21117", 90 | "thumbnail": "fritz_onion.jpg" 91 | }, 92 | { 93 | "id": 4444446, 94 | "firstName": "Jerle", 95 | "lastName": "Shannara", 96 | "city": "Dallas", 97 | "state": "TX", 98 | "zip": "75212", 99 | "thumbnail": "dan_wahlin.jpg" 100 | }, 101 | { 102 | "id": 4444447, 103 | "firstName": "Menion", 104 | "lastName": "Leah", 105 | "city": "Highlands", 106 | "state": "TX", 107 | "zip": "77562", 108 | "thumbnail": "brad_green.jpg" 109 | }, 110 | { 111 | "id": 4444448, 112 | "firstName": "Severus", 113 | "lastName": "Snape", 114 | "city": "San Francisco", 115 | "state": "CA", 116 | "zip": "94111", 117 | "thumbnail": "keith_sparkjoy.jpg" 118 | }, 119 | { 120 | "id": 4444449, 121 | "firstName": "Sirius", 122 | "lastName": "Black", 123 | "city": "New York City", 124 | "state": "NY", 125 | "zip": "10001", 126 | "thumbnail": "john_papa.jpg" 127 | }, 128 | { 129 | "id": 4444450, 130 | "firstName": "Gandalf", 131 | "lastName": "the White", 132 | "city": "New Haven", 133 | "state": "CN", 134 | "zip": "06501", 135 | "thumbnail": "rob_eisenberg.jpg" 136 | }, 137 | { 138 | "id": 4444451, 139 | "firstName": "Arwen", 140 | "lastName": "Undómiel", 141 | "city": "Portland", 142 | "state": "OR", 143 | "zip": "97211", 144 | "thumbnail": "julie_lerman.jpg" 145 | } 146 | ] 147 | -------------------------------------------------------------------------------- /src/server/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpapa/gulp-patterns/ea6f4f7395c982643d748973083134526571e1c6/src/server/favicon.ico -------------------------------------------------------------------------------- /src/server/routes/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app) { 2 | var api = '/api/'; 3 | var data = '/../data/'; 4 | var jsonfileservice = require('../utils/jsonfileservice')(); 5 | var four0four = require('../utils/404')(); 6 | 7 | app.get(api + 'customer/:id', getCustomer); 8 | app.get(api + 'customers', getCustomers); 9 | 10 | app.get(api + '*', four0four.notFoundMiddleware); 11 | 12 | function getCustomer(req, res, next) { 13 | var id = req.params.id; 14 | var msg = 'customer id ' + id + ' not found. '; 15 | try { 16 | var json = jsonfileservice.getJsonFromFile(data + 'customers.json'); 17 | var customer = json.filter(function(c) { 18 | return c.id === parseInt(id); 19 | }); 20 | if (customer && customer[0]) { 21 | res.send(customer[0]); 22 | } else { 23 | four0four.send404(req, res, msg); 24 | } 25 | } 26 | catch (ex) { 27 | four0four.send404(req, res, msg + ex.message); 28 | } 29 | } 30 | 31 | function getCustomers(req, res, next) { 32 | var msg = 'customers not found. '; 33 | try { 34 | var json = jsonfileservice.getJsonFromFile(data + 'customers.json'); 35 | if (json) { 36 | res.send(json); 37 | } else { 38 | four0four.send404(req, req, msg); 39 | } 40 | } 41 | catch (ex) { 42 | four0four.send404(req, res, msg + ex.message); 43 | } 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/server/utils/404.js: -------------------------------------------------------------------------------- 1 | module.exports = function (app) { 2 | var api = '/api/'; 3 | 4 | var service = { 5 | notFoundMiddleware: notFoundMiddleware, 6 | send404: send404 7 | }; 8 | return service; 9 | 10 | function notFoundMiddleware(req, res, next) { 11 | send404(req, res, 'API endpoint not found'); 12 | } 13 | 14 | function send404(req, res, description) { 15 | var data = { 16 | status: 404, 17 | message: 'Not Found', 18 | description: description, 19 | url: req.url 20 | }; 21 | res.status(404) 22 | .send(data) 23 | .end(); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /src/server/utils/errorHandler.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var service = { 3 | init: init, 4 | logErrors: logErrors 5 | }; 6 | return service; 7 | 8 | function init(err, req, res, next) { 9 | var status = err.statusCode || 500; 10 | if (err.message) { 11 | res.send(status, err.message); 12 | } else { 13 | res.send(status, err); 14 | } 15 | next(); 16 | } 17 | 18 | /* Our fall through error logger and errorHandler */ 19 | function logErrors(err, req, res, next) { 20 | var status = err.statusCode || 500; 21 | console.error(status + ' ' + (err.message ? err.message : err)); 22 | if (err.stack) { 23 | console.error(err.stack); 24 | } 25 | next(err); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/server/utils/jsonfileservice.js: -------------------------------------------------------------------------------- 1 | module.exports = function() { 2 | var service = { 3 | getJsonFromFile: getJsonFromFile 4 | }; 5 | return service; 6 | 7 | function getJsonFromFile(file) { 8 | var fs = require('fs'); 9 | var json = getConfig(file); 10 | return json; 11 | 12 | function readJsonFileSync(filepath, encoding) { 13 | if (typeof (encoding) === 'undefined') { 14 | encoding = 'utf8'; 15 | } 16 | var file = fs.readFileSync(filepath, encoding); 17 | return JSON.parse(file); 18 | } 19 | 20 | function getConfig(file) { 21 | var filepath = __dirname + file; 22 | return readJsonFileSync(filepath); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": { 8 | "bardjs/bardjs.d.ts": { 9 | "commit": "99942cab1446292c79c4328218abd37621505112" 10 | }, 11 | "angularjs/angular.d.ts": { 12 | "commit": "99942cab1446292c79c4328218abd37621505112" 13 | }, 14 | "jquery/jquery.d.ts": { 15 | "commit": "99942cab1446292c79c4328218abd37621505112" 16 | }, 17 | "chai/chai.d.ts": { 18 | "commit": "99942cab1446292c79c4328218abd37621505112" 19 | }, 20 | "mocha/mocha.d.ts": { 21 | "commit": "99942cab1446292c79c4328218abd37621505112" 22 | }, 23 | "angular-ui-router/angular-ui-router.d.ts": { 24 | "commit": "99942cab1446292c79c4328218abd37621505112" 25 | }, 26 | "angularjs/angular-sanitize.d.ts": { 27 | "commit": "99942cab1446292c79c4328218abd37621505112" 28 | }, 29 | "angularjs/angular-mocks.d.ts": { 30 | "commit": "99942cab1446292c79c4328218abd37621505112" 31 | }, 32 | "angularjs/angular-animate.d.ts": { 33 | "commit": "99942cab1446292c79c4328218abd37621505112" 34 | }, 35 | "bootstrap/bootstrap.d.ts": { 36 | "commit": "99942cab1446292c79c4328218abd37621505112" 37 | }, 38 | "moment/moment-node.d.ts": { 39 | "commit": "99942cab1446292c79c4328218abd37621505112" 40 | }, 41 | "moment/moment.d.ts": { 42 | "commit": "99942cab1446292c79c4328218abd37621505112" 43 | }, 44 | "sinon/sinon.d.ts": { 45 | "commit": "99942cab1446292c79c4328218abd37621505112" 46 | }, 47 | "toastr/toastr.d.ts": { 48 | "commit": "99942cab1446292c79c4328218abd37621505112" 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /typings/angular-ui-router/angular-ui-router.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.1.5+ (ui.router module) 2 | // Project: https://github.com/angular-ui/ui-router 3 | // Definitions by: Michel Salib 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare module angular.ui { 9 | 10 | interface IState { 11 | name?: string; 12 | /** 13 | * String HTML content, or function that returns an HTML string 14 | */ 15 | template?: string | {(): string}; 16 | /** 17 | * String URL path to template file OR Function, returns URL path string 18 | */ 19 | templateUrl?: string | {(): string}; 20 | /** 21 | * Function, returns HTML content string 22 | */ 23 | templateProvider?: Function | Array; 24 | /** 25 | * A controller paired to the state. Function OR name as String 26 | */ 27 | controller?: Function | string; 28 | controllerAs?: string; 29 | /** 30 | * Function (injectable), returns the actual controller function or string. 31 | */ 32 | controllerProvider?: Function; 33 | 34 | /** 35 | * Specifies the parent state of this state 36 | */ 37 | parent?: string | IState 38 | 39 | 40 | resolve?: {}; 41 | /** 42 | * A url with optional parameters. When a state is navigated or transitioned to, the $stateParams service will be populated with any parameters that were passed. 43 | */ 44 | url?: string | IUrlMatcher; 45 | /** 46 | * A map which optionally configures parameters declared in the url, or defines additional non-url parameters. Only use this within a state if you are not using url. Otherwise you can specify your parameters within the url. When a state is navigated or transitioned to, the $stateParams service will be populated with any parameters that were passed. 47 | */ 48 | params?: any; 49 | /** 50 | * Use the views property to set up multiple views. If you don't need multiple views within a single state this property is not needed. Tip: remember that often nested views are more useful and powerful than multiple sibling views. 51 | */ 52 | views?: {}; 53 | abstract?: boolean; 54 | /** 55 | * Callback function for when a state is entered. Good way to trigger an action or dispatch an event, such as opening a dialog. 56 | * If minifying your scripts, make sure to explictly annotate this function, because it won't be automatically annotated by your build tools. 57 | */ 58 | onEnter?: Function|(string|Function)[]; 59 | /** 60 | * Callback functions for when a state is entered and exited. Good way to trigger an action or dispatch an event, such as opening a dialog. 61 | * If minifying your scripts, make sure to explictly annotate this function, because it won't be automatically annotated by your build tools. 62 | */ 63 | onExit?: Function|(string|Function)[]; 64 | /** 65 | * Arbitrary data object, useful for custom configuration. 66 | */ 67 | data?: any; 68 | /** 69 | * Boolean (default true). If false will not retrigger the same state just because a search/query parameter has changed. Useful for when you'd like to modify $location.search() without triggering a reload. 70 | */ 71 | reloadOnSearch?: boolean; 72 | } 73 | 74 | interface IStateProvider extends angular.IServiceProvider { 75 | state(name:string, config:IState): IStateProvider; 76 | state(config:IState): IStateProvider; 77 | decorator(name?: string, decorator?: (state: IState, parent: Function) => any): any; 78 | } 79 | 80 | interface IUrlMatcher { 81 | concat(pattern: string): IUrlMatcher; 82 | exec(path: string, searchParams: {}): {}; 83 | parameters(): string[]; 84 | format(values: {}): string; 85 | } 86 | 87 | interface IUrlMatcherFactory { 88 | compile(pattern: string): IUrlMatcher; 89 | isMatcher(o: any): boolean; 90 | type(name: string, definition: any, definitionFn?: any): any; 91 | caseInsensitive(value: boolean): void; 92 | defaultSquashPolicy(value: string): void; 93 | strictMode(value: boolean): void; 94 | } 95 | 96 | interface IUrlRouterProvider extends angular.IServiceProvider { 97 | when(whenPath: RegExp, handler: Function): IUrlRouterProvider; 98 | when(whenPath: RegExp, handler: any[]): IUrlRouterProvider; 99 | when(whenPath: RegExp, toPath: string): IUrlRouterProvider; 100 | when(whenPath: IUrlMatcher, hanlder: Function): IUrlRouterProvider; 101 | when(whenPath: IUrlMatcher, handler: any[]): IUrlRouterProvider; 102 | when(whenPath: IUrlMatcher, toPath: string): IUrlRouterProvider; 103 | when(whenPath: string, handler: Function): IUrlRouterProvider; 104 | when(whenPath: string, handler: any[]): IUrlRouterProvider; 105 | when(whenPath: string, toPath: string): IUrlRouterProvider; 106 | otherwise(handler: Function): IUrlRouterProvider; 107 | otherwise(handler: any[]): IUrlRouterProvider; 108 | otherwise(path: string): IUrlRouterProvider; 109 | rule(handler: Function): IUrlRouterProvider; 110 | rule(handler: any[]): IUrlRouterProvider; 111 | } 112 | 113 | interface IStateOptions { 114 | /** 115 | * {boolean=true|string=} - If true will update the url in the location bar, if false will not. If string, must be "replace", which will update url and also replace last history record. 116 | */ 117 | location?: boolean | string; 118 | /** 119 | * {boolean=true}, If true will inherit url parameters from current url. 120 | */ 121 | inherit?: boolean; 122 | /** 123 | * {object=$state.$current}, When transitioning with relative path (e.g '^'), defines which state to be relative from. 124 | */ 125 | relative?: IState; 126 | /** 127 | * {boolean=true}, If true will broadcast $stateChangeStart and $stateChangeSuccess events. 128 | */ 129 | notify?: boolean; 130 | /** 131 | * {boolean=false}, If true will force transition even if the state or params have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd use this when you want to force a reload when everything is the same, including search params. 132 | */ 133 | reload?: boolean; 134 | } 135 | 136 | interface IHrefOptions { 137 | lossy?: boolean; 138 | inherit?: boolean; 139 | relative?: IState; 140 | absolute?: boolean; 141 | } 142 | 143 | interface IStateService { 144 | /** 145 | * Convenience method for transitioning to a new state. $state.go calls $state.transitionTo internally but automatically sets options to { location: true, inherit: true, relative: $state.$current, notify: true }. This allows you to easily use an absolute or relative to path and specify only the parameters you'd like to update (while letting unspecified parameters inherit from the currently active ancestor states). 146 | * 147 | * @param to Absolute state name or relative state path. Some examples: 148 | * 149 | * $state.go('contact.detail') - will go to the contact.detail state 150 | * $state.go('^') - will go to a parent state 151 | * $state.go('^.sibling') - will go to a sibling state 152 | * $state.go('.child.grandchild') - will go to grandchild state 153 | * 154 | * @param params A map of the parameters that will be sent to the state, will populate $stateParams. Any parameters that are not specified will be inherited from currently defined parameters. This allows, for example, going to a sibling state that shares parameters specified in a parent state. Parameter inheritance only works between common ancestor states, I.e. transitioning to a sibling will get you the parameters for all parents, transitioning to a child will get you all current parameters, etc. 155 | * 156 | * @param options Options object. 157 | */ 158 | go(to: string, params?: {}, options?: IStateOptions): angular.IPromise; 159 | transitionTo(state: string, params?: {}, updateLocation?: boolean): void; 160 | transitionTo(state: string, params?: {}, options?: IStateOptions): void; 161 | includes(state: string, params?: {}): boolean; 162 | is(state:string, params?: {}): boolean; 163 | is(state: IState, params?: {}): boolean; 164 | href(state: IState, params?: {}, options?: IHrefOptions): string; 165 | href(state: string, params?: {}, options?: IHrefOptions): string; 166 | get(state: string): IState; 167 | get(): IState[]; 168 | current: IState; 169 | params: IStateParamsService; 170 | reload(): void; 171 | } 172 | 173 | interface IStateParamsService { 174 | [key: string]: any; 175 | } 176 | 177 | interface IUrlRouterService { 178 | /* 179 | * Triggers an update; the same update that happens when the address bar 180 | * url changes, aka $locationChangeSuccess. 181 | * 182 | * This method is useful when you need to use preventDefault() on the 183 | * $locationChangeSuccess event, perform some custom logic (route protection, 184 | * auth, config, redirection, etc) and then finally proceed with the transition 185 | * by calling $urlRouter.sync(). 186 | * 187 | */ 188 | sync(): void; 189 | } 190 | 191 | interface IUiViewScrollProvider { 192 | /* 193 | * Reverts back to using the core $anchorScroll service for scrolling 194 | * based on the url anchor. 195 | */ 196 | useAnchorScroll(): void; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /typings/angularjs/angular-animate.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.3 (ngAnimate module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Michel Salib , Adi Dahiya , Raphael Schweizer , Cody Schaaf 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare module "angular-animate" { 9 | var _: string; 10 | export = _; 11 | } 12 | 13 | /** 14 | * ngAnimate module (angular-animate.js) 15 | */ 16 | declare module angular.animate { 17 | interface IAnimateFactory extends Function { 18 | enter?: (element: ng.IAugmentedJQuery, doneFn: Function) => IAnimateCssRunner|void; 19 | leave?: (element: ng.IAugmentedJQuery, doneFn: Function) => IAnimateCssRunner|void; 20 | addClass?: (element: ng.IAugmentedJQuery, className: string, doneFn: Function) => IAnimateCssRunner|void; 21 | removeClass?: (element: ng.IAugmentedJQuery, className: string, doneFn: Function) => IAnimateCssRunner|void; 22 | setClass?: (element: ng.IAugmentedJQuery, className: string, doneFn: Function) => IAnimateCssRunner|void; 23 | } 24 | 25 | /** 26 | * AnimateService 27 | * see http://docs.angularjs.org/api/ngAnimate/service/$animate 28 | */ 29 | interface IAnimateService extends angular.IAnimateService { 30 | /** 31 | * Globally enables / disables animations. 32 | * 33 | * @param value If provided then set the animation on or off. 34 | * @param element If provided then the element will be used to represent the enable/disable operation. 35 | * @returns current animation state 36 | */ 37 | enabled(value?: boolean, element?: JQuery): boolean; 38 | 39 | /** 40 | * Performs an inline animation on the element. 41 | * 42 | * @param element the element that will be the focus of the animation 43 | * @param from a collection of CSS styles that will be applied to the element at the start of the animation 44 | * @param to a collection of CSS styles that the element will animate towards 45 | * @param className an optional CSS class that will be added to the element for the duration of the animation (the default class is 'ng-inline-animate') 46 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 47 | * @returns the animation callback promise 48 | */ 49 | animate(element: JQuery, from: any, to: any, className?: string, options?: IAnimationOptions): IPromise; 50 | 51 | /** 52 | * Appends the element to the parentElement element that resides in the document and then runs the enter animation. 53 | * 54 | * @param element the element that will be the focus of the enter animation 55 | * @param parentElement the parent element of the element that will be the focus of the enter animation 56 | * @param afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation 57 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 58 | * @returns the animation callback promise 59 | */ 60 | enter(element: JQuery, parentElement: JQuery, afterElement?: JQuery, options?: IAnimationOptions): IPromise; 61 | 62 | /** 63 | * Runs the leave animation operation and, upon completion, removes the element from the DOM. 64 | * 65 | * @param element the element that will be the focus of the leave animation 66 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 67 | * @returns the animation callback promise 68 | */ 69 | leave(element: JQuery, options?: IAnimationOptions): IPromise; 70 | 71 | /** 72 | * Fires the move DOM operation. Just before the animation starts, the animate service will either append 73 | * it into the parentElement container or add the element directly after the afterElement element if present. 74 | * Then the move animation will be run. 75 | * 76 | * @param element the element that will be the focus of the move animation 77 | * @param parentElement the parent element of the element that will be the focus of the move animation 78 | * @param afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation 79 | * @returns the animation callback promise 80 | */ 81 | move(element: JQuery, parentElement: JQuery, afterElement?: JQuery): IPromise; 82 | 83 | /** 84 | * Triggers a custom animation event based off the className variable and then attaches the className 85 | * value to the element as a CSS class. 86 | * 87 | * @param element the element that will be animated 88 | * @param className the CSS class that will be added to the element and then animated 89 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 90 | * @returns the animation callback promise 91 | */ 92 | addClass(element: JQuery, className: string, options?: IAnimationOptions): IPromise; 93 | 94 | /** 95 | * Triggers a custom animation event based off the className variable and then removes the CSS class 96 | * provided by the className value from the element. 97 | * 98 | * @param element the element that will be animated 99 | * @param className the CSS class that will be animated and then removed from the element 100 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 101 | * @returns the animation callback promise 102 | */ 103 | removeClass(element: JQuery, className: string, options?: IAnimationOptions): IPromise; 104 | 105 | /** 106 | * Adds and/or removes the given CSS classes to and from the element. Once complete, the done() callback 107 | * will be fired (if provided). 108 | * 109 | * @param element the element which will have its CSS classes changed removed from it 110 | * @param add the CSS classes which will be added to the element 111 | * @param remove the CSS class which will be removed from the element CSS classes have been set on the element 112 | * @param options an optional collection of styles that will be picked up by the CSS transition/animation 113 | * @returns the animation callback promise 114 | */ 115 | setClass(element: JQuery, add: string, remove: string, options?: IAnimationOptions): IPromise; 116 | 117 | /** 118 | * Cancels the provided animation. 119 | */ 120 | cancel(animationPromise: IPromise): void; 121 | } 122 | 123 | /** 124 | * AngularProvider 125 | * see http://docs.angularjs.org/api/ngAnimate/provider/$animateProvider 126 | */ 127 | interface IAnimateProvider { 128 | /** 129 | * Registers a new injectable animation factory function. 130 | * 131 | * @param name The name of the animation. 132 | * @param factory The factory function that will be executed to return the animation object. 133 | */ 134 | register(name: string, factory: () => IAnimateCallbackObject): void; 135 | 136 | /** 137 | * Gets and/or sets the CSS class expression that is checked when performing an animation. 138 | * 139 | * @param expression The className expression which will be checked against all animations. 140 | * @returns The current CSS className expression value. If null then there is no expression value. 141 | */ 142 | classNameFilter(expression?: RegExp): RegExp; 143 | } 144 | 145 | /** 146 | * Angular Animation Options 147 | * see https://docs.angularjs.org/api/ngAnimate/#applying-directive-specific-styles-to-an-animation 148 | */ 149 | interface IAnimationOptions { 150 | /** 151 | * The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. 152 | */ 153 | to?: Object; 154 | 155 | /** 156 | * The starting CSS styles (a key/value object) that will be applied at the start of the animation. 157 | */ 158 | from?: Object; 159 | 160 | /** 161 | * The DOM event (e.g. enter, leave, move). When used, a generated CSS class of ng-EVENT and 162 | * ng-EVENT-active will be applied to the element during the animation. Multiple events can be provided when 163 | * spaces are used as a separator. (Note that this will not perform any DOM operation.) 164 | */ 165 | event?: string; 166 | 167 | /** 168 | * The CSS easing value that will be applied to the transition or keyframe animation (or both). 169 | */ 170 | easing?: string; 171 | 172 | /** 173 | * The raw CSS transition style that will be used (e.g. 1s linear all). 174 | */ 175 | transition?: string; 176 | 177 | /** 178 | * The raw CSS keyframe animation style that will be used (e.g. 1s my_animation linear). 179 | */ 180 | keyframe?: string; 181 | 182 | /** 183 | * A space separated list of CSS classes that will be added to the element and spread across the animation. 184 | */ 185 | addClass?: string; 186 | 187 | /** 188 | * A space separated list of CSS classes that will be removed from the element and spread across 189 | * the animation. 190 | */ 191 | removeClass?: string; 192 | 193 | /** 194 | * A number value representing the total duration of the transition and/or keyframe (note that a value 195 | * of 1 is 1000ms). If a value of 0 is provided then the animation will be skipped entirely. 196 | */ 197 | duration?: number; 198 | 199 | /** 200 | * A number value representing the total delay of the transition and/or keyframe (note that a value of 201 | * 1 is 1000ms). If a value of true is used then whatever delay value is detected from the CSS classes will be 202 | * mirrored on the elements styles (e.g. by setting delay true then the style value of the element will be 203 | * transition-delay: DETECTED_VALUE). Using true is useful when you want the CSS classes and inline styles to 204 | * all share the same CSS delay value. 205 | */ 206 | delay?: number; 207 | 208 | /** 209 | * A numeric time value representing the delay between successively animated elements (Click here to 210 | * learn how CSS-based staggering works in ngAnimate.) 211 | */ 212 | stagger?: number; 213 | 214 | /** 215 | * The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item 216 | * in the stagger; therefore when a stagger option value of 0.1 is used then there will be a stagger delay of 600ms) 217 | * applyClassesEarly - Whether or not the classes being added or removed will be used when detecting the animation. 218 | * This is set by $animate when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. 219 | * (Note that this will prevent any transitions from occuring on the classes being added and removed.) 220 | */ 221 | staggerIndex?: number; 222 | } 223 | 224 | interface IAnimateCssRunner { 225 | /** 226 | * Starts the animation 227 | * 228 | * @returns The animation runner with a done function for supplying a callback. 229 | */ 230 | start(): IAnimateCssRunnerStart; 231 | 232 | /** 233 | * Ends (aborts) the animation 234 | */ 235 | end(): void; 236 | } 237 | 238 | interface IAnimateCssRunnerStart extends IPromise { 239 | /** 240 | * Allows you to add done callbacks to the running animation 241 | * 242 | * @param callbackFn: the callback function to be run 243 | */ 244 | done(callbackFn: (animationFinished: boolean) => void): void; 245 | } 246 | 247 | /** 248 | * AnimateCssService 249 | * see http://docs.angularjs.org/api/ngAnimate/service/$animateCss 250 | */ 251 | interface IAnimateCssService { 252 | (element: JQuery, animateCssOptions: IAnimationOptions): IAnimateCssRunner; 253 | } 254 | 255 | } 256 | 257 | declare module angular { 258 | interface IModule { 259 | animate(cssSelector: string, animateFactory: angular.animate.IAnimateFactory): IModule; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /typings/angularjs/angular-sanitize.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.3 (ngSanitize module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Diego Vilar 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | declare module "angular-sanitize" { 10 | var _: string; 11 | export = _; 12 | } 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | // ngSanitize module (angular-sanitize.js) 16 | /////////////////////////////////////////////////////////////////////////////// 17 | declare module angular.sanitize { 18 | 19 | /////////////////////////////////////////////////////////////////////////// 20 | // SanitizeService 21 | // see http://docs.angularjs.org/api/ngSanitize.$sanitize 22 | /////////////////////////////////////////////////////////////////////////// 23 | interface ISanitizeService { 24 | (html: string): string; 25 | } 26 | 27 | /////////////////////////////////////////////////////////////////////////// 28 | // Filters included with the ngSanitize 29 | // see https://github.com/angular/angular.js/tree/v1.2.0/src/ngSanitize/filter 30 | /////////////////////////////////////////////////////////////////////////// 31 | export module filter { 32 | 33 | // Finds links in text input and turns them into html links. 34 | // Supports http/https/ftp/mailto and plain email address links. 35 | // see http://code.angularjs.org/1.2.0/docs/api/ngSanitize.filter:linky 36 | interface ILinky { 37 | (text: string, target?: string): string; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /typings/bardjs/bardjs.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for bardjs 0.1.4 2 | // Project: https://github.com/wardbell/bardjs 3 | // Definitions by: Andrew Archibald 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | /// 8 | /// 9 | 10 | /** 11 | * Module for bardjs functions 12 | */ 13 | declare module bard { 14 | /** 15 | * Replaces the ngMock'ed $httpBackend with the real one from ng thus 16 | * restoring the ability to issue AJAX calls to the backend with $http. 17 | * 18 | * Note that $q remains ngMocked so you must flush $http calls ($rootScope.$digest). 19 | * Use $rootScope.$apply() for this purpose. 20 | * 21 | * Could restore $q with $qReal in which case don't need to flush. 22 | */ 23 | function $httpBackend($provide: angular.auto.IProvideService): any; 24 | 25 | /** 26 | * Replaces the ngMock'ed $q with the real one from ng thus 27 | * obviating the need to flush $http and $q queues 28 | * at the expense of ability to control $q timing. 29 | */ 30 | function $q($provide: angular.auto.IProvideService): any; 31 | 32 | /** 33 | * Add names of globals to list of OK globals for this mocha spec 34 | * NB: Call this method ONLY if you're using mocha! 35 | * NB: Turn off browser-sync else mocha detects the browser-sync globals 36 | * like ` ___browserSync___` 37 | */ 38 | function addGlobals(...globals: any[]): void; 39 | 40 | /** 41 | * Prepare ngMocked application feature module 42 | * along with faked toastr, routehelper, 43 | * and faked router services. 44 | * Especially useful for controller testing 45 | * Use it as you would the ngMocks#module method 46 | * 47 | * DO NOT USE IF YOU NEED THE REAL ROUTER SERVICES! 48 | * Fall back to `angular.mock.module(...)` or just `module(...)` 49 | */ 50 | function appModule(...fns: (string | Function | Object)[]): () => void; 51 | 52 | /** 53 | * Assert a failure in mocha, without condition 54 | */ 55 | function assertFail(message: string): Chai.AssertionError; 56 | 57 | /** 58 | * Prepare ngMocked module definition that makes real $http and $q calls 59 | * Also adds fakeLogger to the end of the definition 60 | * Use it as you would the ngMocks#module method 61 | */ 62 | function asyncModule(...fns: (string | Function | Object)[]): () => void; 63 | 64 | /** 65 | * Get or set bard debugging flag 66 | */ 67 | function debugging(newFlag?: any): boolean; 68 | 69 | /** 70 | * Registers a fake logger service that you can spy on 71 | */ 72 | function fakeLogger($provide: angular.auto.IProvideService): void; 73 | 74 | /** 75 | * Registers a fake route helper provider service that you can spy on 76 | */ 77 | function fakeRouteHelperProvider($provide: angular.auto.IProvideService): void; 78 | 79 | /** 80 | * Stub out the $routeProvider so we avoid 81 | * all routing calls, including the default route 82 | * which runs on every test otherwise. 83 | * Make sure this goes before the inject in the spec. 84 | */ 85 | function fakeRouteProvider($provide: angular.auto.IProvideService): void; 86 | 87 | /** 88 | * Stub out the $stateProvider so we avoid 89 | * all routing calls, including the default state 90 | * which runs on every test otherwise. 91 | * Make sure this goes before the inject in the spec. 92 | */ 93 | function fakeStateProvider($provide: angular.auto.IProvideService): void; 94 | 95 | /** 96 | * Registers a fake toastr service that you can spy on 97 | */ 98 | function fakeToastr($provide: angular.auto.IProvideService): void; 99 | 100 | /** 101 | * Inject selected services into the windows object during test 102 | * then remove them when test ends with an `afterEach`. 103 | * 104 | * spares us the repetition of creating common service vars and injecting them 105 | * 106 | * Option: the first argument may be the mocha spec context object (`this`) 107 | * It MUST be `this` if you what to check for mocha global leaks. 108 | * Do NOT supply `this` as the first arg if you're not running mocha specs. 109 | * 110 | * remaining inject arguments may take one of 3 forms : 111 | * 112 | * function - This fn will be passed to ngMocks.inject. 113 | * Annotations extracted after inject does its thing. 114 | * [strings] - same string array you'd use to set fn.$inject 115 | * (...string) - string arguments turned into a string array 116 | */ 117 | function inject(context?: Function, ...args: string[]): void; 118 | 119 | /** 120 | * Write to console if bard debugging flag is on 121 | */ 122 | function log(message: any): void; 123 | 124 | /** 125 | * Listen to mocha test runner events 126 | * Usage in browser: 127 | * var runner = mocha.run(); 128 | * bard.mochaRunnerListener(runner); 129 | */ 130 | function mochaRunnerListener(runner: Mocha.IRunner): void; 131 | 132 | /** 133 | * Mocks out a service with sinon stubbed functions 134 | * that return the values specified in the config 135 | * 136 | * If the config value is `undefined`, 137 | * stub the service method with a dummy that doesn't return a value 138 | * 139 | * If the config value is a function, set service property with it 140 | * 141 | * If a service member is a property, not a function, 142 | * set it with the config value 143 | * If a service member name is not a key in config, 144 | * follow the same logic as above to set its members 145 | * using the config._default value (which is `undefined` if omitted) 146 | * 147 | * If there is a config entry that is NOT a member of the service 148 | * add mocked function to the service using the config value 149 | */ 150 | function mockService(service: any, config: any): any; 151 | 152 | /** 153 | * Replaces the accented characters of many European languages w/ unaccented chars 154 | * Use it in JavaScript string sorts where such characters may be encountered 155 | * Matches the default string comparers of most databases. 156 | * Ex: replaceAccentChars(a.Name) < replaceAccentChars(b.Name) 157 | * instead of: a.Name < b.Name 158 | */ 159 | function replaceAccentChars(text: string): string; 160 | 161 | /** 162 | * Assert that there are no outstanding HTTP requests after test is complete 163 | * For use with ngMocks; doesn't work for async server integration tests 164 | */ 165 | function verifyNoOutstandingHttpRequests(): void; 166 | 167 | /** 168 | * Returns a function that execute a callback function 169 | * (typically a fn making asserts) within a try/catch 170 | * The try/catch then calls the ambient "done" function 171 | * in the appropriate way for both success and failure 172 | */ 173 | function wrapWithDone(callback: Function, done: Function): Function; 174 | } 175 | -------------------------------------------------------------------------------- /typings/bootstrap/bootstrap.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Bootstrap 2.2 2 | // Project: http://twitter.github.com/bootstrap/ 3 | // Definitions by: Boris Yankov 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | interface ModalOptions { 10 | backdrop?: boolean; 11 | keyboard?: boolean; 12 | show?: boolean; 13 | remote?: string; 14 | } 15 | 16 | interface ModalOptionsBackdropString { 17 | backdrop?: string; // for "static" 18 | keyboard?: boolean; 19 | show?: boolean; 20 | remote?: string; 21 | } 22 | 23 | interface ScrollSpyOptions { 24 | offset?: number; 25 | } 26 | 27 | interface TooltipOptions { 28 | animation?: boolean; 29 | html?: boolean; 30 | placement?: any; 31 | selector?: string; 32 | title?: any; 33 | trigger?: string; 34 | delay?: any; 35 | container?: any; 36 | } 37 | 38 | interface PopoverOptions { 39 | animation?: boolean; 40 | html?: boolean; 41 | placement?: any; 42 | selector?: string; 43 | trigger?: string; 44 | title?: any; 45 | content?: any; 46 | delay?: any; 47 | container?: any; 48 | } 49 | 50 | interface CollapseOptions { 51 | parent?: any; 52 | toggle?: boolean; 53 | } 54 | 55 | interface CarouselOptions { 56 | interval?: number; 57 | pause?: string; 58 | } 59 | 60 | interface TypeaheadOptions { 61 | source?: any; 62 | items?: number; 63 | minLength?: number; 64 | matcher?: (item: any) => boolean; 65 | sorter?: (items: any[]) => any[]; 66 | updater?: (item: any) => any; 67 | highlighter?: (item: any) => string; 68 | } 69 | 70 | interface AffixOptions { 71 | offset?: any; 72 | } 73 | 74 | interface JQuery { 75 | modal(options?: ModalOptions): JQuery; 76 | modal(options?: ModalOptionsBackdropString): JQuery; 77 | modal(command: string): JQuery; 78 | 79 | dropdown(): JQuery; 80 | dropdown(command: string): JQuery; 81 | 82 | scrollspy(command: string): JQuery; 83 | scrollspy(options?: ScrollSpyOptions): JQuery; 84 | 85 | tab(): JQuery; 86 | tab(command: string): JQuery; 87 | 88 | tooltip(options?: TooltipOptions): JQuery; 89 | tooltip(command: string): JQuery; 90 | 91 | popover(options?: PopoverOptions): JQuery; 92 | popover(command: string): JQuery; 93 | 94 | alert(): JQuery; 95 | alert(command: string): JQuery; 96 | 97 | button(): JQuery; 98 | button(command: string): JQuery; 99 | 100 | collapse(options?: CollapseOptions): JQuery; 101 | collapse(command: string): JQuery; 102 | 103 | carousel(options?: CarouselOptions): JQuery; 104 | carousel(command: string): JQuery; 105 | 106 | typeahead(options?: TypeaheadOptions): JQuery; 107 | 108 | affix(options?: AffixOptions): JQuery; 109 | } 110 | 111 | declare module "bootstrap" { 112 | } 113 | -------------------------------------------------------------------------------- /typings/chai-shim.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | declare var expect: Chai.ExpectStatic; -------------------------------------------------------------------------------- /typings/chai/chai.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for chai 2.0.0 2 | // Project: http://chaijs.com/ 3 | // Definitions by: Jed Mao , 4 | // Bart van der Schoor , 5 | // Andrew Brown 6 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 7 | 8 | declare module Chai { 9 | 10 | interface ChaiStatic { 11 | expect: ExpectStatic; 12 | should(): Should; 13 | /** 14 | * Provides a way to extend the internals of Chai 15 | */ 16 | use(fn: (chai: any, utils: any) => void): any; 17 | assert: AssertStatic; 18 | config: Config; 19 | } 20 | 21 | export interface ExpectStatic extends AssertionStatic { 22 | } 23 | 24 | export interface AssertStatic extends Assert { 25 | } 26 | 27 | export interface AssertionStatic { 28 | (target: any, message?: string): Assertion; 29 | } 30 | 31 | interface ShouldAssertion { 32 | equal(value1: any, value2: any, message?: string): void; 33 | Throw: ShouldThrow; 34 | throw: ShouldThrow; 35 | exist(value: any, message?: string): void; 36 | } 37 | 38 | interface Should extends ShouldAssertion { 39 | not: ShouldAssertion; 40 | fail(actual: any, expected: any, message?: string, operator?: string): void; 41 | } 42 | 43 | interface ShouldThrow { 44 | (actual: Function): void; 45 | (actual: Function, expected: string|RegExp, message?: string): void; 46 | (actual: Function, constructor: Error|Function, expected?: string|RegExp, message?: string): void; 47 | } 48 | 49 | interface Assertion extends LanguageChains, NumericComparison, TypeComparison { 50 | not: Assertion; 51 | deep: Deep; 52 | a: TypeComparison; 53 | an: TypeComparison; 54 | include: Include; 55 | contain: Include; 56 | ok: Assertion; 57 | true: Assertion; 58 | false: Assertion; 59 | null: Assertion; 60 | undefined: Assertion; 61 | exist: Assertion; 62 | empty: Assertion; 63 | arguments: Assertion; 64 | Arguments: Assertion; 65 | equal: Equal; 66 | equals: Equal; 67 | eq: Equal; 68 | eql: Equal; 69 | eqls: Equal; 70 | property: Property; 71 | ownProperty: OwnProperty; 72 | haveOwnProperty: OwnProperty; 73 | length: Length; 74 | lengthOf: Length; 75 | match(regexp: RegExp|string, message?: string): Assertion; 76 | string(string: string, message?: string): Assertion; 77 | keys: Keys; 78 | key(string: string): Assertion; 79 | throw: Throw; 80 | throws: Throw; 81 | Throw: Throw; 82 | respondTo(method: string, message?: string): Assertion; 83 | itself: Assertion; 84 | satisfy(matcher: Function, message?: string): Assertion; 85 | closeTo(expected: number, delta: number, message?: string): Assertion; 86 | members: Members; 87 | } 88 | 89 | interface LanguageChains { 90 | to: Assertion; 91 | be: Assertion; 92 | been: Assertion; 93 | is: Assertion; 94 | that: Assertion; 95 | which: Assertion; 96 | and: Assertion; 97 | has: Assertion; 98 | have: Assertion; 99 | with: Assertion; 100 | at: Assertion; 101 | of: Assertion; 102 | same: Assertion; 103 | } 104 | 105 | interface NumericComparison { 106 | above: NumberComparer; 107 | gt: NumberComparer; 108 | greaterThan: NumberComparer; 109 | least: NumberComparer; 110 | gte: NumberComparer; 111 | below: NumberComparer; 112 | lt: NumberComparer; 113 | lessThan: NumberComparer; 114 | most: NumberComparer; 115 | lte: NumberComparer; 116 | within(start: number, finish: number, message?: string): Assertion; 117 | } 118 | 119 | interface NumberComparer { 120 | (value: number, message?: string): Assertion; 121 | } 122 | 123 | interface TypeComparison { 124 | (type: string, message?: string): Assertion; 125 | instanceof: InstanceOf; 126 | instanceOf: InstanceOf; 127 | } 128 | 129 | interface InstanceOf { 130 | (constructor: Object, message?: string): Assertion; 131 | } 132 | 133 | interface Deep { 134 | equal: Equal; 135 | include: Include; 136 | property: Property; 137 | } 138 | 139 | interface Equal { 140 | (value: any, message?: string): Assertion; 141 | } 142 | 143 | interface Property { 144 | (name: string, value?: any, message?: string): Assertion; 145 | } 146 | 147 | interface OwnProperty { 148 | (name: string, message?: string): Assertion; 149 | } 150 | 151 | interface Length extends LanguageChains, NumericComparison { 152 | (length: number, message?: string): Assertion; 153 | } 154 | 155 | interface Include { 156 | (value: Object, message?: string): Assertion; 157 | (value: string, message?: string): Assertion; 158 | (value: number, message?: string): Assertion; 159 | keys: Keys; 160 | members: Members; 161 | } 162 | 163 | interface Keys { 164 | (...keys: string[]): Assertion; 165 | (keys: any[]): Assertion; 166 | } 167 | 168 | interface Throw { 169 | (): Assertion; 170 | (expected: string, message?: string): Assertion; 171 | (expected: RegExp, message?: string): Assertion; 172 | (constructor: Error, expected?: string, message?: string): Assertion; 173 | (constructor: Error, expected?: RegExp, message?: string): Assertion; 174 | (constructor: Function, expected?: string, message?: string): Assertion; 175 | (constructor: Function, expected?: RegExp, message?: string): Assertion; 176 | } 177 | 178 | interface Members { 179 | (set: any[], message?: string): Assertion; 180 | } 181 | 182 | export interface Assert { 183 | /** 184 | * @param expression Expression to test for truthiness. 185 | * @param message Message to display on error. 186 | */ 187 | (expression: any, message?: string): void; 188 | 189 | fail(actual?: any, expected?: any, msg?: string, operator?: string): void; 190 | 191 | ok(val: any, msg?: string): void; 192 | notOk(val: any, msg?: string): void; 193 | 194 | equal(act: any, exp: any, msg?: string): void; 195 | notEqual(act: any, exp: any, msg?: string): void; 196 | 197 | strictEqual(act: any, exp: any, msg?: string): void; 198 | notStrictEqual(act: any, exp: any, msg?: string): void; 199 | 200 | deepEqual(act: any, exp: any, msg?: string): void; 201 | notDeepEqual(act: any, exp: any, msg?: string): void; 202 | 203 | isTrue(val: any, msg?: string): void; 204 | isFalse(val: any, msg?: string): void; 205 | 206 | isNull(val: any, msg?: string): void; 207 | isNotNull(val: any, msg?: string): void; 208 | 209 | isUndefined(val: any, msg?: string): void; 210 | isDefined(val: any, msg?: string): void; 211 | 212 | isFunction(val: any, msg?: string): void; 213 | isNotFunction(val: any, msg?: string): void; 214 | 215 | isObject(val: any, msg?: string): void; 216 | isNotObject(val: any, msg?: string): void; 217 | 218 | isArray(val: any, msg?: string): void; 219 | isNotArray(val: any, msg?: string): void; 220 | 221 | isString(val: any, msg?: string): void; 222 | isNotString(val: any, msg?: string): void; 223 | 224 | isNumber(val: any, msg?: string): void; 225 | isNotNumber(val: any, msg?: string): void; 226 | 227 | isBoolean(val: any, msg?: string): void; 228 | isNotBoolean(val: any, msg?: string): void; 229 | 230 | typeOf(val: any, type: string, msg?: string): void; 231 | notTypeOf(val: any, type: string, msg?: string): void; 232 | 233 | instanceOf(val: any, type: Function, msg?: string): void; 234 | notInstanceOf(val: any, type: Function, msg?: string): void; 235 | 236 | include(exp: string, inc: any, msg?: string): void; 237 | include(exp: any[], inc: any, msg?: string): void; 238 | 239 | notInclude(exp: string, inc: any, msg?: string): void; 240 | notInclude(exp: any[], inc: any, msg?: string): void; 241 | 242 | match(exp: any, re: RegExp, msg?: string): void; 243 | notMatch(exp: any, re: RegExp, msg?: string): void; 244 | 245 | property(obj: Object, prop: string, msg?: string): void; 246 | notProperty(obj: Object, prop: string, msg?: string): void; 247 | deepProperty(obj: Object, prop: string, msg?: string): void; 248 | notDeepProperty(obj: Object, prop: string, msg?: string): void; 249 | 250 | propertyVal(obj: Object, prop: string, val: any, msg?: string): void; 251 | propertyNotVal(obj: Object, prop: string, val: any, msg?: string): void; 252 | 253 | deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): void; 254 | deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): void; 255 | 256 | lengthOf(exp: any, len: number, msg?: string): void; 257 | //alias frenzy 258 | throw(fn: Function, msg?: string): void; 259 | throw(fn: Function, regExp: RegExp): void; 260 | throw(fn: Function, errType: Function, msg?: string): void; 261 | throw(fn: Function, errType: Function, regExp: RegExp): void; 262 | 263 | throws(fn: Function, msg?: string): void; 264 | throws(fn: Function, regExp: RegExp): void; 265 | throws(fn: Function, errType: Function, msg?: string): void; 266 | throws(fn: Function, errType: Function, regExp: RegExp): void; 267 | 268 | Throw(fn: Function, msg?: string): void; 269 | Throw(fn: Function, regExp: RegExp): void; 270 | Throw(fn: Function, errType: Function, msg?: string): void; 271 | Throw(fn: Function, errType: Function, regExp: RegExp): void; 272 | 273 | doesNotThrow(fn: Function, msg?: string): void; 274 | doesNotThrow(fn: Function, regExp: RegExp): void; 275 | doesNotThrow(fn: Function, errType: Function, msg?: string): void; 276 | doesNotThrow(fn: Function, errType: Function, regExp: RegExp): void; 277 | 278 | operator(val: any, operator: string, val2: any, msg?: string): void; 279 | closeTo(act: number, exp: number, delta: number, msg?: string): void; 280 | 281 | sameMembers(set1: any[], set2: any[], msg?: string): void; 282 | includeMembers(set1: any[], set2: any[], msg?: string): void; 283 | 284 | ifError(val: any, msg?: string): void; 285 | } 286 | 287 | export interface Config { 288 | includeStack: boolean; 289 | } 290 | 291 | export class AssertionError { 292 | constructor(message: string, _props?: any, ssf?: Function); 293 | name: string; 294 | message: string; 295 | showDiff: boolean; 296 | stack: string; 297 | } 298 | } 299 | 300 | declare var chai: Chai.ChaiStatic; 301 | 302 | declare module "chai" { 303 | export = chai; 304 | } 305 | 306 | interface Object { 307 | should: Chai.Assertion; 308 | } 309 | -------------------------------------------------------------------------------- /typings/mocha/mocha.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for mocha 2.2.5 2 | // Project: http://mochajs.org/ 3 | // Definitions by: Kazi Manzur Rashid , otiai10 , jt000 , Vadim Macagon 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | interface MochaSetupOptions { 7 | //milliseconds to wait before considering a test slow 8 | slow?: number; 9 | 10 | // timeout in milliseconds 11 | timeout?: number; 12 | 13 | // ui name "bdd", "tdd", "exports" etc 14 | ui?: string; 15 | 16 | //array of accepted globals 17 | globals?: any[]; 18 | 19 | // reporter instance (function or string), defaults to `mocha.reporters.Spec` 20 | reporter?: any; 21 | 22 | // bail on the first test failure 23 | bail?: boolean; 24 | 25 | // ignore global leaks 26 | ignoreLeaks?: boolean; 27 | 28 | // grep string or regexp to filter tests with 29 | grep?: any; 30 | } 31 | 32 | interface MochaDone { 33 | (error?: Error): void; 34 | } 35 | 36 | declare var mocha: Mocha; 37 | declare var describe: Mocha.IContextDefinition; 38 | declare var xdescribe: Mocha.IContextDefinition; 39 | // alias for `describe` 40 | declare var context: Mocha.IContextDefinition; 41 | // alias for `describe` 42 | declare var suite: Mocha.IContextDefinition; 43 | declare var it: Mocha.ITestDefinition; 44 | declare var xit: Mocha.ITestDefinition; 45 | // alias for `it` 46 | declare var test: Mocha.ITestDefinition; 47 | 48 | declare function before(action: () => void): void; 49 | 50 | declare function before(action: (done: MochaDone) => void): void; 51 | 52 | declare function setup(action: () => void): void; 53 | 54 | declare function setup(action: (done: MochaDone) => void): void; 55 | 56 | declare function after(action: () => void): void; 57 | 58 | declare function after(action: (done: MochaDone) => void): void; 59 | 60 | declare function teardown(action: () => void): void; 61 | 62 | declare function teardown(action: (done: MochaDone) => void): void; 63 | 64 | declare function beforeEach(action: () => void): void; 65 | 66 | declare function beforeEach(action: (done: MochaDone) => void): void; 67 | 68 | declare function suiteSetup(action: () => void): void; 69 | 70 | declare function suiteSetup(action: (done: MochaDone) => void): void; 71 | 72 | declare function afterEach(action: () => void): void; 73 | 74 | declare function afterEach(action: (done: MochaDone) => void): void; 75 | 76 | declare function suiteTeardown(action: () => void): void; 77 | 78 | declare function suiteTeardown(action: (done: MochaDone) => void): void; 79 | 80 | declare class Mocha { 81 | constructor(options?: { 82 | grep?: RegExp; 83 | ui?: string; 84 | reporter?: string; 85 | timeout?: number; 86 | bail?: boolean; 87 | }); 88 | 89 | /** Setup mocha with the given options. */ 90 | setup(options: MochaSetupOptions): Mocha; 91 | bail(value?: boolean): Mocha; 92 | addFile(file: string): Mocha; 93 | /** Sets reporter by name, defaults to "spec". */ 94 | reporter(name: string): Mocha; 95 | /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ 96 | reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha; 97 | ui(value: string): Mocha; 98 | grep(value: string): Mocha; 99 | grep(value: RegExp): Mocha; 100 | invert(): Mocha; 101 | ignoreLeaks(value: boolean): Mocha; 102 | checkLeaks(): Mocha; 103 | /** Enables growl support. */ 104 | growl(): Mocha; 105 | globals(value: string): Mocha; 106 | globals(values: string[]): Mocha; 107 | useColors(value: boolean): Mocha; 108 | useInlineDiffs(value: boolean): Mocha; 109 | timeout(value: number): Mocha; 110 | slow(value: number): Mocha; 111 | enableTimeouts(value: boolean): Mocha; 112 | asyncOnly(value: boolean): Mocha; 113 | noHighlighting(value: boolean): Mocha; 114 | /** Runs tests and invokes `onComplete()` when finished. */ 115 | run(onComplete?: (failures: number) => void): Mocha.IRunner; 116 | } 117 | 118 | // merge the Mocha class declaration with a module 119 | declare module Mocha { 120 | /** Partial interface for Mocha's `Runnable` class. */ 121 | interface IRunnable { 122 | title: string; 123 | fn: Function; 124 | async: boolean; 125 | sync: boolean; 126 | timedOut: boolean; 127 | } 128 | 129 | /** Partial interface for Mocha's `Suite` class. */ 130 | interface ISuite { 131 | parent: ISuite; 132 | title: string; 133 | 134 | fullTitle(): string; 135 | } 136 | 137 | /** Partial interface for Mocha's `Test` class. */ 138 | interface ITest extends IRunnable { 139 | parent: ISuite; 140 | pending: boolean; 141 | 142 | fullTitle(): string; 143 | } 144 | 145 | /** Partial interface for Mocha's `Runner` class. */ 146 | interface IRunner {} 147 | 148 | interface IContextDefinition { 149 | (description: string, spec: () => void): ISuite; 150 | only(description: string, spec: () => void): ISuite; 151 | skip(description: string, spec: () => void): void; 152 | timeout(ms: number): void; 153 | } 154 | 155 | interface ITestDefinition { 156 | (expectation: string, assertion?: () => void): ITest; 157 | (expectation: string, assertion?: (done: MochaDone) => void): ITest; 158 | only(expectation: string, assertion?: () => void): ITest; 159 | only(expectation: string, assertion?: (done: MochaDone) => void): ITest; 160 | skip(expectation: string, assertion?: () => void): void; 161 | skip(expectation: string, assertion?: (done: MochaDone) => void): void; 162 | timeout(ms: number): void; 163 | } 164 | 165 | export module reporters { 166 | export class Base { 167 | stats: { 168 | suites: number; 169 | tests: number; 170 | passes: number; 171 | pending: number; 172 | failures: number; 173 | }; 174 | 175 | constructor(runner: IRunner); 176 | } 177 | 178 | export class Doc extends Base {} 179 | export class Dot extends Base {} 180 | export class HTML extends Base {} 181 | export class HTMLCov extends Base {} 182 | export class JSON extends Base {} 183 | export class JSONCov extends Base {} 184 | export class JSONStream extends Base {} 185 | export class Landing extends Base {} 186 | export class List extends Base {} 187 | export class Markdown extends Base {} 188 | export class Min extends Base {} 189 | export class Nyan extends Base {} 190 | export class Progress extends Base { 191 | /** 192 | * @param options.open String used to indicate the start of the progress bar. 193 | * @param options.complete String used to indicate a complete test on the progress bar. 194 | * @param options.incomplete String used to indicate an incomplete test on the progress bar. 195 | * @param options.close String used to indicate the end of the progress bar. 196 | */ 197 | constructor(runner: IRunner, options?: { 198 | open?: string; 199 | complete?: string; 200 | incomplete?: string; 201 | close?: string; 202 | }); 203 | } 204 | export class Spec extends Base {} 205 | export class TAP extends Base {} 206 | export class XUnit extends Base { 207 | constructor(runner: IRunner, options?: any); 208 | } 209 | } 210 | } 211 | 212 | declare module "mocha" { 213 | export = Mocha; 214 | } 215 | -------------------------------------------------------------------------------- /typings/moment/moment.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Moment.js 2.8.0 2 | // Project: https://github.com/timrwood/moment 3 | // Definitions by: Michael Lakerveld , Aaron King , Hiroki Horiuchi , Dick van den Brink , Adi Dahiya 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare var moment: moment.MomentStatic; 9 | -------------------------------------------------------------------------------- /typings/toastr/toastr.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Toastr 2.0.1 2 | // Project: https://github.com/CodeSeven/toastr 3 | // Definitions by: Boris Yankov 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | interface ToastrOptions { 10 | /** 11 | * Optionally override the animation easing to show or hide the toasts. Default is swing. swing and linear are built into jQuery. 12 | */ 13 | showEasing?: string; 14 | /** 15 | * Optionally override the animation easing to show or hide the toasts. Default is swing. swing and linear are built into jQuery. 16 | */ 17 | hideEasing?: string; 18 | /** 19 | * Use the jQuery show/hide method of your choice. These default to fadeIn/fadeOut. The methods fadeIn/fadeOut, slideDown/slideUp, and show/hide are built into jQuery. 20 | */ 21 | showMethod?: string; 22 | /** 23 | * Use the jQuery show/hide method of your choice. These default to fadeIn/fadeOut. The methods fadeIn/fadeOut, slideDown/slideUp, and show/hide are built into jQuery. 24 | */ 25 | hideMethod?: string; 26 | /** 27 | * Should a close button be shown 28 | */ 29 | closeButton?: boolean; 30 | /** 31 | * Html for the close button 32 | */ 33 | closeHtml?: string; 34 | /** 35 | * Should clicking on toast dismiss it? 36 | */ 37 | tapToDismiss?: boolean; 38 | /** 39 | * CSS class the toast element will be given 40 | */ 41 | toastClass?: string; 42 | /** 43 | * Id toast container will be given 44 | */ 45 | containerId?: string; 46 | /** 47 | * Should debug details be outputted to the console 48 | */ 49 | debug?: boolean; 50 | /** 51 | * Time in milliseconds the toast should take to show 52 | */ 53 | showDuration?: number; 54 | /** 55 | * onShown function callback 56 | **/ 57 | onShown?: () => void; 58 | /** 59 | * Time in milliseconds the toast should take to hide 60 | */ 61 | hideDuration?: number; 62 | /** 63 | * onHidden function callback 64 | **/ 65 | onHidden?: () => void; 66 | /** 67 | * Time in milliseconds the toast should be displayed after mouse over 68 | */ 69 | extendedTimeOut?: number; 70 | iconClasses?: { 71 | /** 72 | * Icon to use on error toasts 73 | */ 74 | error: string; 75 | /** 76 | * Icon to use on info toasts 77 | */ 78 | info: string; 79 | /** 80 | * Icon to use on success toasts 81 | */ 82 | success: string; 83 | /** 84 | * Icon to use on warning toasts 85 | */ 86 | warning: string; 87 | }; 88 | /** 89 | * Icon to use for toast 90 | */ 91 | iconClass?: string; 92 | /** 93 | * Where toast should be displayed 94 | */ 95 | positionClass?: string; 96 | /** 97 | * Where toast should be displayed - background 98 | */ 99 | backgroundpositionClass?: string; 100 | /** 101 | * Time in milliseconds that the toast should be displayed 102 | */ 103 | timeOut?: number; 104 | /** 105 | * CSS class the title element will be given 106 | */ 107 | titleClass?: string; 108 | /** 109 | * CSS class the message element will be given 110 | */ 111 | messageClass?: string; 112 | /** 113 | * Set newest toast to appear on top 114 | **/ 115 | newestOnTop?: boolean; 116 | 117 | /** 118 | * Rather than having identical toasts stack, set the preventDuplicates property to true. Duplicates are matched to the previous toast based on their message content. 119 | */ 120 | preventDuplicates?: boolean; 121 | 122 | /** 123 | * Visually indicates how long before a toast expires. 124 | */ 125 | progressBar?: boolean; 126 | 127 | /** 128 | * Function to execute on toast click 129 | */ 130 | onclick?: () => void; 131 | } 132 | 133 | interface ToastrDisplayMethod { 134 | /** 135 | * Create a toast 136 | * 137 | * @param message Message to display in toast 138 | */ 139 | (message: string): JQuery; 140 | /** 141 | * Create a toast 142 | * 143 | * @param message Message to display in toast 144 | * @param title Title to display on toast 145 | */ 146 | (message: string, title: string): JQuery; 147 | /** 148 | * Create a toast 149 | * 150 | * @param message Message to display in toast 151 | * @param title Title to display on toast 152 | * @param overrides Option values for toast 153 | */ 154 | (message: string, title: string, overrides: ToastrOptions): JQuery; 155 | } 156 | 157 | interface Toastr { 158 | /** 159 | * Clear toasts 160 | */ 161 | clear: { 162 | /** 163 | * Clear all toasts 164 | */ 165 | (): void; 166 | /** 167 | * Clear specific toast 168 | * 169 | * @param toast Toast to clear 170 | */ 171 | (toast: JQuery): void; 172 | }; 173 | /** 174 | * Create an error toast 175 | */ 176 | error: ToastrDisplayMethod; 177 | /** 178 | * Create an info toast 179 | */ 180 | info: ToastrDisplayMethod; 181 | /** 182 | * Create an options object 183 | */ 184 | options: ToastrOptions; 185 | /** 186 | * Create a success toast 187 | */ 188 | success: ToastrDisplayMethod; 189 | /** 190 | * Create a warning toast 191 | */ 192 | warning: ToastrDisplayMethod; 193 | /** 194 | * Get toastr version 195 | */ 196 | version: string; 197 | } 198 | 199 | declare var toastr: Toastr; 200 | declare module "toastr" { 201 | export = toastr; 202 | } 203 | -------------------------------------------------------------------------------- /typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | /// 6 | /// 7 | /// 8 | /// 9 | /// 10 | /// 11 | /// 12 | /// 13 | /// 14 | /// 15 | --------------------------------------------------------------------------------