├── .gitignore ├── README.md ├── angular ├── .editorconfig ├── README.md ├── angular-cli-build.js ├── angular-cli.json ├── config │ ├── environment.dev.ts │ ├── environment.js │ ├── environment.prod.ts │ ├── karma-test-shim.js │ ├── karma.conf.js │ └── protractor.conf.js ├── e2e │ ├── app.e2e-spec.ts │ ├── app.po.ts │ ├── tsconfig.json │ └── typings.d.ts ├── package.json ├── src │ ├── app │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── authmanager.ts │ │ ├── components │ │ │ ├── auth │ │ │ │ ├── auth.html │ │ │ │ └── auth.ts │ │ │ ├── companies │ │ │ │ ├── companies.html │ │ │ │ └── companies.ts │ │ │ ├── projects │ │ │ │ ├── projects.html │ │ │ │ └── projects.ts │ │ │ ├── task │ │ │ │ ├── task.html │ │ │ │ ├── task.ts │ │ │ │ ├── taskRO.html │ │ │ │ └── taskRO.ts │ │ │ └── tasks │ │ │ │ ├── tasks.html │ │ │ │ ├── tasks.ts │ │ │ │ ├── tasksRO.html │ │ │ │ └── tasksRO.ts │ │ ├── environment.ts │ │ ├── index.ts │ │ ├── interfaces.ts │ │ ├── shared │ │ │ └── index.ts │ │ └── utility.ts │ ├── css │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.min.css │ │ ├── dashboard.css │ │ └── ie10-viewport-bug-workaround.css │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── index.html │ ├── js │ │ ├── bootstrap.min.js │ │ ├── holder.min.js │ │ ├── ie-emulation-modes-warning.js │ │ ├── ie10-viewport-bug-workaround.js │ │ └── jquery-2.1.4.min.js │ ├── main.ts │ ├── system-config.ts │ ├── tsconfig.json │ └── typings.d.ts ├── tslint.json ├── typings.json └── typings │ ├── browser.d.ts │ ├── browser │ └── ambient │ │ ├── angular-protractor │ │ └── index.d.ts │ │ ├── es6-shim │ │ └── index.d.ts │ │ ├── jasmine │ │ └── index.d.ts │ │ └── selenium-webdriver │ │ └── index.d.ts │ ├── main.d.ts │ └── main │ └── ambient │ ├── angular-protractor │ └── index.d.ts │ ├── es6-shim │ └── index.d.ts │ ├── jasmine │ └── index.d.ts │ └── selenium-webdriver │ └── index.d.ts ├── app.js ├── config.json ├── models ├── company.js ├── project.js ├── task.js └── user.js ├── package-lock.json ├── package.json ├── routes ├── cdn.js ├── company.js ├── project.js ├── task.js └── user.js └── validators └── validators.js /.gitignore: -------------------------------------------------------------------------------- 1 | angular/public 2 | angular/tmp 3 | node_modules 4 | public 5 | cdn 6 | 7 | .DS_Store* 8 | Thumbs.db 9 | ~* 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CEAN Stack Project Tracking Application 2 | 3 | This project is meant to demonstrate a full stack application using Couchbase, Express Framework, Angular 2, and Node.js. This particular stack is called the CEAN stack or CANE stack. With the Object Document Modeling (ODM) tool Ottoman, we can easily create relationships between documents within the application. 4 | 5 | ## Installation 6 | 7 | Download or clone the project from GitHub and run the following via the Command Prompt (Windows) or Terminal (Mac and Linux): 8 | 9 | ``` 10 | npm install 11 | cd angular 12 | npm install 13 | ``` 14 | 15 | This will install all Node.js and Angular 2 dependencies into the project. With the dependencies available, the TypeScript files need to be compiled into their JavaScript version. This can be done by executing the following from the Terminal or Command Prompt: 16 | 17 | ``` 18 | cd angular 19 | ng build --output-path=../public 20 | ``` 21 | 22 | If there were no compile time errors, you should be left with a **public** directory that will be picked up by Node.js when the project is run. 23 | 24 | ## Configuration 25 | 26 | This project expects a Couchbase Server bucket to exist named **comply**. This bucket name can be changed in the project's **config.json** file. 27 | 28 | ## Running the Project 29 | 30 | From the root of the project, in your Command Prompt or Terminal execute the following to run the Node.js backend: 31 | 32 | ``` 33 | node app.js 34 | ``` 35 | 36 | Because the Angular 2 TypeScript files were compiled in the installation step, and because they are bundled with the Node.js code, the application can be accessed via **http://localhost:3000** 37 | 38 | ## Resources 39 | 40 | Couchbase Server - [http://www.couchbase.com](http://www.couchbase.com) 41 | 42 | Ottoman - [http://ottomanjs.com](http://ottomanjs.com) 43 | 44 | Couchbase Compliance Demo with Java - [https://github.com/couchbaselabs/comply-java](https://github.com/couchbaselabs/comply-java) 45 | 46 | Couchbase Compliance Demo with GoLang - [https://github.com/couchbaselabs/comply-golang](https://github.com/couchbaselabs/comply-golang) 47 | -------------------------------------------------------------------------------- /angular/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /angular/README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 | 3 | This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.9. 4 | 5 | ## Development server 6 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 7 | 8 | ## Code scaffolding 9 | 10 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/route/class`. 11 | 12 | ## Build 13 | 14 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 15 | 16 | ## Running unit tests 17 | 18 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 19 | 20 | ## Running end-to-end tests 21 | 22 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 23 | Before running the tests make sure you are serving the app via `ng serve`. 24 | 25 | ## Deploying to Github Pages 26 | 27 | Run `ng github-pages:deploy` to deploy to Github Pages. 28 | 29 | ## Further help 30 | 31 | To get more help on the `angular-cli` use `ng --help` or go check out the [Angular-CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 32 | -------------------------------------------------------------------------------- /angular/angular-cli-build.js: -------------------------------------------------------------------------------- 1 | // Angular-CLI build configuration 2 | // This file lists all the node_modules files that will be used in a build 3 | // Also see https://github.com/angular/angular-cli/wiki/3rd-party-libs 4 | 5 | /* global require, module */ 6 | 7 | var Angular2App = require('angular-cli/lib/broccoli/angular2-app'); 8 | 9 | module.exports = function(defaults) { 10 | return new Angular2App(defaults, { 11 | vendorNpmFiles: [ 12 | 'systemjs/dist/system-polyfills.js', 13 | 'systemjs/dist/system.src.js', 14 | 'zone.js/dist/**/*.+(js|js.map)', 15 | 'es6-shim/es6-shim.js', 16 | 'reflect-metadata/**/*.+(ts|js|js.map)', 17 | 'rxjs/**/*.+(js|js.map)', 18 | '@angular/**/*.+(js|js.map)' 19 | ] 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /angular/angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": { 3 | "version": "1.0.0-beta.9", 4 | "name": "angular" 5 | }, 6 | "apps": [ 7 | { 8 | "main": "src/main.ts", 9 | "tsconfig": "src/tsconfig.json", 10 | "mobile": false 11 | } 12 | ], 13 | "addons": [], 14 | "packages": [], 15 | "e2e": { 16 | "protractor": { 17 | "config": "config/protractor.conf.js" 18 | } 19 | }, 20 | "test": { 21 | "karma": { 22 | "config": "config/karma.conf.js" 23 | } 24 | }, 25 | "defaults": { 26 | "prefix": "app", 27 | "sourceDir": "src", 28 | "styleExt": "css", 29 | "prefixInterfaces": false, 30 | "lazyRoutePrefix": "+" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /angular/config/environment.dev.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false 3 | }; 4 | -------------------------------------------------------------------------------- /angular/config/environment.js: -------------------------------------------------------------------------------- 1 | // Angular-CLI server configuration 2 | // Unrelated to environment.dev|prod.ts 3 | 4 | /* jshint node: true */ 5 | 6 | module.exports = function(environment) { 7 | return { 8 | environment: environment, 9 | baseURL: '/', 10 | locationType: 'auto' 11 | }; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /angular/config/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /angular/config/karma-test-shim.js: -------------------------------------------------------------------------------- 1 | // Test shim for Karma, needed to load files via SystemJS 2 | 3 | /*global jasmine, __karma__, window*/ 4 | Error.stackTraceLimit = Infinity; 5 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000; 6 | 7 | __karma__.loaded = function () { 8 | }; 9 | 10 | var distPath = '/base/dist/'; 11 | var appPaths = ['app']; //Add all valid source code folders here 12 | 13 | function isJsFile(path) { 14 | return path.slice(-3) == '.js'; 15 | } 16 | 17 | function isSpecFile(path) { 18 | return path.slice(-8) == '.spec.js'; 19 | } 20 | 21 | function isAppFile(path) { 22 | return isJsFile(path) && appPaths.some(function(appPath) { 23 | var fullAppPath = distPath + appPath + '/'; 24 | return path.substr(0, fullAppPath.length) == fullAppPath; 25 | }); 26 | } 27 | 28 | var allSpecFiles = Object.keys(window.__karma__.files) 29 | .filter(isSpecFile) 30 | .filter(isAppFile); 31 | 32 | // Load our SystemJS configuration. 33 | System.config({ 34 | baseURL: distPath 35 | }); 36 | 37 | System.import('system-config.js').then(function() { 38 | // Load and configure the TestComponentBuilder. 39 | return Promise.all([ 40 | System.import('@angular/core/testing'), 41 | System.import('@angular/platform-browser-dynamic/testing') 42 | ]).then(function (providers) { 43 | var testing = providers[0]; 44 | var testingBrowser = providers[1]; 45 | 46 | testing.setBaseTestProviders(testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, 47 | testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS); 48 | }); 49 | }).then(function() { 50 | // Finally, load all spec files. 51 | // This will run the tests directly. 52 | return Promise.all( 53 | allSpecFiles.map(function (moduleName) { 54 | return System.import(moduleName); 55 | })); 56 | }).then(__karma__.start, __karma__.error); -------------------------------------------------------------------------------- /angular/config/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '..', 7 | frameworks: ['jasmine'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher') 11 | ], 12 | customLaunchers: { 13 | // chrome setup for travis CI using chromium 14 | Chrome_travis_ci: { 15 | base: 'Chrome', 16 | flags: ['--no-sandbox'] 17 | } 18 | }, 19 | files: [ 20 | { pattern: 'dist/vendor/es6-shim/es6-shim.js', included: true, watched: false }, 21 | { pattern: 'dist/vendor/zone.js/dist/zone.js', included: true, watched: false }, 22 | { pattern: 'dist/vendor/reflect-metadata/Reflect.js', included: true, watched: false }, 23 | { pattern: 'dist/vendor/systemjs/dist/system-polyfills.js', included: true, watched: false }, 24 | { pattern: 'dist/vendor/systemjs/dist/system.src.js', included: true, watched: false }, 25 | { pattern: 'dist/vendor/zone.js/dist/async-test.js', included: true, watched: false }, 26 | { pattern: 'dist/vendor/zone.js/dist/fake-async-test.js', included: true, watched: false }, 27 | 28 | { pattern: 'config/karma-test-shim.js', included: true, watched: true }, 29 | 30 | // Distribution folder. 31 | { pattern: 'dist/**/*', included: false, watched: true } 32 | ], 33 | exclude: [ 34 | // Vendor packages might include spec files. We don't want to use those. 35 | 'dist/vendor/**/*.spec.js' 36 | ], 37 | preprocessors: {}, 38 | reporters: ['progress'], 39 | port: 9876, 40 | colors: true, 41 | logLevel: config.LOG_INFO, 42 | autoWatch: true, 43 | browsers: ['Chrome'], 44 | singleRun: false 45 | }); 46 | }; 47 | -------------------------------------------------------------------------------- /angular/config/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/docs/referenceConf.js 3 | 4 | /*global jasmine */ 5 | var SpecReporter = require('jasmine-spec-reporter'); 6 | 7 | exports.config = { 8 | allScriptsTimeout: 11000, 9 | specs: [ 10 | '../e2e/**/*.e2e-spec.ts' 11 | ], 12 | capabilities: { 13 | 'browserName': 'chrome' 14 | }, 15 | directConnect: true, 16 | baseUrl: 'http://localhost:4200/', 17 | framework: 'jasmine', 18 | jasmineNodeOpts: { 19 | showColors: true, 20 | defaultTimeoutInterval: 30000, 21 | print: function() {} 22 | }, 23 | useAllAngular2AppRoots: true, 24 | beforeLaunch: function() { 25 | require('ts-node').register({ 26 | project: 'e2e' 27 | }); 28 | }, 29 | onPrepare: function() { 30 | jasmine.getEnv().addReporter(new SpecReporter()); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /angular/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AngularPage } from './app.po'; 2 | 3 | describe('angular App', function() { 4 | let page: AngularPage; 5 | 6 | beforeEach(() => { 7 | page = new AngularPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /angular/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | export class AngularPage { 2 | navigateTo() { 3 | return browser.get('/'); 4 | } 5 | 6 | getParagraphText() { 7 | return element(by.css('app-root h1')).getText(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /angular/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "mapRoot": "", 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "noEmitOnError": true, 11 | "noImplicitAny": false, 12 | "rootDir": ".", 13 | "sourceMap": true, 14 | "sourceRoot": "/", 15 | "target": "es5" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /angular/e2e/typings.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /angular/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "angular-cli": {}, 6 | "scripts": { 7 | "start": "ng serve", 8 | "postinstall": "typings install", 9 | "lint": "tslint \"src/**/*.ts\"", 10 | "test": "ng test", 11 | "pree2e": "webdriver-manager update", 12 | "e2e": "protractor" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular/common": "2.0.0-rc.3", 17 | "@angular/compiler": "2.0.0-rc.3", 18 | "@angular/core": "2.0.0-rc.3", 19 | "@angular/forms": "0.2.0", 20 | "@angular/http": "2.0.0-rc.3", 21 | "@angular/platform-browser": "2.0.0-rc.3", 22 | "@angular/platform-browser-dynamic": "2.0.0-rc.3", 23 | "@angular/router": "3.0.0-alpha.8", 24 | "es6-shim": "0.35.1", 25 | "reflect-metadata": "0.1.3", 26 | "rxjs": "5.0.0-beta.6", 27 | "systemjs": "0.19.26", 28 | "zone.js": "0.6.12" 29 | }, 30 | "devDependencies": { 31 | "angular-cli": "1.0.0-beta.9", 32 | "codelyzer": "0.0.20", 33 | "ember-cli-inject-live-reload": "1.4.0", 34 | "jasmine-core": "2.4.1", 35 | "jasmine-spec-reporter": "2.5.0", 36 | "karma": "0.13.22", 37 | "karma-chrome-launcher": "0.2.3", 38 | "karma-jasmine": "0.3.8", 39 | "protractor": "3.3.0", 40 | "ts-node": "0.5.5", 41 | "tslint": "3.11.0", 42 | "typescript": "1.8.10", 43 | "typings": "0.8.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /angular/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/app/app.component.css -------------------------------------------------------------------------------- /angular/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 |
26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /angular/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable:no-unused-variable */ 2 | 3 | import { 4 | beforeEach, beforeEachProviders, 5 | describe, xdescribe, 6 | expect, it, xit, 7 | async, inject 8 | } from '@angular/core/testing'; 9 | import { AppComponent } from './app.component'; 10 | 11 | beforeEachProviders(() => [AppComponent]); 12 | 13 | describe('App: Angular', () => { 14 | it('should create the app', 15 | inject([AppComponent], (app: AppComponent) => { 16 | expect(app).toBeTruthy(); 17 | })); 18 | }); 19 | -------------------------------------------------------------------------------- /angular/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { RuntimeCompiler} from '@angular/compiler/src/runtime_compiler'; 2 | import { Component } from '@angular/core'; 3 | import { ROUTER_DIRECTIVES, Router } from "@angular/router"; 4 | import { Location } from "@angular/common"; 5 | import { AuthManager } from "./authmanager"; 6 | 7 | @Component({ 8 | moduleId: module.id, 9 | selector: 'app-root', 10 | directives: [ROUTER_DIRECTIVES], 11 | templateUrl: 'app.component.html', 12 | styleUrls: ['app.component.css'] 13 | }) 14 | export class AppComponent { 15 | 16 | router: Router; 17 | location: Location; 18 | authManager: AuthManager; 19 | 20 | constructor(router: Router, location: Location, authManager: AuthManager, private _runtimeCompiler: RuntimeCompiler) { 21 | this._runtimeCompiler.clearCache(); 22 | this.router = router; 23 | this.location = location; 24 | this.authManager = authManager; 25 | if(!this.authManager.isAuthenticated()) { 26 | this.router.navigate(["/auth"]); 27 | } 28 | } 29 | 30 | logout() { 31 | this.authManager.logout(); 32 | this.router.navigate(["/auth"]); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /angular/src/app/authmanager.ts: -------------------------------------------------------------------------------- 1 | import {Injectable, Inject} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {IUser} from "./interfaces"; 4 | import {Utility} from "./utility"; 5 | 6 | @Injectable() 7 | 8 | export class AuthManager { 9 | 10 | http: Http; 11 | utility: Utility; 12 | 13 | constructor(http: Http, utility: Utility) { 14 | this.http = http; 15 | this.utility = utility; 16 | } 17 | 18 | isAuthenticated() { 19 | if (!localStorage.getItem("user") || localStorage.getItem("user") == "") { 20 | return false; 21 | } else { 22 | return true; 23 | } 24 | } 25 | 26 | getAuthToken() { 27 | if (localStorage.getItem("user")) { 28 | return JSON.parse(localStorage.getItem("user"))._id; 29 | } else { 30 | return null; 31 | } 32 | } 33 | 34 | getUserEmail() { 35 | if (localStorage.getItem("user")) { 36 | return JSON.parse(localStorage.getItem("user")).email; 37 | } else { 38 | return null; 39 | } 40 | } 41 | 42 | login(email: string, password: string) { 43 | return new Promise((resolve, reject) => { 44 | this.utility.makeGetRequest("/api/user/login", [email, password]).then((result) => { 45 | if(result) { 46 | localStorage.setItem("user", JSON.stringify(result)); 47 | resolve(result); 48 | } else { 49 | reject("User not found"); 50 | } 51 | }, (error) => { 52 | reject(error); 53 | }); 54 | }); 55 | } 56 | 57 | logout() { 58 | localStorage.clear(); 59 | } 60 | 61 | register(user: IUser) { 62 | return this.utility.makePostRequest("/api/user/create", [], user); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /angular/src/app/components/auth/auth.html: -------------------------------------------------------------------------------- 1 |
2 |

Auth

3 |
4 |
5 | 6 |
7 | 8 |
9 |
10 |
11 | 12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 |
21 |
22 |
23 |
24 | 25 | 112 | -------------------------------------------------------------------------------- /angular/src/app/components/auth/auth.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {Router} from "@angular/router"; 4 | import {AuthManager} from "../../authmanager"; 5 | import {IUser, ICompany} from "../../interfaces"; 6 | import {Utility} from "../../utility"; 7 | 8 | @Component({ 9 | selector: "auth", 10 | viewProviders: [HTTP_PROVIDERS, AuthManager, Utility], 11 | templateUrl: "./app/components/auth/auth.html" 12 | }) 13 | export class AuthPage { 14 | 15 | http: Http; 16 | authManager: AuthManager; 17 | router: Router; 18 | companies: Array; 19 | userCompany: string; 20 | utility: Utility; 21 | 22 | constructor(http: Http, router: Router, authManager: AuthManager, utility: Utility) { 23 | this.router = router; 24 | this.authManager = authManager; 25 | this.http = http; 26 | this.utility = utility; 27 | this.companies = []; 28 | this.userCompany = ""; 29 | this.utility.makeGetRequest("/api/company/getAll", []).then((result) => { 30 | this.companies = > result; 31 | }, (error) => { 32 | console.error(error); 33 | }); 34 | } 35 | 36 | login(email: string, password: string) { 37 | if (!email || email == "") { 38 | console.error("Email must exist"); 39 | } else if (!password || password == "") { 40 | console.error("Password must exist"); 41 | } else { 42 | this.authManager.login(email, password).then((result) => { 43 | this.router.navigate(["/"]); 44 | }, (error) => { 45 | console.error(error); 46 | }); 47 | } 48 | } 49 | 50 | register(firstname: string, lastname: string, street: string, city: string, state: string, zip: string, country: string, phone: string, email: string, password: string, company: string) { 51 | var postBody: IUser = { 52 | name: { 53 | first: firstname, 54 | last: lastname 55 | }, 56 | address: { 57 | street: street, 58 | city: city, 59 | state: state, 60 | zip: zip, 61 | country: country 62 | }, 63 | email: email, 64 | phone: phone, 65 | password: password, 66 | company: company 67 | } 68 | this.authManager.register(postBody).then((result) => { 69 | this.authManager.login(email, password).then((result) => { 70 | this.router.navigate(["/"]); 71 | }, (error) => { 72 | console.error(error); 73 | }); 74 | }, (error) => { 75 | console.error(error); 76 | });; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /angular/src/app/components/companies/companies.html: -------------------------------------------------------------------------------- 1 |
2 |

Companies

3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
NameCityStateWebsite
{{company.name}}{{company.address.city}}{{company.address.state}}{{company.website}}
23 |
24 | 25 | 91 | -------------------------------------------------------------------------------- /angular/src/app/components/companies/companies.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {Router} from "@angular/router"; 4 | import {AuthManager} from "../../authmanager"; 5 | import {ICompany} from "../../interfaces"; 6 | import {Utility} from "../../utility"; 7 | 8 | @Component({ 9 | selector: "companies", 10 | viewProviders: [HTTP_PROVIDERS, AuthManager, Utility], 11 | templateUrl: "./app/components/companies/companies.html" 12 | }) 13 | export class CompaniesPage { 14 | 15 | http: Http; 16 | companies: Array; 17 | utility: Utility; 18 | 19 | constructor(http: Http, router: Router, authManager: AuthManager, utility: Utility) { 20 | if (!authManager.isAuthenticated()) { 21 | router.navigate(["/auth"]); 22 | } 23 | this.http = http; 24 | this.utility = utility; 25 | this.companies = []; 26 | this.utility.makeGetRequest("/api/company/getAll", []).then((result) => { 27 | this.companies = > result; 28 | }, (error) => { 29 | console.error(error); 30 | }); 31 | } 32 | 33 | create(name: string, street: string, city: string, state: string, zip: string, country: string, phone: string, website: string) { 34 | this.utility.makePostRequest("/api/company/create", [], { 35 | name: name, 36 | address: { 37 | street: street, 38 | city: city, 39 | state: state, 40 | country: country, 41 | zip: zip 42 | }, 43 | phone: phone, 44 | website: website 45 | }).then((result) => { 46 | this.companies.push( result); 47 | }, (error) => { 48 | console.error(error); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /angular/src/app/components/projects/projects.html: -------------------------------------------------------------------------------- 1 |
2 |

Projects

3 |
4 |
5 | 6 |
7 |
8 |
9 |

Tasks I'm Assigned

10 |
11 |
12 |
13 |
14 | {{task.name}} 15 |
16 |
17 | {{task.description.substring(0, 200)}} ... 18 |
19 |
20 |
21 |
22 |

Project's I Own

23 |
24 |
25 |
26 |
27 | {{project.name}} 28 |
29 |
30 | {{project.description.substring(0, 200)}} ... 31 |
32 |
33 |
34 |
35 |

Project's I'm A Part Of

36 |
37 |
38 |
39 |
40 | {{project.name}} 41 |
42 |
43 | {{project.description.substring(0, 200)}} ... 44 |
45 |
46 |
47 |
48 |
49 | 50 | 80 | -------------------------------------------------------------------------------- /angular/src/app/components/projects/projects.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {Router, ROUTER_DIRECTIVES} from "@angular/router"; 4 | import {AuthManager} from "../../authmanager"; 5 | import {IProject, ITask, IUser} from "../../interfaces"; 6 | import {Utility} from "../../utility"; 7 | 8 | @Component({ 9 | selector: "projects", 10 | viewProviders: [HTTP_PROVIDERS, AuthManager, Utility], 11 | directives: [ROUTER_DIRECTIVES], 12 | templateUrl: "./app/components/projects/projects.html" 13 | }) 14 | export class ProjectsPage { 15 | 16 | http: Http; 17 | projects: Array; 18 | otherProjects: Array; 19 | assignedTasks: Array; 20 | authManager: AuthManager; 21 | utility: Utility; 22 | 23 | constructor(http: Http, router: Router, authManager: AuthManager, utility: Utility) { 24 | this.authManager = authManager; 25 | if (!authManager.isAuthenticated()) { 26 | router.navigate(["/auth"]); 27 | } 28 | this.http = http; 29 | this.utility = utility; 30 | this.getProjects(); 31 | this.getOtherProjects(); 32 | this.getAssignedTasks(); 33 | } 34 | 35 | getProjects() { 36 | this.utility.makeGetRequest("/api/project/getAll", [this.authManager.getAuthToken()]).then((result) => { 37 | this.projects = > result; 38 | }, (error) => { 39 | console.error(error); 40 | }); 41 | } 42 | 43 | getOtherProjects() { 44 | this.otherProjects = []; 45 | this.utility.makeGetRequest("/api/project/getOther", [this.authManager.getAuthToken()]).then((result: Array) => { 46 | this.otherProjects = []; 47 | for(var i = 0; i < result.length; i++) { 48 | if(result[i].owner._id != this.authManager.getAuthToken()) { 49 | this.otherProjects.push(result[i]); 50 | } 51 | } 52 | }, (error) => { 53 | console.error(error); 54 | }); 55 | } 56 | 57 | getAssignedTasks() { 58 | this.utility.makeGetRequest("/api/task/getAssignedTo", [this.authManager.getAuthToken()]).then((result: Array) => { 59 | this.assignedTasks = []; 60 | for(var i = 0; i < result.length; i++) { 61 | if(result[i].owner._id != this.authManager.getAuthToken()) { 62 | this.assignedTasks.push(result[i]); 63 | } 64 | } 65 | }, (error) => { 66 | console.error(error); 67 | }); 68 | } 69 | 70 | create(name: string, description: string) { 71 | this.utility.makePostRequest("/api/project/create", [], { 72 | name: name, 73 | description: description, 74 | owner: this.authManager.getAuthToken(), 75 | users: [], 76 | tasks: [] 77 | }).then((result) => { 78 | this.projects.push(result); 79 | }, (error) => { 80 | console.error(error); 81 | }); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /angular/src/app/components/task/task.html: -------------------------------------------------------------------------------- 1 |
2 |

{{project.name}} / {{task.name}}

3 |
4 |

5 | Task Description:{{task.description}} 6 |

7 |

8 | Task Created:{{task.createdON}} 9 |

10 |

11 | permalink 12 |

13 |
14 |
15 |
16 |
17 |
18 | Task History 19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 |
27 | 28 |

29 |
30 |
31 | 32 |
33 |
34 |
35 |
36 |
37 |

{{item.user.name.first}} {{item.user.name.last}} - {{parseDate(item.createdAt)}}

38 |

{{item.log}}

39 |
40 | click for full size 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Assigned To 50 |
51 |
    52 |
  • 53 | 56 |
  • 57 |
58 |
59 |
60 |
61 | Users 62 |
63 |
    64 |
  • {{user.name.first}} {{user.name.last}}
  • 65 |
66 | 74 |
75 |
76 |
77 |
78 | 108 | -------------------------------------------------------------------------------- /angular/src/app/components/task/task.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {ActivatedRoute, Router, ROUTER_DIRECTIVES} from "@angular/router"; 3 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 4 | import {AuthManager} from "../../authmanager"; 5 | import {ITask, IProject, IUser} from "../../interfaces"; 6 | import {Utility} from "../../utility"; 7 | 8 | @Component({ 9 | selector: "task", 10 | viewProviders: [HTTP_PROVIDERS, AuthManager, Utility], 11 | directives: [ROUTER_DIRECTIVES], 12 | templateUrl: "./app/components/task/task.html" 13 | }) 14 | export class TaskPage { 15 | 16 | project: IProject; 17 | task: ITask; 18 | comment: String; 19 | http: Http; 20 | projectId: string; 21 | taskId: string; 22 | taskUser: string; 23 | authManager: AuthManager; 24 | users: Array; 25 | utility: Utility; 26 | userPhoto: File; 27 | 28 | constructor(route: ActivatedRoute, http: Http, router: Router, authManager: AuthManager, utility: Utility) { 29 | this.authManager = authManager; 30 | if (!authManager.isAuthenticated()) { 31 | router.navigate(["/auth"]); 32 | } 33 | this.http = http; 34 | this.utility = utility; 35 | this.users = []; 36 | route.params.subscribe(params => { 37 | this.taskId = params["taskId"]; 38 | }) 39 | this.project = { _id: "", name: "", description: "", owner: {}, users: [], tasks: [], permalink:"" }; 40 | this.task = { _id: "", name: "", description: "", owner: null, assignedTo: {name: {}}, users: [], history: [], permalink :""}; 41 | this.getTask(this.taskId); 42 | this.getUsers(); 43 | } 44 | 45 | getTask(taskId) { 46 | this.utility.makeGetRequest("/api/task/get", [taskId]).then((result: any) => { 47 | this.task = result.task; 48 | this.getProject(result.projectId); 49 | }, (error) => { 50 | console.error(error); 51 | }); 52 | } 53 | 54 | getProject(projectId: string) { 55 | this.utility.makeGetRequest("/api/project/get", [projectId]).then((result) => { 56 | this.project = result; 57 | }, (error) => { 58 | console.log(error); 59 | }); 60 | } 61 | 62 | reply(comment: String) { 63 | if(comment && comment != "") { 64 | this.utility.makePostRequest("/api/task/addHistory", [], {log: comment, userId: this.authManager.getAuthToken(), taskId: this.taskId}).then((result) => { 65 | this.task.history.unshift(result); 66 | }, (error) => { 67 | console.error(error); 68 | }); 69 | } 70 | this.comment = ""; 71 | } 72 | 73 | savePhoto(description:string){ 74 | this.utility.makeFileRequest("/api/cdn/add", [], this.userPhoto, description, this.authManager.getAuthToken(), this.taskId).then((result) => { 75 | this.task.history.unshift(result); 76 | }, (error) => { 77 | console.error(error); 78 | }); 79 | } 80 | 81 | fileEventUpload(photo:any){ 82 | this.userPhoto=photo.target.files[0]; 83 | } 84 | 85 | addUser(taskUser: string) { 86 | if (taskUser && taskUser != "") { 87 | this.utility.makePostRequest("/api/task/addUser", [], {email: taskUser, taskId: this.taskId}).then((result) => { 88 | this.task.users.unshift( result); 89 | }, (error) => { 90 | console.error(error); 91 | }); 92 | this.taskUser = ""; 93 | } 94 | } 95 | 96 | getUsers() { 97 | this.utility.makeGetRequest("/api/user/getAll", []).then((result) => { 98 | this.users = > result; 99 | }, (error) => { 100 | console.error(error); 101 | }); 102 | } 103 | 104 | change(event) { 105 | this.utility.makePostRequest("/api/task/assignUser", [], {userId: event.target.value, taskId: this.taskId}).then((result) => { 106 | console.log( result); 107 | }, (error) => { 108 | console.error(error); 109 | }); 110 | } 111 | 112 | parseDate(date: string) { 113 | var d: Date = new Date(date); 114 | var fullMonth = [ 115 | "January", 116 | "February", 117 | "March", 118 | "April", 119 | "May", 120 | "June", 121 | "July", 122 | "August", 123 | "September", 124 | "October", 125 | "November", 126 | "December" 127 | ]; 128 | return fullMonth[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear() + " @ " + d.toLocaleTimeString(); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /angular/src/app/components/task/taskRO.html: -------------------------------------------------------------------------------- 1 |
2 |

{{project.name}} / {{task.name}}

3 |
4 |

5 | Task Description:{{task.description}} 6 |

7 |

8 | Task Created:{{task.createdON}} 9 |

10 |

11 | permalink 12 |

13 |
14 |
15 |
16 |
17 |
18 | Task History 19 |
20 | 21 |
22 |
23 |
24 |
25 |

{{item.user.name.first}} {{item.user.name.last}} - {{parseDate(item.createdAt)}}

26 |

{{item.log}}

27 |
28 | click for full size 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /angular/src/app/components/task/taskRO.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {ActivatedRoute, Router, ROUTER_DIRECTIVES} from "@angular/router"; 3 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 4 | import {ITask, IProject, IUser} from "../../interfaces"; 5 | import {Utility} from "../../utility"; 6 | 7 | @Component({ 8 | selector: "taskRO", 9 | viewProviders: [HTTP_PROVIDERS, Utility], 10 | directives: [ROUTER_DIRECTIVES], 11 | templateUrl: "./app/components/task/taskRO.html" 12 | }) 13 | export class TaskROPage { 14 | 15 | project: IProject; 16 | task: ITask; 17 | comment: String; 18 | http: Http; 19 | projectId: string; 20 | taskId: string; 21 | taskUser: string; 22 | users: Array; 23 | utility: Utility; 24 | 25 | constructor(route: ActivatedRoute, http: Http, router: Router, utility: Utility) { 26 | this.http = http; 27 | this.utility = utility; 28 | this.users = []; 29 | route.params.subscribe(params => { 30 | this.taskId = params["url"]; 31 | }); 32 | this.project = { _id: "", name: "", description: "", owner: {}, users: [], tasks: [], permalink:"" }; 33 | this.task = { _id: "", name: "", description: "", owner: null, assignedTo: {name: {}}, users: [], history: [], permalink :""}; 34 | this.getTask(this.taskId); 35 | } 36 | 37 | getTask(taskId) { 38 | this.utility.makeGetRequest("/api/task/link", [taskId]).then((result: any) => { 39 | console.log("taskId:",[taskId]); 40 | this.task = result.task; 41 | this.getProject(result.projectId); 42 | }, (error) => { 43 | console.error(error); 44 | }); 45 | } 46 | 47 | getProject(projectId: string) { 48 | this.utility.makeGetRequest("/api/project/get", [projectId]).then((result) => { 49 | this.project = result; 50 | }, (error) => { 51 | console.log(error); 52 | }); 53 | } 54 | parseDate(date: string) { 55 | var d: Date = new Date(date); 56 | var fullMonth = [ 57 | "January", 58 | "February", 59 | "March", 60 | "April", 61 | "May", 62 | "June", 63 | "July", 64 | "August", 65 | "September", 66 | "October", 67 | "November", 68 | "December" 69 | ]; 70 | return fullMonth[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear() + " @ " + d.toLocaleTimeString(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /angular/src/app/components/tasks/tasks.html: -------------------------------------------------------------------------------- 1 |
2 |

{{project.name}}

3 |
4 |

5 | Project Description: {{project.description}} 6 |

7 |

8 | Project Created ON: {{project.createdON}} 9 |

10 |

11 | Project Status: {{project.status}} 12 |

13 |

14 | permalink 15 |

16 |
17 |
18 |
19 |
20 |
21 | Tasks 22 |
23 | 24 |
25 |
26 | 29 |
30 |
31 |
32 |
33 |
34 | Users 35 |
36 |
    37 |
  • {{user.name.first}} {{user.name.last}}
  • 38 |
39 | 47 |
48 |
49 |
50 |
51 | 52 | 91 | -------------------------------------------------------------------------------- /angular/src/app/components/tasks/tasks.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {ActivatedRoute, Router, ROUTER_DIRECTIVES} from "@angular/router"; 4 | import {AuthManager} from "../../authmanager"; 5 | import {ITask, IProject, IUser} from "../../interfaces"; 6 | import {Utility} from "../../utility"; 7 | 8 | @Component({ 9 | selector: "tasks", 10 | viewProviders: [HTTP_PROVIDERS, AuthManager, Utility], 11 | directives: [ROUTER_DIRECTIVES], 12 | templateUrl: "./app/components/tasks/tasks.html" 13 | }) 14 | export class TasksPage { 15 | 16 | http: Http; 17 | users: Array; 18 | project: IProject; 19 | projectId: string; 20 | projectUser: string; 21 | authManager: AuthManager; 22 | utility: Utility; 23 | 24 | constructor(http: Http, route: ActivatedRoute, router: Router, authManager: AuthManager, utility: Utility) { 25 | this.authManager = authManager; 26 | if (!authManager.isAuthenticated()) { 27 | router.navigate(["/auth"]); 28 | } 29 | this.http = http; 30 | this.utility = utility; 31 | route.params.subscribe(params => { 32 | this.projectId = params["projectId"]; 33 | }); 34 | this.project = { _id: "", name: "", description: "", owner: {}, users: [], tasks: null, permalink:"" }; 35 | this.getProject(this.projectId); 36 | this.getUsers(); 37 | } 38 | 39 | getUsers() { 40 | this.utility.makeGetRequest("/api/user/getAll", []).then((result) => { 41 | this.users = > result; 42 | }, (error) => { 43 | console.log(error); 44 | }); 45 | } 46 | 47 | getProject(projectId: string) { 48 | this.utility.makeGetRequest("/api/project/get", [projectId]).then((result) => { 49 | this.project = result; 50 | }, (error) => { 51 | console.log(error); 52 | }); 53 | } 54 | 55 | create(name: string, description: string, assignedTo: string) { 56 | this.utility.makePostRequest("/api/task/create", [this.projectId], { 57 | name: name, 58 | description: description, 59 | owner: this.authManager.getAuthToken(), 60 | assignedTo: assignedTo, 61 | users: [], 62 | history: [] 63 | }).then((result) => { 64 | this.project.tasks.push(result); 65 | }, (error) => { 66 | console.error(error); 67 | }); 68 | } 69 | 70 | addUser(projectUser: string) { 71 | if (projectUser && projectUser != "") { 72 | this.utility.makePostRequest("/api/project/addUser", [], {email: projectUser, projectId: this.project._id}).then((result) => { 73 | this.project.users.unshift(result); 74 | }, (error) => { 75 | console.error(error); 76 | }); 77 | this.projectUser = ""; 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /angular/src/app/components/tasks/tasksRO.html: -------------------------------------------------------------------------------- 1 |
2 |

{{project.name}}

3 |
4 |

5 | Project Description: {{project.description}} 6 |

7 |

8 | Project Created ON: {{project.createdON}} 9 |

10 |

11 | Project Status: {{project.status}} 12 |

13 |

14 | permalink 15 |

16 |
17 | -------------------------------------------------------------------------------- /angular/src/app/components/tasks/tasksRO.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | import {ActivatedRoute, Router, ROUTER_DIRECTIVES} from "@angular/router"; 4 | import {ITask, IProject, IUser} from "../../interfaces"; 5 | import {Utility} from "../../utility"; 6 | 7 | @Component({ 8 | selector: "tasksRO", 9 | viewProviders: [HTTP_PROVIDERS, Utility], 10 | directives: [ROUTER_DIRECTIVES], 11 | templateUrl: "./app/components/tasks/tasksRO.html" 12 | }) 13 | export class TasksROPage { 14 | 15 | http: Http; 16 | project: IProject; 17 | projectId: string; 18 | utility: Utility; 19 | 20 | constructor(http: Http, route: ActivatedRoute, router: Router, utility: Utility) { 21 | this.http = http; 22 | this.utility = utility; 23 | route.params.subscribe(params => { 24 | this.projectId = params["url"]; 25 | }); 26 | this.project = { _id: "", name: "", description: "", owner: {}, users: [], tasks: null, permalink:"" }; 27 | this.getProject(this.projectId); 28 | } 29 | 30 | getProject(projectId: string) { 31 | this.utility.makeGetRequest("/api/project/link", [projectId]).then((result) => { 32 | this.project = result; 33 | }, (error) => { 34 | console.log(error); 35 | }); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /angular/src/app/environment.ts: -------------------------------------------------------------------------------- 1 | // The file for the current environment will overwrite this one during build 2 | // Different environments can be found in config/environment.{dev|prod}.ts 3 | // The build system defaults to the dev environment 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | -------------------------------------------------------------------------------- /angular/src/app/index.ts: -------------------------------------------------------------------------------- 1 | export * from './environment'; 2 | export * from './app.component'; 3 | -------------------------------------------------------------------------------- /angular/src/app/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | _id?: string, 3 | name: { 4 | first: string, 5 | last: string 6 | }, 7 | address: { 8 | street: string, 9 | city: string, 10 | state: string, 11 | zip: string, 12 | country: string 13 | }, 14 | email: string, 15 | phone: string, 16 | password: string, 17 | company: Object 18 | } 19 | 20 | export interface ITask { 21 | _id?: string, 22 | name: string, 23 | description: string, 24 | owner: IUser, 25 | assignedTo: Object, 26 | users: Array, 27 | history: Array, 28 | permalink: string 29 | } 30 | 31 | export interface IProject { 32 | _id?: string, 33 | name: string, 34 | description: string, 35 | permalink:string, 36 | owner: IUser, 37 | users: Array, 38 | tasks: Array 39 | } 40 | 41 | export interface ICompany { 42 | _id?: string, 43 | name: string, 44 | address: { 45 | street: string, 46 | city: string, 47 | state: string, 48 | zip: string, 49 | country: string 50 | } 51 | phone: string, 52 | website: string 53 | } 54 | -------------------------------------------------------------------------------- /angular/src/app/shared/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/app/shared/index.ts -------------------------------------------------------------------------------- /angular/src/app/utility.ts: -------------------------------------------------------------------------------- 1 | import {Injectable, Inject} from "@angular/core"; 2 | import {Http, Request, RequestMethod, Headers, HTTP_PROVIDERS} from "@angular/http"; 3 | 4 | @Injectable() 5 | 6 | export class Utility { 7 | 8 | http: Http; 9 | 10 | constructor(http: Http) { 11 | this.http = http; 12 | } 13 | 14 | makePostRequest(url: string, params: Array, body: Object) { 15 | var fullUrl: string = url; 16 | if(params && params.length > 0) { 17 | fullUrl = fullUrl + "/" + params.join("/"); 18 | } 19 | console.log("HTTP POST REQUEST: ", fullUrl); 20 | return new Promise((resolve, reject) => { 21 | var requestHeaders = new Headers(); 22 | requestHeaders.append("Content-Type", "application/json"); 23 | this.http.request(new Request({ 24 | method: RequestMethod.Post, 25 | url: fullUrl, 26 | body: JSON.stringify(body), 27 | headers: requestHeaders 28 | })) 29 | .subscribe((success) => { 30 | console.log("HTTP POST RESPONSE: ", success.json); 31 | resolve(success.json()); 32 | }, (error) => { 33 | reject(error.json()); 34 | }); 35 | }); 36 | } 37 | 38 | makeFileRequest(url: string, params: Array, file:File, description:string, userId: string, taskId:string) { 39 | 40 | return new Promise((resolve, reject)=> { 41 | var formData:any = new FormData(); 42 | 43 | formData.append('upl', file, file.name); 44 | formData.append('description', description); 45 | formData.append('userId', userId); 46 | formData.append('taskId', taskId); 47 | 48 | var xhr = new XMLHttpRequest(); 49 | 50 | xhr.onreadystatechange = function () { 51 | if (xhr.readyState == 4) { 52 | if (xhr.status == 200) { 53 | resolve(JSON.parse(xhr.response)); // NOT Json by default, it must be parsed. 54 | } else { 55 | reject(xhr.response); 56 | } 57 | } 58 | } 59 | xhr.open('POST', '/api/cdn/add', true); 60 | xhr.send(formData); 61 | }); 62 | } 63 | 64 | makeGetRequest(url: string, params: Array) { 65 | var fullUrl: string = url; 66 | if(params && params.length > 0) { 67 | fullUrl = fullUrl + "/" + params.join("/"); 68 | } 69 | console.log("HTTP GET REQUEST: ", fullUrl); 70 | return new Promise((resolve, reject) => { 71 | this.http.get(fullUrl) 72 | .subscribe((success) => { 73 | console.log("HTTP GET RESPONSE: ", success.json()); 74 | resolve(success.json()); 75 | }, (error) => { 76 | reject(error.json()); 77 | }); 78 | }); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /angular/src/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.5 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /angular/src/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Base structure 3 | */ 4 | 5 | /* Move down content because we have a fixed navbar that is 50px tall */ 6 | body { 7 | padding-top: 50px; 8 | } 9 | 10 | 11 | /* 12 | * Global add-ons 13 | */ 14 | 15 | .sub-header { 16 | padding-bottom: 10px; 17 | border-bottom: 1px solid #eee; 18 | } 19 | 20 | /* 21 | * Top navigation 22 | * Hide default border to remove 1px line. 23 | */ 24 | .navbar-fixed-top { 25 | border: 0; 26 | } 27 | 28 | /* 29 | * Sidebar 30 | */ 31 | 32 | /* Hide for mobile, show later */ 33 | .sidebar { 34 | display: none; 35 | } 36 | @media (min-width: 768px) { 37 | .sidebar { 38 | position: fixed; 39 | top: 51px; 40 | bottom: 0; 41 | left: 0; 42 | z-index: 1000; 43 | display: block; 44 | padding: 20px; 45 | overflow-x: hidden; 46 | overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ 47 | background-color: #f5f5f5; 48 | border-right: 1px solid #eee; 49 | } 50 | } 51 | 52 | /* Sidebar navigation */ 53 | .nav-sidebar { 54 | margin-right: -21px; /* 20px padding + 1px border */ 55 | margin-bottom: 20px; 56 | margin-left: -20px; 57 | } 58 | .nav-sidebar > li > a { 59 | padding-right: 20px; 60 | padding-left: 20px; 61 | } 62 | .nav-sidebar > .active > a, 63 | .nav-sidebar > .active > a:hover, 64 | .nav-sidebar > .active > a:focus { 65 | color: #fff; 66 | background-color: #428bca; 67 | } 68 | 69 | 70 | /* 71 | * Main content 72 | */ 73 | 74 | .main { 75 | padding: 20px; 76 | } 77 | @media (min-width: 768px) { 78 | .main { 79 | padding-right: 40px; 80 | padding-left: 40px; 81 | } 82 | } 83 | .main .page-header { 84 | margin-top: 0; 85 | } 86 | 87 | 88 | /* 89 | * Placeholder dashboard ideas 90 | */ 91 | 92 | .placeholders { 93 | margin-bottom: 30px; 94 | text-align: center; 95 | } 96 | .placeholders h4 { 97 | margin-bottom: 0; 98 | } 99 | .placeholder { 100 | margin-bottom: 20px; 101 | } 102 | .placeholder img { 103 | display: inline-block; 104 | border-radius: 50%; 105 | } 106 | -------------------------------------------------------------------------------- /angular/src/css/ie10-viewport-bug-workaround.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * IE10 viewport hack for Surface/desktop Windows 8 bug 3 | * Copyright 2014-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | /* 8 | * See the Getting Started docs for more information: 9 | * http://getbootstrap.com/getting-started/#support-ie10-width 10 | */ 11 | @-webkit-viewport { width: device-width; } 12 | @-moz-viewport { width: device-width; } 13 | @-ms-viewport { width: device-width; } 14 | @-o-viewport { width: device-width; } 15 | @viewport { width: device-width; } 16 | -------------------------------------------------------------------------------- /angular/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/favicon.ico -------------------------------------------------------------------------------- /angular/src/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /angular/src/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /angular/src/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /angular/src/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/comply-nodejs/73ee99927ed948ecce24dd8dd6adb1689d59a3a7/angular/src/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /angular/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular 6 | 7 | {{#unless environment.production}} 8 | 9 | {{/unless}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Loading... 18 | {{#each scripts.polyfills}} 19 | 20 | {{/each}} 21 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /angular/src/js/holder.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | Holder - client side image placeholders 4 | Version 2.6.0+51ebp 5 | © 2015 Ivan Malopinsky - http://imsky.co 6 | 7 | Site: http://holderjs.com 8 | Issues: https://github.com/imsky/holder/issues 9 | License: http://opensource.org/licenses/MIT 10 | 11 | */ 12 | !function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):"object"==typeof exports?exports.Holder=b():a.Holder=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){(function(b){function d(a,b,c,d){var g=e(c.substr(c.lastIndexOf(a.domain)),a);g&&f({mode:null,el:d,flags:g,engineSettings:b})}function e(a,b){for(var c={theme:y(K.settings.themes.gray,null),stylesheets:b.stylesheets,holderURL:[]},d=!1,e=String.fromCharCode(11),f=a.replace(/([^\\])\//g,"$1"+e).split(e),g=/%[0-9a-f]{2}/gi,h=f.length,i=0;h>i;i++){var j=f[i];if(j.match(g))try{j=decodeURIComponent(j)}catch(k){j=f[i]}var l=!1;if(K.flags.dimensions.match(j))d=!0,c.dimensions=K.flags.dimensions.output(j),l=!0;else if(K.flags.fluid.match(j))d=!0,c.dimensions=K.flags.fluid.output(j),c.fluid=!0,l=!0;else if(K.flags.textmode.match(j))c.textmode=K.flags.textmode.output(j),l=!0;else if(K.flags.colors.match(j)){var m=K.flags.colors.output(j);c.theme=y(c.theme,m),l=!0}else if(b.themes[j])b.themes.hasOwnProperty(j)&&(c.theme=y(b.themes[j],null)),l=!0;else if(K.flags.font.match(j))c.font=K.flags.font.output(j),l=!0;else if(K.flags.auto.match(j))c.auto=!0,l=!0;else if(K.flags.text.match(j))c.text=K.flags.text.output(j),l=!0;else if(K.flags.size.match(j))c.size=K.flags.size.output(j),l=!0;else if(K.flags.random.match(j)){null==K.vars.cache.themeKeys&&(K.vars.cache.themeKeys=Object.keys(b.themes));var n=K.vars.cache.themeKeys[0|Math.random()*K.vars.cache.themeKeys.length];c.theme=y(b.themes[n],null),l=!0}l&&c.holderURL.push(j)}return c.holderURL.unshift(b.domain),c.holderURL=c.holderURL.join("/"),d?c:!1}function f(a){var b=a.mode,c=a.el,d=a.flags,e=a.engineSettings,f=d.dimensions,h=d.theme,i=f.width+"x"+f.height;if(b=null==b?d.fluid?"fluid":"image":b,null!=d.text&&(h.text=d.text,"object"===c.nodeName.toLowerCase())){for(var l=h.text.split("\\n"),m=0;m1){var l=0,m=0,n=a.width*K.setup.lineWrapRatio,o=0;k=new e.Group("line"+o);for(var p=0;p=n||r===!0)&&(b(g,k,l,g.properties.leading),l=0,m+=g.properties.leading,o+=1,k=new e.Group("line"+o),k.y=m),r!==!0&&(j.moveTo(l,0),l+=h.spaceWidth+q.width,k.add(j))}b(g,k,l,g.properties.leading);for(var s in g.children)k=g.children[s],k.moveTo((g.width-k.width)/2,null,null);g.moveTo((a.width-g.width)/2,(a.height-g.height)/2,null),(a.height-g.height)/2<0&&g.moveTo(null,0,null)}else j=new e.Text(a.text),k=new e.Group("line0"),k.add(j),g.add(k),g.moveTo((a.width-h.boundingBox.width)/2,(a.height-h.boundingBox.height)/2,null);return d}function i(a,b,c){var d=parseInt(a,10),e=parseInt(b,10),f=Math.max(d,e),g=Math.min(d,e),h=.8*Math.min(g,f*K.defaults.scale);return Math.round(Math.max(c,h))}function j(a){var b;b=null==a||null==a.nodeType?K.vars.resizableImages:[a];for(var c=0,d=b.length;d>c;c++){var e=b[c];if(e.holderData){var f=e.holderData.flags,h=E(e);if(h){if(!e.holderData.resizeUpdate)continue;if(f.fluid&&f.auto){var i=e.holderData.fluidConfig;switch(i.mode){case"width":h.height=h.width/i.ratio;break;case"height":h.width=h.height*i.ratio}}var j={mode:"image",holderSettings:{dimensions:h,theme:f.theme,flags:f},el:e,engineSettings:e.holderData.engineSettings};"exact"==f.textmode&&(f.exactDimensions=h,j.holderSettings.dimensions=f.dimensions),g(j)}else n(e)}}}function k(a){if(a.holderData){var b=E(a);if(b){var c=a.holderData.flags,d={fluidHeight:"%"==c.dimensions.height.slice(-1),fluidWidth:"%"==c.dimensions.width.slice(-1),mode:null,initialDimensions:b};d.fluidWidth&&!d.fluidHeight?(d.mode="width",d.ratio=d.initialDimensions.width/parseFloat(c.dimensions.height)):!d.fluidWidth&&d.fluidHeight&&(d.mode="height",d.ratio=parseFloat(c.dimensions.width)/d.initialDimensions.height),a.holderData.fluidConfig=d}else n(a)}}function l(){for(var a,c=[],d=Object.keys(K.vars.invisibleImages),e=0,f=d.length;f>e;e++)a=K.vars.invisibleImages[d[e]],E(a)&&"img"==a.nodeName.toLowerCase()&&(c.push(a),delete K.vars.invisibleImages[d[e]]);c.length&&J.run({images:c}),b.requestAnimationFrame(l)}function m(){K.vars.visibilityCheckStarted||(b.requestAnimationFrame(l),K.vars.visibilityCheckStarted=!0)}function n(a){a.holderData.invisibleId||(K.vars.invisibleId+=1,K.vars.invisibleImages["i"+K.vars.invisibleId]=a,a.holderData.invisibleId=K.vars.invisibleId)}function o(a,b){return null==b?document.createElement(a):document.createElementNS(b,a)}function p(a,b){for(var c in b)a.setAttribute(c,b[c])}function q(a,b,c){var d,e;null==a?(a=o("svg",F),d=o("defs",F),e=o("style",F),p(e,{type:"text/css"}),d.appendChild(e),a.appendChild(d)):e=a.querySelector("style"),a.webkitMatchesSelector&&a.setAttribute("xmlns",F);for(var f=0;f=0;h--){var i=g.createProcessingInstruction("xml-stylesheet",'href="'+f[h]+'" rel="stylesheet"');g.insertBefore(i,g.firstChild)}var j=g.createProcessingInstruction("xml",'version="1.0" encoding="UTF-8" standalone="yes"');g.insertBefore(j,g.firstChild),g.removeChild(g.documentElement),e=d.serializeToString(g)}var k=d.serializeToString(a);return k=k.replace(/\&(\#[0-9]{2,}\;)/g,"&$1"),e+k}}function s(){return b.DOMParser?(new DOMParser).parseFromString("","application/xml"):void 0}function t(a){K.vars.debounceTimer||a.call(this),K.vars.debounceTimer&&b.clearTimeout(K.vars.debounceTimer),K.vars.debounceTimer=b.setTimeout(function(){K.vars.debounceTimer=null,a.call(this)},K.setup.debounce)}function u(){t(function(){j(null)})}var v=c(1),w=c(2),x=c(3),y=x.extend,z=x.cssProps,A=x.encodeHtmlEntity,B=x.decodeHtmlEntity,C=x.imageExists,D=x.getNodeArray,E=x.dimensionCheck,F="http://www.w3.org/2000/svg",G=8,H="2.6.0",I="\nCreated with Holder.js "+H+".\nLearn more at http://holderjs.com\n(c) 2012-2015 Ivan Malopinsky - http://imsky.co\n",J={version:H,addTheme:function(a,b){return null!=a&&null!=b&&(K.settings.themes[a]=b),delete K.vars.cache.themeKeys,this},addImage:function(a,b){var c=document.querySelectorAll(b);if(c.length)for(var d=0,e=c.length;e>d;d++){var f=o("img"),g={};g[K.vars.dataAttr]=a,p(f,g),c[d].appendChild(f)}return this},setResizeUpdate:function(a,b){a.holderData&&(a.holderData.resizeUpdate=!!b,a.holderData.resizeUpdate&&j(a))},run:function(a){a=a||{};var c={},g=y(K.settings,a);K.vars.preempted=!0,K.vars.dataAttr=g.dataAttr||K.vars.dataAttr,c.renderer=g.renderer?g.renderer:K.setup.renderer,-1===K.setup.renderers.join(",").indexOf(c.renderer)&&(c.renderer=K.setup.supportsSVG?"svg":K.setup.supportsCanvas?"canvas":"html");var h=D(g.images),i=D(g.bgnodes),j=D(g.stylenodes),k=D(g.objects);c.stylesheets=[],c.svgXMLStylesheet=!0,c.noFontFallback=g.noFontFallback?g.noFontFallback:!1;for(var l=0;l1){c.nodeValue="";for(var u=0;u=0?b:1)}function f(a){v?e(a):w.push(a)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function y(){document.removeEventListener("DOMContentLoaded",y,!1),document.readyState="complete"},!1),document.readyState="loading");var g=a.document,h=g.documentElement,i="load",j=!1,k="on"+i,l="complete",m="readyState",n="attachEvent",o="detachEvent",p="addEventListener",q="DOMContentLoaded",r="onreadystatechange",s="removeEventListener",t=p in g,u=j,v=j,w=[];if(g[m]===l)e(b);else if(t)g[p](q,c,j),a[p](i,c,j);else{g[n](r,c),a[n](k,c);try{u=null==a.frameElement&&h}catch(x){}u&&u.doScroll&&!function z(){if(!v){try{u.doScroll("left")}catch(a){return e(z,50)}d(),b()}}()}return f.version="1.4.0",f.isReady=function(){return v},f}a.exports="undefined"!=typeof window&&b(window)},function(a,b,c){var d=c(4),e=function(a){function b(a,b){for(var c in b)a[c]=b[c];return a}var c=1,e=d.defclass({constructor:function(a){c++,this.parent=null,this.children={},this.id=c,this.name="n"+c,null!=a&&(this.name=a),this.x=0,this.y=0,this.z=0,this.width=0,this.height=0},resize:function(a,b){null!=a&&(this.width=a),null!=b&&(this.height=b)},moveTo:function(a,b,c){this.x=null!=a?a:this.x,this.y=null!=b?b:this.y,this.z=null!=c?c:this.z},add:function(a){var b=a.name;if(null!=this.children[b])throw"SceneGraph: child with that name already exists: "+b;this.children[b]=a,a.parent=this}}),f=d(e,function(b){this.constructor=function(){b.constructor.call(this,"root"),this.properties=a}}),g=d(e,function(a){function c(c,d){if(a.constructor.call(this,c),this.properties={fill:"#000"},null!=d)b(this.properties,d);else if(null!=c&&"string"!=typeof c)throw"SceneGraph: invalid node name"}this.Group=d.extend(this,{constructor:c,type:"group"}),this.Rect=d.extend(this,{constructor:c,type:"rect"}),this.Text=d.extend(this,{constructor:function(a){c.call(this),this.properties.text=a},type:"text"})}),h=new f;return this.Shape=g,this.root=h,this};a.exports=e},function(a,b){(function(a){b.extend=function(a,b){var c={};for(var d in a)a.hasOwnProperty(d)&&(c[d]=a[d]);if(null!=b)for(var e in b)b.hasOwnProperty(e)&&(c[e]=b[e]);return c},b.cssProps=function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(c+":"+a[c]);return b.join(";")},b.encodeHtmlEntity=function(a){for(var b=[],c=0,d=a.length-1;d>=0;d--)c=a.charCodeAt(d),b.unshift(c>128?["&#",c,";"].join(""):a[d]);return b.join("")},b.getNodeArray=function(b){var c=null;return"string"==typeof b?c=document.querySelectorAll(b):a.NodeList&&b instanceof a.NodeList?c=b:a.Node&&b instanceof a.Node?c=[b]:a.HTMLCollection&&b instanceof a.HTMLCollection?c=b:b instanceof Array?c=b:null===b&&(c=[]),c},b.imageExists=function(a,b){var c=new Image;c.onerror=function(){b.call(this,!1)},c.onload=function(){b.call(this,!0)},c.src=a},b.decodeHtmlEntity=function(a){return a.replace(/&#(\d+);/g,function(a,b){return String.fromCharCode(b)})},b.dimensionCheck=function(a){var b={height:a.clientHeight,width:a.clientWidth};return b.height&&b.width?b:!1}}).call(b,function(){return this}())},function(a){var b=function(){},c=Array.prototype.slice,d=function(a,d){var e=b.prototype="function"==typeof a?a.prototype:a,f=new b,g=d.apply(f,c.call(arguments,2).concat(e));if("object"==typeof g)for(var h in g)f[h]=g[h];if(!f.hasOwnProperty("constructor"))return f;var i=f.constructor;return i.prototype=f,i};d.defclass=function(a){var b=a.constructor;return b.prototype=a,b},d.extend=function(a,b){return d(a,function(a){return this.uber=a,b})},a.exports=d}])}); -------------------------------------------------------------------------------- /angular/src/js/ie-emulation-modes-warning.js: -------------------------------------------------------------------------------- 1 | // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT 2 | // IT'S JUST JUNK FOR OUR DOCS! 3 | // ++++++++++++++++++++++++++++++++++++++++++ 4 | /*! 5 | * Copyright 2014-2015 Twitter, Inc. 6 | * 7 | * Licensed under the Creative Commons Attribution 3.0 Unported License. For 8 | * details, see https://creativecommons.org/licenses/by/3.0/. 9 | */ 10 | // Intended to prevent false-positive bug reports about Bootstrap not working properly in old versions of IE due to folks testing using IE's unreliable emulation modes. 11 | (function () { 12 | 'use strict'; 13 | 14 | function emulatedIEMajorVersion() { 15 | var groups = /MSIE ([0-9.]+)/.exec(window.navigator.userAgent) 16 | if (groups === null) { 17 | return null 18 | } 19 | var ieVersionNum = parseInt(groups[1], 10) 20 | var ieMajorVersion = Math.floor(ieVersionNum) 21 | return ieMajorVersion 22 | } 23 | 24 | function actualNonEmulatedIEMajorVersion() { 25 | // Detects the actual version of IE in use, even if it's in an older-IE emulation mode. 26 | // IE JavaScript conditional compilation docs: https://msdn.microsoft.com/library/121hztk3%28v=vs.94%29.aspx 27 | // @cc_on docs: https://msdn.microsoft.com/library/8ka90k2e%28v=vs.94%29.aspx 28 | var jscriptVersion = new Function('/*@cc_on return @_jscript_version; @*/')() // jshint ignore:line 29 | if (jscriptVersion === undefined) { 30 | return 11 // IE11+ not in emulation mode 31 | } 32 | if (jscriptVersion < 9) { 33 | return 8 // IE8 (or lower; haven't tested on IE<8) 34 | } 35 | return jscriptVersion // IE9 or IE10 in any mode, or IE11 in non-IE11 mode 36 | } 37 | 38 | var ua = window.navigator.userAgent 39 | if (ua.indexOf('Opera') > -1 || ua.indexOf('Presto') > -1) { 40 | return // Opera, which might pretend to be IE 41 | } 42 | var emulated = emulatedIEMajorVersion() 43 | if (emulated === null) { 44 | return // Not IE 45 | } 46 | var nonEmulated = actualNonEmulatedIEMajorVersion() 47 | 48 | if (emulated !== nonEmulated) { 49 | window.alert('WARNING: You appear to be using IE' + nonEmulated + ' in IE' + emulated + ' emulation mode.\nIE emulation modes can behave significantly differently from ACTUAL older versions of IE.\nPLEASE DON\'T FILE BOOTSTRAP BUGS based on testing in IE emulation modes!') 50 | } 51 | })(); 52 | -------------------------------------------------------------------------------- /angular/src/js/ie10-viewport-bug-workaround.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * IE10 viewport hack for Surface/desktop Windows 8 bug 3 | * Copyright 2014-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | // See the Getting Started docs for more information: 8 | // http://getbootstrap.com/getting-started/#support-ie10-width 9 | 10 | (function () { 11 | 'use strict'; 12 | 13 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) { 14 | var msViewportStyle = document.createElement('style') 15 | msViewportStyle.appendChild( 16 | document.createTextNode( 17 | '@-ms-viewport{width:auto!important}' 18 | ) 19 | ) 20 | document.querySelector('head').appendChild(msViewportStyle) 21 | } 22 | 23 | })(); 24 | -------------------------------------------------------------------------------- /angular/src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrap } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { RouterConfig, provideRouter } from "@angular/router"; 4 | import { HTTP_PROVIDERS } from "@angular/http"; 5 | import { AppComponent, environment } from './app/'; 6 | import { AuthManager } from "./app/authmanager"; 7 | import { Utility } from "./app/utility"; 8 | 9 | import { AuthPage } from "./app/components/auth/auth"; 10 | import { CompaniesPage } from "./app/components/companies/companies"; 11 | import { ProjectsPage } from "./app/components/projects/projects"; 12 | import { TaskPage } from "./app/components/task/task"; 13 | import { TasksPage } from "./app/components/tasks/tasks"; 14 | import { TasksROPage } from "./app/components/tasks/tasksRO"; 15 | import { TaskROPage } from "./app/components/task/taskRO"; 16 | 17 | if (environment.production) { 18 | enableProdMode(); 19 | } 20 | 21 | export const AppRoutes: RouterConfig = [ 22 | { path: "auth", component: AuthPage }, 23 | { path: "companies", component: CompaniesPage }, 24 | { path: "", component: ProjectsPage }, 25 | { path: "task/:taskId", component: TaskPage }, 26 | { path: "tasks/:projectId", component: TasksPage }, 27 | { path: "p/:url", component: TasksROPage }, 28 | { path: "t/:url", component: TaskROPage } 29 | ]; 30 | 31 | bootstrap(AppComponent, [AuthManager, Utility, [provideRouter(AppRoutes)], HTTP_PROVIDERS]); 32 | -------------------------------------------------------------------------------- /angular/src/system-config.ts: -------------------------------------------------------------------------------- 1 | // SystemJS configuration file, see links for more information 2 | // https://github.com/systemjs/systemjs 3 | // https://github.com/systemjs/systemjs/blob/master/docs/config-api.md 4 | 5 | /*********************************************************************************************** 6 | * User Configuration. 7 | **********************************************************************************************/ 8 | /** Map relative paths to URLs. */ 9 | const map: any = { 10 | }; 11 | 12 | /** User packages configuration. */ 13 | const packages: any = { 14 | }; 15 | 16 | //////////////////////////////////////////////////////////////////////////////////////////////// 17 | /*********************************************************************************************** 18 | * Everything underneath this line is managed by the CLI. 19 | **********************************************************************************************/ 20 | const barrels: string[] = [ 21 | // Angular specific barrels. 22 | '@angular/core', 23 | '@angular/common', 24 | '@angular/compiler', 25 | '@angular/forms', 26 | '@angular/http', 27 | '@angular/router', 28 | '@angular/platform-browser', 29 | '@angular/platform-browser-dynamic', 30 | 31 | // Thirdparty barrels. 32 | 'rxjs', 33 | 34 | // App specific barrels. 35 | 'app', 36 | 'app/shared', 37 | /** @cli-barrel */ 38 | ]; 39 | 40 | const cliSystemConfigPackages: any = {}; 41 | barrels.forEach((barrelName: string) => { 42 | cliSystemConfigPackages[barrelName] = { main: 'index' }; 43 | }); 44 | 45 | /** Type declaration for ambient System. */ 46 | declare var System: any; 47 | 48 | // Apply the CLI SystemJS configuration. 49 | System.config({ 50 | map: { 51 | '@angular': 'vendor/@angular', 52 | 'rxjs': 'vendor/rxjs', 53 | 'main': 'main.js' 54 | }, 55 | packages: cliSystemConfigPackages 56 | }); 57 | 58 | // Apply the user's configuration. 59 | System.config({ map, packages }); 60 | -------------------------------------------------------------------------------- /angular/src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "mapRoot": "/", 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "noEmitOnError": true, 11 | "noImplicitAny": false, 12 | "outDir": "../dist/", 13 | "rootDir": ".", 14 | "sourceMap": true, 15 | "target": "es5", 16 | "inlineSources": true 17 | }, 18 | "filesGlob": [ 19 | "./**/*.ts" 20 | ], 21 | "files": [ 22 | "./app/app.component.spec.ts", 23 | "./app/app.component.ts", 24 | "./app/authmanager.ts", 25 | "./app/components/auth/auth.ts", 26 | "./app/components/companies/companies.ts", 27 | "./app/components/projects/projects.ts", 28 | "./app/components/task/task.ts", 29 | "./app/components/task/taskRO.ts", 30 | "./app/components/tasks/tasks.ts", 31 | "./app/components/tasks/tasksRO.ts", 32 | "./app/environment.ts", 33 | "./app/index.ts", 34 | "./app/interfaces.ts", 35 | "./app/shared/index.ts", 36 | "./app/utility.ts", 37 | "./main.ts", 38 | "./system-config.ts", 39 | "./typings.d.ts" 40 | ], 41 | "atom": { 42 | "rewriteTsconfig": true 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /angular/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | // Typings reference file, see links for more information 2 | // https://github.com/typings/typings 3 | // https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html 4 | 5 | /// 6 | declare var module: { id: string }; 7 | -------------------------------------------------------------------------------- /angular/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "class-name": true, 7 | "comment-format": [ 8 | true, 9 | "check-space" 10 | ], 11 | "curly": true, 12 | "eofline": true, 13 | "forin": true, 14 | "indent": [ 15 | true, 16 | "spaces" 17 | ], 18 | "label-position": true, 19 | "label-undefined": true, 20 | "max-line-length": [ 21 | true, 22 | 140 23 | ], 24 | "member-access": false, 25 | "member-ordering": [ 26 | true, 27 | "static-before-instance", 28 | "variables-before-functions" 29 | ], 30 | "no-arg": true, 31 | "no-bitwise": true, 32 | "no-console": [ 33 | true, 34 | "debug", 35 | "info", 36 | "time", 37 | "timeEnd", 38 | "trace" 39 | ], 40 | "no-construct": true, 41 | "no-debugger": true, 42 | "no-duplicate-key": true, 43 | "no-duplicate-variable": true, 44 | "no-empty": false, 45 | "no-eval": true, 46 | "no-inferrable-types": true, 47 | "no-shadowed-variable": true, 48 | "no-string-literal": false, 49 | "no-switch-case-fall-through": true, 50 | "no-trailing-whitespace": true, 51 | "no-unused-expression": true, 52 | "no-unused-variable": true, 53 | "no-unreachable": true, 54 | "no-use-before-declare": true, 55 | "no-var-keyword": true, 56 | "object-literal-sort-keys": false, 57 | "one-line": [ 58 | true, 59 | "check-open-brace", 60 | "check-catch", 61 | "check-else", 62 | "check-whitespace" 63 | ], 64 | "quotemark": [ 65 | true, 66 | "single" 67 | ], 68 | "radix": true, 69 | "semicolon": [ 70 | "always" 71 | ], 72 | "triple-equals": [ 73 | true, 74 | "allow-null-check" 75 | ], 76 | "typedef-whitespace": [ 77 | true, 78 | { 79 | "call-signature": "nospace", 80 | "index-signature": "nospace", 81 | "parameter": "nospace", 82 | "property-declaration": "nospace", 83 | "variable-declaration": "nospace" 84 | } 85 | ], 86 | "variable-name": false, 87 | "whitespace": [ 88 | true, 89 | "check-branch", 90 | "check-decl", 91 | "check-operator", 92 | "check-separator", 93 | "check-type" 94 | ], 95 | 96 | "directive-selector-name": [true, "camelCase"], 97 | "component-selector-name": [true, "kebab-case"], 98 | "directive-selector-type": [true, "attribute"], 99 | "component-selector-type": [true, "element"], 100 | "use-input-property-decorator": true, 101 | "use-output-property-decorator": true, 102 | "use-host-property-decorator": true, 103 | "no-input-rename": true, 104 | "no-output-rename": true, 105 | "use-life-cycle-interface": true, 106 | "use-pipe-transform-interface": true, 107 | "component-class-suffix": true, 108 | "directive-class-suffix": true 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /angular/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ambientDevDependencies": { 3 | "angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160412134438", 5 | "selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654" 6 | }, 7 | "ambientDependencies": { 8 | "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /angular/typings/browser.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | -------------------------------------------------------------------------------- /angular/typings/browser/ambient/jasmine/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5c182b9af717f73146399c2485f70f1e2ac0ff2b/jasmine/jasmine.d.ts 3 | // Type definitions for Jasmine 2.2 4 | // Project: http://jasmine.github.io/ 5 | // Definitions by: Boris Yankov , Theodore Brown , David Pärsson 6 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 7 | 8 | 9 | // For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts 10 | 11 | declare function describe(description: string, specDefinitions: () => void): void; 12 | declare function fdescribe(description: string, specDefinitions: () => void): void; 13 | declare function xdescribe(description: string, specDefinitions: () => void): void; 14 | 15 | declare function it(expectation: string, assertion?: () => void, timeout?: number): void; 16 | declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 17 | declare function fit(expectation: string, assertion?: () => void, timeout?: number): void; 18 | declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 19 | declare function xit(expectation: string, assertion?: () => void, timeout?: number): void; 20 | declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 21 | 22 | /** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */ 23 | declare function pending(reason?: string): void; 24 | 25 | declare function beforeEach(action: () => void, timeout?: number): void; 26 | declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void; 27 | declare function afterEach(action: () => void, timeout?: number): void; 28 | declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void; 29 | 30 | declare function beforeAll(action: () => void, timeout?: number): void; 31 | declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; 32 | declare function afterAll(action: () => void, timeout?: number): void; 33 | declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void; 34 | 35 | declare function expect(spy: Function): jasmine.Matchers; 36 | declare function expect(actual: any): jasmine.Matchers; 37 | 38 | declare function fail(e?: any): void; 39 | /** Action method that should be called when the async work is complete */ 40 | interface DoneFn extends Function { 41 | (): void; 42 | 43 | /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */ 44 | fail: (message?: Error|string) => void; 45 | } 46 | 47 | declare function spyOn(object: any, method: string): jasmine.Spy; 48 | 49 | declare function runs(asyncMethod: Function): void; 50 | declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void; 51 | declare function waits(timeout?: number): void; 52 | 53 | declare namespace jasmine { 54 | 55 | var clock: () => Clock; 56 | 57 | function any(aclass: any): Any; 58 | function anything(): Any; 59 | function arrayContaining(sample: any[]): ArrayContaining; 60 | function objectContaining(sample: any): ObjectContaining; 61 | function createSpy(name: string, originalFn?: Function): Spy; 62 | function createSpyObj(baseName: string, methodNames: any[]): any; 63 | function createSpyObj(baseName: string, methodNames: any[]): T; 64 | function pp(value: any): string; 65 | function getEnv(): Env; 66 | function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; 67 | function addMatchers(matchers: CustomMatcherFactories): void; 68 | function stringMatching(str: string): Any; 69 | function stringMatching(str: RegExp): Any; 70 | 71 | interface Any { 72 | 73 | new (expectedClass: any): any; 74 | 75 | jasmineMatches(other: any): boolean; 76 | jasmineToString(): string; 77 | } 78 | 79 | // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains() 80 | interface ArrayLike { 81 | length: number; 82 | [n: number]: T; 83 | } 84 | 85 | interface ArrayContaining { 86 | new (sample: any[]): any; 87 | 88 | asymmetricMatch(other: any): boolean; 89 | jasmineToString(): string; 90 | } 91 | 92 | interface ObjectContaining { 93 | new (sample: any): any; 94 | 95 | jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; 96 | jasmineToString(): string; 97 | } 98 | 99 | interface Block { 100 | 101 | new (env: Env, func: SpecFunction, spec: Spec): any; 102 | 103 | execute(onComplete: () => void): void; 104 | } 105 | 106 | interface WaitsBlock extends Block { 107 | new (env: Env, timeout: number, spec: Spec): any; 108 | } 109 | 110 | interface WaitsForBlock extends Block { 111 | new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any; 112 | } 113 | 114 | interface Clock { 115 | install(): void; 116 | uninstall(): void; 117 | /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */ 118 | tick(ms: number): void; 119 | mockDate(date?: Date): void; 120 | } 121 | 122 | interface CustomEqualityTester { 123 | (first: any, second: any): boolean; 124 | } 125 | 126 | interface CustomMatcher { 127 | compare(actual: T, expected: T): CustomMatcherResult; 128 | compare(actual: any, expected: any): CustomMatcherResult; 129 | } 130 | 131 | interface CustomMatcherFactory { 132 | (util: MatchersUtil, customEqualityTesters: Array): CustomMatcher; 133 | } 134 | 135 | interface CustomMatcherFactories { 136 | [index: string]: CustomMatcherFactory; 137 | } 138 | 139 | interface CustomMatcherResult { 140 | pass: boolean; 141 | message?: string; 142 | } 143 | 144 | interface MatchersUtil { 145 | equals(a: any, b: any, customTesters?: Array): boolean; 146 | contains(haystack: ArrayLike | string, needle: any, customTesters?: Array): boolean; 147 | buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: Array): string; 148 | } 149 | 150 | interface Env { 151 | setTimeout: any; 152 | clearTimeout: void; 153 | setInterval: any; 154 | clearInterval: void; 155 | updateInterval: number; 156 | 157 | currentSpec: Spec; 158 | 159 | matchersClass: Matchers; 160 | 161 | version(): any; 162 | versionString(): string; 163 | nextSpecId(): number; 164 | addReporter(reporter: Reporter): void; 165 | execute(): void; 166 | describe(description: string, specDefinitions: () => void): Suite; 167 | // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these 168 | beforeEach(beforeEachFunction: () => void): void; 169 | beforeAll(beforeAllFunction: () => void): void; 170 | currentRunner(): Runner; 171 | afterEach(afterEachFunction: () => void): void; 172 | afterAll(afterAllFunction: () => void): void; 173 | xdescribe(desc: string, specDefinitions: () => void): XSuite; 174 | it(description: string, func: () => void): Spec; 175 | // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these 176 | xit(desc: string, func: () => void): XSpec; 177 | compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean; 178 | compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; 179 | equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; 180 | contains_(haystack: any, needle: any): boolean; 181 | addCustomEqualityTester(equalityTester: CustomEqualityTester): void; 182 | addMatchers(matchers: CustomMatcherFactories): void; 183 | specFilter(spec: Spec): boolean; 184 | } 185 | 186 | interface FakeTimer { 187 | 188 | new (): any; 189 | 190 | reset(): void; 191 | tick(millis: number): void; 192 | runFunctionsWithinRange(oldMillis: number, nowMillis: number): void; 193 | scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void; 194 | } 195 | 196 | interface HtmlReporter { 197 | new (): any; 198 | } 199 | 200 | interface HtmlSpecFilter { 201 | new (): any; 202 | } 203 | 204 | interface Result { 205 | type: string; 206 | } 207 | 208 | interface NestedResults extends Result { 209 | description: string; 210 | 211 | totalCount: number; 212 | passedCount: number; 213 | failedCount: number; 214 | 215 | skipped: boolean; 216 | 217 | rollupCounts(result: NestedResults): void; 218 | log(values: any): void; 219 | getItems(): Result[]; 220 | addResult(result: Result): void; 221 | passed(): boolean; 222 | } 223 | 224 | interface MessageResult extends Result { 225 | values: any; 226 | trace: Trace; 227 | } 228 | 229 | interface ExpectationResult extends Result { 230 | matcherName: string; 231 | passed(): boolean; 232 | expected: any; 233 | actual: any; 234 | message: string; 235 | trace: Trace; 236 | } 237 | 238 | interface Trace { 239 | name: string; 240 | message: string; 241 | stack: any; 242 | } 243 | 244 | interface PrettyPrinter { 245 | 246 | new (): any; 247 | 248 | format(value: any): void; 249 | iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void; 250 | emitScalar(value: any): void; 251 | emitString(value: string): void; 252 | emitArray(array: any[]): void; 253 | emitObject(obj: any): void; 254 | append(value: any): void; 255 | } 256 | 257 | interface StringPrettyPrinter extends PrettyPrinter { 258 | } 259 | 260 | interface Queue { 261 | 262 | new (env: any): any; 263 | 264 | env: Env; 265 | ensured: boolean[]; 266 | blocks: Block[]; 267 | running: boolean; 268 | index: number; 269 | offset: number; 270 | abort: boolean; 271 | 272 | addBefore(block: Block, ensure?: boolean): void; 273 | add(block: any, ensure?: boolean): void; 274 | insertNext(block: any, ensure?: boolean): void; 275 | start(onComplete?: () => void): void; 276 | isRunning(): boolean; 277 | next_(): void; 278 | results(): NestedResults; 279 | } 280 | 281 | interface Matchers { 282 | 283 | new (env: Env, actual: any, spec: Env, isNot?: boolean): any; 284 | 285 | env: Env; 286 | actual: any; 287 | spec: Env; 288 | isNot?: boolean; 289 | message(): any; 290 | 291 | toBe(expected: any, expectationFailOutput?: any): boolean; 292 | toEqual(expected: any, expectationFailOutput?: any): boolean; 293 | toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean; 294 | toBeDefined(expectationFailOutput?: any): boolean; 295 | toBeUndefined(expectationFailOutput?: any): boolean; 296 | toBeNull(expectationFailOutput?: any): boolean; 297 | toBeNaN(): boolean; 298 | toBeTruthy(expectationFailOutput?: any): boolean; 299 | toBeFalsy(expectationFailOutput?: any): boolean; 300 | toHaveBeenCalled(): boolean; 301 | toHaveBeenCalledWith(...params: any[]): boolean; 302 | toHaveBeenCalledTimes(expected: number): boolean; 303 | toContain(expected: any, expectationFailOutput?: any): boolean; 304 | toBeLessThan(expected: number, expectationFailOutput?: any): boolean; 305 | toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean; 306 | toBeCloseTo(expected: number, precision: any, expectationFailOutput?: any): boolean; 307 | toThrow(expected?: any): boolean; 308 | toThrowError(message?: string | RegExp): boolean; 309 | toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean; 310 | not: Matchers; 311 | 312 | Any: Any; 313 | } 314 | 315 | interface Reporter { 316 | reportRunnerStarting(runner: Runner): void; 317 | reportRunnerResults(runner: Runner): void; 318 | reportSuiteResults(suite: Suite): void; 319 | reportSpecStarting(spec: Spec): void; 320 | reportSpecResults(spec: Spec): void; 321 | log(str: string): void; 322 | } 323 | 324 | interface MultiReporter extends Reporter { 325 | addReporter(reporter: Reporter): void; 326 | } 327 | 328 | interface Runner { 329 | 330 | new (env: Env): any; 331 | 332 | execute(): void; 333 | beforeEach(beforeEachFunction: SpecFunction): void; 334 | afterEach(afterEachFunction: SpecFunction): void; 335 | beforeAll(beforeAllFunction: SpecFunction): void; 336 | afterAll(afterAllFunction: SpecFunction): void; 337 | finishCallback(): void; 338 | addSuite(suite: Suite): void; 339 | add(block: Block): void; 340 | specs(): Spec[]; 341 | suites(): Suite[]; 342 | topLevelSuites(): Suite[]; 343 | results(): NestedResults; 344 | } 345 | 346 | interface SpecFunction { 347 | (spec?: Spec): void; 348 | } 349 | 350 | interface SuiteOrSpec { 351 | id: number; 352 | env: Env; 353 | description: string; 354 | queue: Queue; 355 | } 356 | 357 | interface Spec extends SuiteOrSpec { 358 | 359 | new (env: Env, suite: Suite, description: string): any; 360 | 361 | suite: Suite; 362 | 363 | afterCallbacks: SpecFunction[]; 364 | spies_: Spy[]; 365 | 366 | results_: NestedResults; 367 | matchersClass: Matchers; 368 | 369 | getFullName(): string; 370 | results(): NestedResults; 371 | log(arguments: any): any; 372 | runs(func: SpecFunction): Spec; 373 | addToQueue(block: Block): void; 374 | addMatcherResult(result: Result): void; 375 | expect(actual: any): any; 376 | waits(timeout: number): Spec; 377 | waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec; 378 | fail(e?: any): void; 379 | getMatchersClass_(): Matchers; 380 | addMatchers(matchersPrototype: CustomMatcherFactories): void; 381 | finishCallback(): void; 382 | finish(onComplete?: () => void): void; 383 | after(doAfter: SpecFunction): void; 384 | execute(onComplete?: () => void): any; 385 | addBeforesAndAftersToQueue(): void; 386 | explodes(): void; 387 | spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy; 388 | removeAllSpies(): void; 389 | } 390 | 391 | interface XSpec { 392 | id: number; 393 | runs(): void; 394 | } 395 | 396 | interface Suite extends SuiteOrSpec { 397 | 398 | new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any; 399 | 400 | parentSuite: Suite; 401 | 402 | getFullName(): string; 403 | finish(onComplete?: () => void): void; 404 | beforeEach(beforeEachFunction: SpecFunction): void; 405 | afterEach(afterEachFunction: SpecFunction): void; 406 | beforeAll(beforeAllFunction: SpecFunction): void; 407 | afterAll(afterAllFunction: SpecFunction): void; 408 | results(): NestedResults; 409 | add(suiteOrSpec: SuiteOrSpec): void; 410 | specs(): Spec[]; 411 | suites(): Suite[]; 412 | children(): any[]; 413 | execute(onComplete?: () => void): void; 414 | } 415 | 416 | interface XSuite { 417 | execute(): void; 418 | } 419 | 420 | interface Spy { 421 | (...params: any[]): any; 422 | 423 | identity: string; 424 | and: SpyAnd; 425 | calls: Calls; 426 | mostRecentCall: { args: any[]; }; 427 | argsForCall: any[]; 428 | wasCalled: boolean; 429 | } 430 | 431 | interface SpyAnd { 432 | /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */ 433 | callThrough(): Spy; 434 | /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */ 435 | returnValue(val: any): Spy; 436 | /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */ 437 | callFake(fn: Function): Spy; 438 | /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */ 439 | throwError(msg: string): Spy; 440 | /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */ 441 | stub(): Spy; 442 | } 443 | 444 | interface Calls { 445 | /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. **/ 446 | any(): boolean; 447 | /** By chaining the spy with calls.count(), will return the number of times the spy was called **/ 448 | count(): number; 449 | /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index **/ 450 | argsFor(index: number): any[]; 451 | /** By chaining the spy with calls.allArgs(), will return the arguments to all calls **/ 452 | allArgs(): any[]; 453 | /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls **/ 454 | all(): CallInfo[]; 455 | /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call **/ 456 | mostRecent(): CallInfo; 457 | /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call **/ 458 | first(): CallInfo; 459 | /** By chaining the spy with calls.reset(), will clears all tracking for a spy **/ 460 | reset(): void; 461 | } 462 | 463 | interface CallInfo { 464 | /** The context (the this) for the call */ 465 | object: any; 466 | /** All arguments passed to the call */ 467 | args: any[]; 468 | /** The return value of the call */ 469 | returnValue: any; 470 | } 471 | 472 | interface Util { 473 | inherit(childClass: Function, parentClass: Function): any; 474 | formatException(e: any): any; 475 | htmlEscape(str: string): string; 476 | argsToArray(args: any): any; 477 | extend(destination: any, source: any): any; 478 | } 479 | 480 | interface JsApiReporter extends Reporter { 481 | 482 | started: boolean; 483 | finished: boolean; 484 | result: any; 485 | messages: any; 486 | 487 | new (): any; 488 | 489 | suites(): Suite[]; 490 | summarize_(suiteOrSpec: SuiteOrSpec): any; 491 | results(): any; 492 | resultsForSpec(specId: any): any; 493 | log(str: any): any; 494 | resultsForSpecs(specIds: any): any; 495 | summarizeResult_(result: any): any; 496 | } 497 | 498 | interface Jasmine { 499 | Spec: Spec; 500 | clock: Clock; 501 | util: Util; 502 | } 503 | 504 | export var HtmlReporter: HtmlReporter; 505 | export var HtmlSpecFilter: HtmlSpecFilter; 506 | export var DEFAULT_TIMEOUT_INTERVAL: number; 507 | } -------------------------------------------------------------------------------- /angular/typings/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | /// 5 | -------------------------------------------------------------------------------- /angular/typings/main/ambient/es6-shim/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/7de6c3dd94feaeb21f20054b9f30d5dabc5efabd/es6-shim/es6-shim.d.ts 3 | // Type definitions for es6-shim v0.31.2 4 | // Project: https://github.com/paulmillr/es6-shim 5 | // Definitions by: Ron Buckton 6 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 7 | 8 | declare type PropertyKey = string | number | symbol; 9 | 10 | interface IteratorResult { 11 | done: boolean; 12 | value?: T; 13 | } 14 | 15 | interface IterableShim { 16 | /** 17 | * Shim for an ES6 iterable. Not intended for direct use by user code. 18 | */ 19 | "_es6-shim iterator_"(): Iterator; 20 | } 21 | 22 | interface Iterator { 23 | next(value?: any): IteratorResult; 24 | return?(value?: any): IteratorResult; 25 | throw?(e?: any): IteratorResult; 26 | } 27 | 28 | interface IterableIteratorShim extends IterableShim, Iterator { 29 | /** 30 | * Shim for an ES6 iterable iterator. Not intended for direct use by user code. 31 | */ 32 | "_es6-shim iterator_"(): IterableIteratorShim; 33 | } 34 | 35 | interface StringConstructor { 36 | /** 37 | * Return the String value whose elements are, in order, the elements in the List elements. 38 | * If length is 0, the empty string is returned. 39 | */ 40 | fromCodePoint(...codePoints: number[]): string; 41 | 42 | /** 43 | * String.raw is intended for use as a tag function of a Tagged Template String. When called 44 | * as such the first argument will be a well formed template call site object and the rest 45 | * parameter will contain the substitution values. 46 | * @param template A well-formed template string call site representation. 47 | * @param substitutions A set of substitution values. 48 | */ 49 | raw(template: TemplateStringsArray, ...substitutions: any[]): string; 50 | } 51 | 52 | interface String { 53 | /** 54 | * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point 55 | * value of the UTF-16 encoded code point starting at the string element at position pos in 56 | * the String resulting from converting this object to a String. 57 | * If there is no element at that position, the result is undefined. 58 | * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos. 59 | */ 60 | codePointAt(pos: number): number; 61 | 62 | /** 63 | * Returns true if searchString appears as a substring of the result of converting this 64 | * object to a String, at one or more positions that are 65 | * greater than or equal to position; otherwise, returns false. 66 | * @param searchString search string 67 | * @param position If position is undefined, 0 is assumed, so as to search all of the String. 68 | */ 69 | includes(searchString: string, position?: number): boolean; 70 | 71 | /** 72 | * Returns true if the sequence of elements of searchString converted to a String is the 73 | * same as the corresponding elements of this object (converted to a String) starting at 74 | * endPosition – length(this). Otherwise returns false. 75 | */ 76 | endsWith(searchString: string, endPosition?: number): boolean; 77 | 78 | /** 79 | * Returns a String value that is made from count copies appended together. If count is 0, 80 | * T is the empty String is returned. 81 | * @param count number of copies to append 82 | */ 83 | repeat(count: number): string; 84 | 85 | /** 86 | * Returns true if the sequence of elements of searchString converted to a String is the 87 | * same as the corresponding elements of this object (converted to a String) starting at 88 | * position. Otherwise returns false. 89 | */ 90 | startsWith(searchString: string, position?: number): boolean; 91 | 92 | /** 93 | * Returns an HTML anchor element and sets the name attribute to the text value 94 | * @param name 95 | */ 96 | anchor(name: string): string; 97 | 98 | /** Returns a HTML element */ 99 | big(): string; 100 | 101 | /** Returns a HTML element */ 102 | blink(): string; 103 | 104 | /** Returns a HTML element */ 105 | bold(): string; 106 | 107 | /** Returns a HTML element */ 108 | fixed(): string 109 | 110 | /** Returns a HTML element and sets the color attribute value */ 111 | fontcolor(color: string): string 112 | 113 | /** Returns a HTML element and sets the size attribute value */ 114 | fontsize(size: number): string; 115 | 116 | /** Returns a HTML element and sets the size attribute value */ 117 | fontsize(size: string): string; 118 | 119 | /** Returns an HTML element */ 120 | italics(): string; 121 | 122 | /** Returns an HTML element and sets the href attribute value */ 123 | link(url: string): string; 124 | 125 | /** Returns a HTML element */ 126 | small(): string; 127 | 128 | /** Returns a HTML element */ 129 | strike(): string; 130 | 131 | /** Returns a HTML element */ 132 | sub(): string; 133 | 134 | /** Returns a HTML element */ 135 | sup(): string; 136 | 137 | /** 138 | * Shim for an ES6 iterable. Not intended for direct use by user code. 139 | */ 140 | "_es6-shim iterator_"(): IterableIteratorShim; 141 | } 142 | 143 | interface ArrayConstructor { 144 | /** 145 | * Creates an array from an array-like object. 146 | * @param arrayLike An array-like object to convert to an array. 147 | * @param mapfn A mapping function to call on every element of the array. 148 | * @param thisArg Value of 'this' used to invoke the mapfn. 149 | */ 150 | from(arrayLike: ArrayLike, mapfn: (v: T, k: number) => U, thisArg?: any): Array; 151 | 152 | /** 153 | * Creates an array from an iterable object. 154 | * @param iterable An iterable object to convert to an array. 155 | * @param mapfn A mapping function to call on every element of the array. 156 | * @param thisArg Value of 'this' used to invoke the mapfn. 157 | */ 158 | from(iterable: IterableShim, mapfn: (v: T, k: number) => U, thisArg?: any): Array; 159 | 160 | /** 161 | * Creates an array from an array-like object. 162 | * @param arrayLike An array-like object to convert to an array. 163 | */ 164 | from(arrayLike: ArrayLike): Array; 165 | 166 | /** 167 | * Creates an array from an iterable object. 168 | * @param iterable An iterable object to convert to an array. 169 | */ 170 | from(iterable: IterableShim): Array; 171 | 172 | /** 173 | * Returns a new array from a set of elements. 174 | * @param items A set of elements to include in the new array object. 175 | */ 176 | of(...items: T[]): Array; 177 | } 178 | 179 | interface Array { 180 | /** 181 | * Returns the value of the first element in the array where predicate is true, and undefined 182 | * otherwise. 183 | * @param predicate find calls predicate once for each element of the array, in ascending 184 | * order, until it finds one where predicate returns true. If such an element is found, find 185 | * immediately returns that element value. Otherwise, find returns undefined. 186 | * @param thisArg If provided, it will be used as the this value for each invocation of 187 | * predicate. If it is not provided, undefined is used instead. 188 | */ 189 | find(predicate: (value: T, index: number, obj: Array) => boolean, thisArg?: any): T; 190 | 191 | /** 192 | * Returns the index of the first element in the array where predicate is true, and undefined 193 | * otherwise. 194 | * @param predicate find calls predicate once for each element of the array, in ascending 195 | * order, until it finds one where predicate returns true. If such an element is found, find 196 | * immediately returns that element value. Otherwise, find returns undefined. 197 | * @param thisArg If provided, it will be used as the this value for each invocation of 198 | * predicate. If it is not provided, undefined is used instead. 199 | */ 200 | findIndex(predicate: (value: T) => boolean, thisArg?: any): number; 201 | 202 | /** 203 | * Returns the this object after filling the section identified by start and end with value 204 | * @param value value to fill array section with 205 | * @param start index to start filling the array at. If start is negative, it is treated as 206 | * length+start where length is the length of the array. 207 | * @param end index to stop filling the array at. If end is negative, it is treated as 208 | * length+end. 209 | */ 210 | fill(value: T, start?: number, end?: number): T[]; 211 | 212 | /** 213 | * Returns the this object after copying a section of the array identified by start and end 214 | * to the same array starting at position target 215 | * @param target If target is negative, it is treated as length+target where length is the 216 | * length of the array. 217 | * @param start If start is negative, it is treated as length+start. If end is negative, it 218 | * is treated as length+end. 219 | * @param end If not specified, length of the this object is used as its default value. 220 | */ 221 | copyWithin(target: number, start: number, end?: number): T[]; 222 | 223 | /** 224 | * Returns an array of key, value pairs for every entry in the array 225 | */ 226 | entries(): IterableIteratorShim<[number, T]>; 227 | 228 | /** 229 | * Returns an list of keys in the array 230 | */ 231 | keys(): IterableIteratorShim; 232 | 233 | /** 234 | * Returns an list of values in the array 235 | */ 236 | values(): IterableIteratorShim; 237 | 238 | /** 239 | * Shim for an ES6 iterable. Not intended for direct use by user code. 240 | */ 241 | "_es6-shim iterator_"(): IterableIteratorShim; 242 | } 243 | 244 | interface NumberConstructor { 245 | /** 246 | * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 247 | * that is representable as a Number value, which is approximately: 248 | * 2.2204460492503130808472633361816 x 10‍−‍16. 249 | */ 250 | EPSILON: number; 251 | 252 | /** 253 | * Returns true if passed value is finite. 254 | * Unlike the global isFininte, Number.isFinite doesn't forcibly convert the parameter to a 255 | * number. Only finite values of the type number, result in true. 256 | * @param number A numeric value. 257 | */ 258 | isFinite(number: number): boolean; 259 | 260 | /** 261 | * Returns true if the value passed is an integer, false otherwise. 262 | * @param number A numeric value. 263 | */ 264 | isInteger(number: number): boolean; 265 | 266 | /** 267 | * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a 268 | * number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter 269 | * to a number. Only values of the type number, that are also NaN, result in true. 270 | * @param number A numeric value. 271 | */ 272 | isNaN(number: number): boolean; 273 | 274 | /** 275 | * Returns true if the value passed is a safe integer. 276 | * @param number A numeric value. 277 | */ 278 | isSafeInteger(number: number): boolean; 279 | 280 | /** 281 | * The value of the largest integer n such that n and n + 1 are both exactly representable as 282 | * a Number value. 283 | * The value of Number.MIN_SAFE_INTEGER is 9007199254740991 2^53 − 1. 284 | */ 285 | MAX_SAFE_INTEGER: number; 286 | 287 | /** 288 | * The value of the smallest integer n such that n and n − 1 are both exactly representable as 289 | * a Number value. 290 | * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)). 291 | */ 292 | MIN_SAFE_INTEGER: number; 293 | 294 | /** 295 | * Converts a string to a floating-point number. 296 | * @param string A string that contains a floating-point number. 297 | */ 298 | parseFloat(string: string): number; 299 | 300 | /** 301 | * Converts A string to an integer. 302 | * @param s A string to convert into a number. 303 | * @param radix A value between 2 and 36 that specifies the base of the number in numString. 304 | * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal. 305 | * All other strings are considered decimal. 306 | */ 307 | parseInt(string: string, radix?: number): number; 308 | } 309 | 310 | interface ObjectConstructor { 311 | /** 312 | * Copy the values of all of the enumerable own properties from one or more source objects to a 313 | * target object. Returns the target object. 314 | * @param target The target object to copy to. 315 | * @param sources One or more source objects to copy properties from. 316 | */ 317 | assign(target: any, ...sources: any[]): any; 318 | 319 | /** 320 | * Returns true if the values are the same value, false otherwise. 321 | * @param value1 The first value. 322 | * @param value2 The second value. 323 | */ 324 | is(value1: any, value2: any): boolean; 325 | 326 | /** 327 | * Sets the prototype of a specified object o to object proto or null. Returns the object o. 328 | * @param o The object to change its prototype. 329 | * @param proto The value of the new prototype or null. 330 | * @remarks Requires `__proto__` support. 331 | */ 332 | setPrototypeOf(o: any, proto: any): any; 333 | } 334 | 335 | interface RegExp { 336 | /** 337 | * Returns a string indicating the flags of the regular expression in question. This field is read-only. 338 | * The characters in this string are sequenced and concatenated in the following order: 339 | * 340 | * - "g" for global 341 | * - "i" for ignoreCase 342 | * - "m" for multiline 343 | * - "u" for unicode 344 | * - "y" for sticky 345 | * 346 | * If no flags are set, the value is the empty string. 347 | */ 348 | flags: string; 349 | } 350 | 351 | interface Math { 352 | /** 353 | * Returns the number of leading zero bits in the 32-bit binary representation of a number. 354 | * @param x A numeric expression. 355 | */ 356 | clz32(x: number): number; 357 | 358 | /** 359 | * Returns the result of 32-bit multiplication of two numbers. 360 | * @param x First number 361 | * @param y Second number 362 | */ 363 | imul(x: number, y: number): number; 364 | 365 | /** 366 | * Returns the sign of the x, indicating whether x is positive, negative or zero. 367 | * @param x The numeric expression to test 368 | */ 369 | sign(x: number): number; 370 | 371 | /** 372 | * Returns the base 10 logarithm of a number. 373 | * @param x A numeric expression. 374 | */ 375 | log10(x: number): number; 376 | 377 | /** 378 | * Returns the base 2 logarithm of a number. 379 | * @param x A numeric expression. 380 | */ 381 | log2(x: number): number; 382 | 383 | /** 384 | * Returns the natural logarithm of 1 + x. 385 | * @param x A numeric expression. 386 | */ 387 | log1p(x: number): number; 388 | 389 | /** 390 | * Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of 391 | * the natural logarithms). 392 | * @param x A numeric expression. 393 | */ 394 | expm1(x: number): number; 395 | 396 | /** 397 | * Returns the hyperbolic cosine of a number. 398 | * @param x A numeric expression that contains an angle measured in radians. 399 | */ 400 | cosh(x: number): number; 401 | 402 | /** 403 | * Returns the hyperbolic sine of a number. 404 | * @param x A numeric expression that contains an angle measured in radians. 405 | */ 406 | sinh(x: number): number; 407 | 408 | /** 409 | * Returns the hyperbolic tangent of a number. 410 | * @param x A numeric expression that contains an angle measured in radians. 411 | */ 412 | tanh(x: number): number; 413 | 414 | /** 415 | * Returns the inverse hyperbolic cosine of a number. 416 | * @param x A numeric expression that contains an angle measured in radians. 417 | */ 418 | acosh(x: number): number; 419 | 420 | /** 421 | * Returns the inverse hyperbolic sine of a number. 422 | * @param x A numeric expression that contains an angle measured in radians. 423 | */ 424 | asinh(x: number): number; 425 | 426 | /** 427 | * Returns the inverse hyperbolic tangent of a number. 428 | * @param x A numeric expression that contains an angle measured in radians. 429 | */ 430 | atanh(x: number): number; 431 | 432 | /** 433 | * Returns the square root of the sum of squares of its arguments. 434 | * @param values Values to compute the square root for. 435 | * If no arguments are passed, the result is +0. 436 | * If there is only one argument, the result is the absolute value. 437 | * If any argument is +Infinity or -Infinity, the result is +Infinity. 438 | * If any argument is NaN, the result is NaN. 439 | * If all arguments are either +0 or −0, the result is +0. 440 | */ 441 | hypot(...values: number[]): number; 442 | 443 | /** 444 | * Returns the integral part of the a numeric expression, x, removing any fractional digits. 445 | * If x is already an integer, the result is x. 446 | * @param x A numeric expression. 447 | */ 448 | trunc(x: number): number; 449 | 450 | /** 451 | * Returns the nearest single precision float representation of a number. 452 | * @param x A numeric expression. 453 | */ 454 | fround(x: number): number; 455 | 456 | /** 457 | * Returns an implementation-dependent approximation to the cube root of number. 458 | * @param x A numeric expression. 459 | */ 460 | cbrt(x: number): number; 461 | } 462 | 463 | interface PromiseLike { 464 | /** 465 | * Attaches callbacks for the resolution and/or rejection of the Promise. 466 | * @param onfulfilled The callback to execute when the Promise is resolved. 467 | * @param onrejected The callback to execute when the Promise is rejected. 468 | * @returns A Promise for the completion of which ever callback is executed. 469 | */ 470 | then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike; 471 | then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike; 472 | } 473 | 474 | /** 475 | * Represents the completion of an asynchronous operation 476 | */ 477 | interface Promise { 478 | /** 479 | * Attaches callbacks for the resolution and/or rejection of the Promise. 480 | * @param onfulfilled The callback to execute when the Promise is resolved. 481 | * @param onrejected The callback to execute when the Promise is rejected. 482 | * @returns A Promise for the completion of which ever callback is executed. 483 | */ 484 | then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): Promise; 485 | then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): Promise; 486 | 487 | /** 488 | * Attaches a callback for only the rejection of the Promise. 489 | * @param onrejected The callback to execute when the Promise is rejected. 490 | * @returns A Promise for the completion of the callback. 491 | */ 492 | catch(onrejected?: (reason: any) => T | PromiseLike): Promise; 493 | catch(onrejected?: (reason: any) => void): Promise; 494 | } 495 | 496 | interface PromiseConstructor { 497 | /** 498 | * A reference to the prototype. 499 | */ 500 | prototype: Promise; 501 | 502 | /** 503 | * Creates a new Promise. 504 | * @param executor A callback used to initialize the promise. This callback is passed two arguments: 505 | * a resolve callback used resolve the promise with a value or the result of another promise, 506 | * and a reject callback used to reject the promise with a provided reason or error. 507 | */ 508 | new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void): Promise; 509 | 510 | /** 511 | * Creates a Promise that is resolved with an array of results when all of the provided Promises 512 | * resolve, or rejected when any Promise is rejected. 513 | * @param values An array of Promises. 514 | * @returns A new Promise. 515 | */ 516 | all(values: IterableShim>): Promise; 517 | 518 | /** 519 | * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved 520 | * or rejected. 521 | * @param values An array of Promises. 522 | * @returns A new Promise. 523 | */ 524 | race(values: IterableShim>): Promise; 525 | 526 | /** 527 | * Creates a new rejected promise for the provided reason. 528 | * @param reason The reason the promise was rejected. 529 | * @returns A new rejected Promise. 530 | */ 531 | reject(reason: any): Promise; 532 | 533 | /** 534 | * Creates a new rejected promise for the provided reason. 535 | * @param reason The reason the promise was rejected. 536 | * @returns A new rejected Promise. 537 | */ 538 | reject(reason: any): Promise; 539 | 540 | /** 541 | * Creates a new resolved promise for the provided value. 542 | * @param value A promise. 543 | * @returns A promise whose internal state matches the provided promise. 544 | */ 545 | resolve(value: T | PromiseLike): Promise; 546 | 547 | /** 548 | * Creates a new resolved promise . 549 | * @returns A resolved promise. 550 | */ 551 | resolve(): Promise; 552 | } 553 | 554 | declare var Promise: PromiseConstructor; 555 | 556 | interface Map { 557 | clear(): void; 558 | delete(key: K): boolean; 559 | forEach(callbackfn: (value: V, index: K, map: Map) => void, thisArg?: any): void; 560 | get(key: K): V; 561 | has(key: K): boolean; 562 | set(key: K, value?: V): Map; 563 | size: number; 564 | entries(): IterableIteratorShim<[K, V]>; 565 | keys(): IterableIteratorShim; 566 | values(): IterableIteratorShim; 567 | } 568 | 569 | interface MapConstructor { 570 | new (): Map; 571 | new (iterable: IterableShim<[K, V]>): Map; 572 | prototype: Map; 573 | } 574 | 575 | declare var Map: MapConstructor; 576 | 577 | interface Set { 578 | add(value: T): Set; 579 | clear(): void; 580 | delete(value: T): boolean; 581 | forEach(callbackfn: (value: T, index: T, set: Set) => void, thisArg?: any): void; 582 | has(value: T): boolean; 583 | size: number; 584 | entries(): IterableIteratorShim<[T, T]>; 585 | keys(): IterableIteratorShim; 586 | values(): IterableIteratorShim; 587 | } 588 | 589 | interface SetConstructor { 590 | new (): Set; 591 | new (iterable: IterableShim): Set; 592 | prototype: Set; 593 | } 594 | 595 | declare var Set: SetConstructor; 596 | 597 | interface WeakMap { 598 | delete(key: K): boolean; 599 | get(key: K): V; 600 | has(key: K): boolean; 601 | set(key: K, value?: V): WeakMap; 602 | } 603 | 604 | interface WeakMapConstructor { 605 | new (): WeakMap; 606 | new (iterable: IterableShim<[K, V]>): WeakMap; 607 | prototype: WeakMap; 608 | } 609 | 610 | declare var WeakMap: WeakMapConstructor; 611 | 612 | interface WeakSet { 613 | add(value: T): WeakSet; 614 | delete(value: T): boolean; 615 | has(value: T): boolean; 616 | } 617 | 618 | interface WeakSetConstructor { 619 | new (): WeakSet; 620 | new (iterable: IterableShim): WeakSet; 621 | prototype: WeakSet; 622 | } 623 | 624 | declare var WeakSet: WeakSetConstructor; 625 | 626 | declare namespace Reflect { 627 | function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; 628 | function construct(target: Function, argumentsList: ArrayLike): any; 629 | function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; 630 | function deleteProperty(target: any, propertyKey: PropertyKey): boolean; 631 | function enumerate(target: any): IterableIteratorShim; 632 | function get(target: any, propertyKey: PropertyKey, receiver?: any): any; 633 | function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; 634 | function getPrototypeOf(target: any): any; 635 | function has(target: any, propertyKey: PropertyKey): boolean; 636 | function isExtensible(target: any): boolean; 637 | function ownKeys(target: any): Array; 638 | function preventExtensions(target: any): boolean; 639 | function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; 640 | function setPrototypeOf(target: any, proto: any): boolean; 641 | } 642 | 643 | declare module "es6-shim" { 644 | var String: StringConstructor; 645 | var Array: ArrayConstructor; 646 | var Number: NumberConstructor; 647 | var Math: Math; 648 | var Object: ObjectConstructor; 649 | var Map: MapConstructor; 650 | var Set: SetConstructor; 651 | var WeakMap: WeakMapConstructor; 652 | var WeakSet: WeakSetConstructor; 653 | var Promise: PromiseConstructor; 654 | namespace Reflect { 655 | function apply(target: Function, thisArgument: any, argumentsList: ArrayLike): any; 656 | function construct(target: Function, argumentsList: ArrayLike): any; 657 | function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean; 658 | function deleteProperty(target: any, propertyKey: PropertyKey): boolean; 659 | function enumerate(target: any): Iterator; 660 | function get(target: any, propertyKey: PropertyKey, receiver?: any): any; 661 | function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor; 662 | function getPrototypeOf(target: any): any; 663 | function has(target: any, propertyKey: PropertyKey): boolean; 664 | function isExtensible(target: any): boolean; 665 | function ownKeys(target: any): Array; 666 | function preventExtensions(target: any): boolean; 667 | function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean; 668 | function setPrototypeOf(target: any, proto: any): boolean; 669 | } 670 | } -------------------------------------------------------------------------------- /angular/typings/main/ambient/jasmine/index.d.ts: -------------------------------------------------------------------------------- 1 | // Generated by typings 2 | // Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/5c182b9af717f73146399c2485f70f1e2ac0ff2b/jasmine/jasmine.d.ts 3 | // Type definitions for Jasmine 2.2 4 | // Project: http://jasmine.github.io/ 5 | // Definitions by: Boris Yankov , Theodore Brown , David Pärsson 6 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 7 | 8 | 9 | // For ddescribe / iit use : https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/karma-jasmine/karma-jasmine.d.ts 10 | 11 | declare function describe(description: string, specDefinitions: () => void): void; 12 | declare function fdescribe(description: string, specDefinitions: () => void): void; 13 | declare function xdescribe(description: string, specDefinitions: () => void): void; 14 | 15 | declare function it(expectation: string, assertion?: () => void, timeout?: number): void; 16 | declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 17 | declare function fit(expectation: string, assertion?: () => void, timeout?: number): void; 18 | declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 19 | declare function xit(expectation: string, assertion?: () => void, timeout?: number): void; 20 | declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void; 21 | 22 | /** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */ 23 | declare function pending(reason?: string): void; 24 | 25 | declare function beforeEach(action: () => void, timeout?: number): void; 26 | declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void; 27 | declare function afterEach(action: () => void, timeout?: number): void; 28 | declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void; 29 | 30 | declare function beforeAll(action: () => void, timeout?: number): void; 31 | declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; 32 | declare function afterAll(action: () => void, timeout?: number): void; 33 | declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void; 34 | 35 | declare function expect(spy: Function): jasmine.Matchers; 36 | declare function expect(actual: any): jasmine.Matchers; 37 | 38 | declare function fail(e?: any): void; 39 | /** Action method that should be called when the async work is complete */ 40 | interface DoneFn extends Function { 41 | (): void; 42 | 43 | /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */ 44 | fail: (message?: Error|string) => void; 45 | } 46 | 47 | declare function spyOn(object: any, method: string): jasmine.Spy; 48 | 49 | declare function runs(asyncMethod: Function): void; 50 | declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void; 51 | declare function waits(timeout?: number): void; 52 | 53 | declare namespace jasmine { 54 | 55 | var clock: () => Clock; 56 | 57 | function any(aclass: any): Any; 58 | function anything(): Any; 59 | function arrayContaining(sample: any[]): ArrayContaining; 60 | function objectContaining(sample: any): ObjectContaining; 61 | function createSpy(name: string, originalFn?: Function): Spy; 62 | function createSpyObj(baseName: string, methodNames: any[]): any; 63 | function createSpyObj(baseName: string, methodNames: any[]): T; 64 | function pp(value: any): string; 65 | function getEnv(): Env; 66 | function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; 67 | function addMatchers(matchers: CustomMatcherFactories): void; 68 | function stringMatching(str: string): Any; 69 | function stringMatching(str: RegExp): Any; 70 | 71 | interface Any { 72 | 73 | new (expectedClass: any): any; 74 | 75 | jasmineMatches(other: any): boolean; 76 | jasmineToString(): string; 77 | } 78 | 79 | // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains() 80 | interface ArrayLike { 81 | length: number; 82 | [n: number]: T; 83 | } 84 | 85 | interface ArrayContaining { 86 | new (sample: any[]): any; 87 | 88 | asymmetricMatch(other: any): boolean; 89 | jasmineToString(): string; 90 | } 91 | 92 | interface ObjectContaining { 93 | new (sample: any): any; 94 | 95 | jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; 96 | jasmineToString(): string; 97 | } 98 | 99 | interface Block { 100 | 101 | new (env: Env, func: SpecFunction, spec: Spec): any; 102 | 103 | execute(onComplete: () => void): void; 104 | } 105 | 106 | interface WaitsBlock extends Block { 107 | new (env: Env, timeout: number, spec: Spec): any; 108 | } 109 | 110 | interface WaitsForBlock extends Block { 111 | new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any; 112 | } 113 | 114 | interface Clock { 115 | install(): void; 116 | uninstall(): void; 117 | /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */ 118 | tick(ms: number): void; 119 | mockDate(date?: Date): void; 120 | } 121 | 122 | interface CustomEqualityTester { 123 | (first: any, second: any): boolean; 124 | } 125 | 126 | interface CustomMatcher { 127 | compare(actual: T, expected: T): CustomMatcherResult; 128 | compare(actual: any, expected: any): CustomMatcherResult; 129 | } 130 | 131 | interface CustomMatcherFactory { 132 | (util: MatchersUtil, customEqualityTesters: Array): CustomMatcher; 133 | } 134 | 135 | interface CustomMatcherFactories { 136 | [index: string]: CustomMatcherFactory; 137 | } 138 | 139 | interface CustomMatcherResult { 140 | pass: boolean; 141 | message?: string; 142 | } 143 | 144 | interface MatchersUtil { 145 | equals(a: any, b: any, customTesters?: Array): boolean; 146 | contains(haystack: ArrayLike | string, needle: any, customTesters?: Array): boolean; 147 | buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: Array): string; 148 | } 149 | 150 | interface Env { 151 | setTimeout: any; 152 | clearTimeout: void; 153 | setInterval: any; 154 | clearInterval: void; 155 | updateInterval: number; 156 | 157 | currentSpec: Spec; 158 | 159 | matchersClass: Matchers; 160 | 161 | version(): any; 162 | versionString(): string; 163 | nextSpecId(): number; 164 | addReporter(reporter: Reporter): void; 165 | execute(): void; 166 | describe(description: string, specDefinitions: () => void): Suite; 167 | // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these 168 | beforeEach(beforeEachFunction: () => void): void; 169 | beforeAll(beforeAllFunction: () => void): void; 170 | currentRunner(): Runner; 171 | afterEach(afterEachFunction: () => void): void; 172 | afterAll(afterAllFunction: () => void): void; 173 | xdescribe(desc: string, specDefinitions: () => void): XSuite; 174 | it(description: string, func: () => void): Spec; 175 | // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these 176 | xit(desc: string, func: () => void): XSpec; 177 | compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean; 178 | compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; 179 | equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; 180 | contains_(haystack: any, needle: any): boolean; 181 | addCustomEqualityTester(equalityTester: CustomEqualityTester): void; 182 | addMatchers(matchers: CustomMatcherFactories): void; 183 | specFilter(spec: Spec): boolean; 184 | } 185 | 186 | interface FakeTimer { 187 | 188 | new (): any; 189 | 190 | reset(): void; 191 | tick(millis: number): void; 192 | runFunctionsWithinRange(oldMillis: number, nowMillis: number): void; 193 | scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void; 194 | } 195 | 196 | interface HtmlReporter { 197 | new (): any; 198 | } 199 | 200 | interface HtmlSpecFilter { 201 | new (): any; 202 | } 203 | 204 | interface Result { 205 | type: string; 206 | } 207 | 208 | interface NestedResults extends Result { 209 | description: string; 210 | 211 | totalCount: number; 212 | passedCount: number; 213 | failedCount: number; 214 | 215 | skipped: boolean; 216 | 217 | rollupCounts(result: NestedResults): void; 218 | log(values: any): void; 219 | getItems(): Result[]; 220 | addResult(result: Result): void; 221 | passed(): boolean; 222 | } 223 | 224 | interface MessageResult extends Result { 225 | values: any; 226 | trace: Trace; 227 | } 228 | 229 | interface ExpectationResult extends Result { 230 | matcherName: string; 231 | passed(): boolean; 232 | expected: any; 233 | actual: any; 234 | message: string; 235 | trace: Trace; 236 | } 237 | 238 | interface Trace { 239 | name: string; 240 | message: string; 241 | stack: any; 242 | } 243 | 244 | interface PrettyPrinter { 245 | 246 | new (): any; 247 | 248 | format(value: any): void; 249 | iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void; 250 | emitScalar(value: any): void; 251 | emitString(value: string): void; 252 | emitArray(array: any[]): void; 253 | emitObject(obj: any): void; 254 | append(value: any): void; 255 | } 256 | 257 | interface StringPrettyPrinter extends PrettyPrinter { 258 | } 259 | 260 | interface Queue { 261 | 262 | new (env: any): any; 263 | 264 | env: Env; 265 | ensured: boolean[]; 266 | blocks: Block[]; 267 | running: boolean; 268 | index: number; 269 | offset: number; 270 | abort: boolean; 271 | 272 | addBefore(block: Block, ensure?: boolean): void; 273 | add(block: any, ensure?: boolean): void; 274 | insertNext(block: any, ensure?: boolean): void; 275 | start(onComplete?: () => void): void; 276 | isRunning(): boolean; 277 | next_(): void; 278 | results(): NestedResults; 279 | } 280 | 281 | interface Matchers { 282 | 283 | new (env: Env, actual: any, spec: Env, isNot?: boolean): any; 284 | 285 | env: Env; 286 | actual: any; 287 | spec: Env; 288 | isNot?: boolean; 289 | message(): any; 290 | 291 | toBe(expected: any, expectationFailOutput?: any): boolean; 292 | toEqual(expected: any, expectationFailOutput?: any): boolean; 293 | toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean; 294 | toBeDefined(expectationFailOutput?: any): boolean; 295 | toBeUndefined(expectationFailOutput?: any): boolean; 296 | toBeNull(expectationFailOutput?: any): boolean; 297 | toBeNaN(): boolean; 298 | toBeTruthy(expectationFailOutput?: any): boolean; 299 | toBeFalsy(expectationFailOutput?: any): boolean; 300 | toHaveBeenCalled(): boolean; 301 | toHaveBeenCalledWith(...params: any[]): boolean; 302 | toHaveBeenCalledTimes(expected: number): boolean; 303 | toContain(expected: any, expectationFailOutput?: any): boolean; 304 | toBeLessThan(expected: number, expectationFailOutput?: any): boolean; 305 | toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean; 306 | toBeCloseTo(expected: number, precision: any, expectationFailOutput?: any): boolean; 307 | toThrow(expected?: any): boolean; 308 | toThrowError(message?: string | RegExp): boolean; 309 | toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean; 310 | not: Matchers; 311 | 312 | Any: Any; 313 | } 314 | 315 | interface Reporter { 316 | reportRunnerStarting(runner: Runner): void; 317 | reportRunnerResults(runner: Runner): void; 318 | reportSuiteResults(suite: Suite): void; 319 | reportSpecStarting(spec: Spec): void; 320 | reportSpecResults(spec: Spec): void; 321 | log(str: string): void; 322 | } 323 | 324 | interface MultiReporter extends Reporter { 325 | addReporter(reporter: Reporter): void; 326 | } 327 | 328 | interface Runner { 329 | 330 | new (env: Env): any; 331 | 332 | execute(): void; 333 | beforeEach(beforeEachFunction: SpecFunction): void; 334 | afterEach(afterEachFunction: SpecFunction): void; 335 | beforeAll(beforeAllFunction: SpecFunction): void; 336 | afterAll(afterAllFunction: SpecFunction): void; 337 | finishCallback(): void; 338 | addSuite(suite: Suite): void; 339 | add(block: Block): void; 340 | specs(): Spec[]; 341 | suites(): Suite[]; 342 | topLevelSuites(): Suite[]; 343 | results(): NestedResults; 344 | } 345 | 346 | interface SpecFunction { 347 | (spec?: Spec): void; 348 | } 349 | 350 | interface SuiteOrSpec { 351 | id: number; 352 | env: Env; 353 | description: string; 354 | queue: Queue; 355 | } 356 | 357 | interface Spec extends SuiteOrSpec { 358 | 359 | new (env: Env, suite: Suite, description: string): any; 360 | 361 | suite: Suite; 362 | 363 | afterCallbacks: SpecFunction[]; 364 | spies_: Spy[]; 365 | 366 | results_: NestedResults; 367 | matchersClass: Matchers; 368 | 369 | getFullName(): string; 370 | results(): NestedResults; 371 | log(arguments: any): any; 372 | runs(func: SpecFunction): Spec; 373 | addToQueue(block: Block): void; 374 | addMatcherResult(result: Result): void; 375 | expect(actual: any): any; 376 | waits(timeout: number): Spec; 377 | waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec; 378 | fail(e?: any): void; 379 | getMatchersClass_(): Matchers; 380 | addMatchers(matchersPrototype: CustomMatcherFactories): void; 381 | finishCallback(): void; 382 | finish(onComplete?: () => void): void; 383 | after(doAfter: SpecFunction): void; 384 | execute(onComplete?: () => void): any; 385 | addBeforesAndAftersToQueue(): void; 386 | explodes(): void; 387 | spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy; 388 | removeAllSpies(): void; 389 | } 390 | 391 | interface XSpec { 392 | id: number; 393 | runs(): void; 394 | } 395 | 396 | interface Suite extends SuiteOrSpec { 397 | 398 | new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any; 399 | 400 | parentSuite: Suite; 401 | 402 | getFullName(): string; 403 | finish(onComplete?: () => void): void; 404 | beforeEach(beforeEachFunction: SpecFunction): void; 405 | afterEach(afterEachFunction: SpecFunction): void; 406 | beforeAll(beforeAllFunction: SpecFunction): void; 407 | afterAll(afterAllFunction: SpecFunction): void; 408 | results(): NestedResults; 409 | add(suiteOrSpec: SuiteOrSpec): void; 410 | specs(): Spec[]; 411 | suites(): Suite[]; 412 | children(): any[]; 413 | execute(onComplete?: () => void): void; 414 | } 415 | 416 | interface XSuite { 417 | execute(): void; 418 | } 419 | 420 | interface Spy { 421 | (...params: any[]): any; 422 | 423 | identity: string; 424 | and: SpyAnd; 425 | calls: Calls; 426 | mostRecentCall: { args: any[]; }; 427 | argsForCall: any[]; 428 | wasCalled: boolean; 429 | } 430 | 431 | interface SpyAnd { 432 | /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */ 433 | callThrough(): Spy; 434 | /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */ 435 | returnValue(val: any): Spy; 436 | /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */ 437 | callFake(fn: Function): Spy; 438 | /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */ 439 | throwError(msg: string): Spy; 440 | /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */ 441 | stub(): Spy; 442 | } 443 | 444 | interface Calls { 445 | /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. **/ 446 | any(): boolean; 447 | /** By chaining the spy with calls.count(), will return the number of times the spy was called **/ 448 | count(): number; 449 | /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index **/ 450 | argsFor(index: number): any[]; 451 | /** By chaining the spy with calls.allArgs(), will return the arguments to all calls **/ 452 | allArgs(): any[]; 453 | /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls **/ 454 | all(): CallInfo[]; 455 | /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call **/ 456 | mostRecent(): CallInfo; 457 | /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call **/ 458 | first(): CallInfo; 459 | /** By chaining the spy with calls.reset(), will clears all tracking for a spy **/ 460 | reset(): void; 461 | } 462 | 463 | interface CallInfo { 464 | /** The context (the this) for the call */ 465 | object: any; 466 | /** All arguments passed to the call */ 467 | args: any[]; 468 | /** The return value of the call */ 469 | returnValue: any; 470 | } 471 | 472 | interface Util { 473 | inherit(childClass: Function, parentClass: Function): any; 474 | formatException(e: any): any; 475 | htmlEscape(str: string): string; 476 | argsToArray(args: any): any; 477 | extend(destination: any, source: any): any; 478 | } 479 | 480 | interface JsApiReporter extends Reporter { 481 | 482 | started: boolean; 483 | finished: boolean; 484 | result: any; 485 | messages: any; 486 | 487 | new (): any; 488 | 489 | suites(): Suite[]; 490 | summarize_(suiteOrSpec: SuiteOrSpec): any; 491 | results(): any; 492 | resultsForSpec(specId: any): any; 493 | log(str: any): any; 494 | resultsForSpecs(specIds: any): any; 495 | summarizeResult_(result: any): any; 496 | } 497 | 498 | interface Jasmine { 499 | Spec: Spec; 500 | clock: Clock; 501 | util: Util; 502 | } 503 | 504 | export var HtmlReporter: HtmlReporter; 505 | export var HtmlSpecFilter: HtmlSpecFilter; 506 | export var DEFAULT_TIMEOUT_INTERVAL: number; 507 | } -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require("express"); 2 | var bodyParser = require("body-parser"); 3 | var couchbase = require("couchbase"); 4 | var ottoman = require("ottoman"); 5 | var path = require("path"); 6 | var config = require("./config"); 7 | var app = express(); 8 | 9 | app.use(bodyParser.json()); 10 | app.use(bodyParser.urlencoded({ extended: true })); 11 | 12 | // Global declaration of the Couchbase server and bucket to be used 13 | var cluster = new couchbase.Cluster(config.couchbase.server); 14 | cluster.authenticate(config.couchbase.user, config.couchbase.pass); 15 | var bucket = cluster.openBucket(config.couchbase.bucket); 16 | module.exports.bucket = bucket; 17 | 18 | // Use store adapter directly so we can control the Couchnode version. 19 | ottoman.store = new ottoman.CbStoreAdapter(module.exports.bucket, couchbase); 20 | 21 | // Set up our routes 22 | app.use("/cdn",express.static(path.join(__dirname, "cdn"))); 23 | app.use(express.static(path.join(__dirname, "public"))); 24 | //app.use("/node_modules", express.static(__dirname + "/node_modules/")); 25 | 26 | app.use(function(req, res, next) { 27 | res.header("Access-Control-Allow-Origin", "*"); 28 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 29 | next(); 30 | }); 31 | 32 | // All endpoints to be used in this application 33 | var company = require("./routes/company.js")(app); 34 | var user = require("./routes/user.js")(app); 35 | var project = require("./routes/project.js")(app); 36 | var task = require("./routes/task.js")(app); 37 | var cdn = require("./routes/cdn.js")(app); 38 | 39 | var UserModel = require("./models/user"); 40 | var CompanyModel = require("./models/company"); 41 | 42 | ottoman.ensureIndices(function(error) { 43 | if(error) { 44 | console.log(error); 45 | } 46 | CompanyModel.findByCompanyName("Couchbase", function(error, company) { 47 | if(company.length < 1) { 48 | createDefaultCompany().then(function(result) { 49 | var server = app.listen(3000, function() { 50 | console.log("Listening on port %s...", server.address().port); 51 | }); 52 | }, function(error) { 53 | console.error(error); 54 | }); 55 | } else { 56 | var server = app.listen(3000, function() { 57 | console.log("Listening on port %s...", server.address().port); 58 | }); 59 | } 60 | }); 61 | }); 62 | 63 | var createDefaultCompany = function() { 64 | return new Promise(function(resolve, reject) { 65 | var company = new CompanyModel({ 66 | name: "Couchbase", 67 | address: { 68 | street: "2440 West El Camino Real", 69 | city: "Mountain View", 70 | state: "CA", 71 | zip: "94040", 72 | country: "USA" 73 | }, 74 | phone: "1234567890", 75 | website: "https://www.couchbase.com" 76 | }); 77 | console.log(company); 78 | company.save(function(error) { 79 | if(error) { 80 | reject(error); 81 | } 82 | resolve(company); 83 | }); 84 | }); 85 | } 86 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "couchbase": { 3 | "server": "couchbase://localhost", 4 | "bucket": "default", 5 | "user": "Administrator", 6 | "pass": "password" 7 | }, 8 | "salt":"testApp" 9 | } 10 | -------------------------------------------------------------------------------- /models/company.js: -------------------------------------------------------------------------------- 1 | var ottoman = require("ottoman"); 2 | var validator = require("../validators/validators.js"); 3 | 4 | var CompanyMdl = ottoman.model("Company", { 5 | createdON: { type: "Date", default:new Date() }, 6 | name: "string", 7 | address: { 8 | street: "string", 9 | city: "string", 10 | state: "string", 11 | zip: "integer", 12 | country: { type: "string", default: "USA" } 13 | }, 14 | phone: { type:"string", validator: validator.PhoneValidator }, 15 | website: "string", 16 | active: { type: "boolean", default:true } 17 | }, { 18 | index: { 19 | findByCompanyName: { 20 | by: "name", 21 | type: "refdoc" 22 | } 23 | } 24 | }); 25 | 26 | module.exports=CompanyMdl; 27 | -------------------------------------------------------------------------------- /models/project.js: -------------------------------------------------------------------------------- 1 | var ottoman = require("ottoman"); 2 | var validator = require("../validators/validators.js"); 3 | 4 | var ProjectMdl = ottoman.model("Project", { 5 | createdON: { type: "Date", default: function() { return new Date() } }, 6 | name: "string", 7 | description: "string", 8 | owner: { ref: "User" }, 9 | users: [{ ref: "User" }], 10 | tasks: [{ ref: "Task" }], 11 | status: "string", 12 | permalink:{type:"string", default: validator.permalinker} 13 | }, { 14 | index: { 15 | findByName: { 16 | by: "name", 17 | type: "n1ql" 18 | }, 19 | findByStatus: { 20 | by: "status", 21 | type: "n1ql" 22 | }, 23 | findByOwner:{ 24 | by:"owner", 25 | type: "n1ql" 26 | }, 27 | findByLink:{ 28 | by:"permalink", 29 | type: "refdoc" 30 | } 31 | } 32 | }); 33 | 34 | module.exports=ProjectMdl; 35 | -------------------------------------------------------------------------------- /models/task.js: -------------------------------------------------------------------------------- 1 | var ottoman = require("ottoman"); 2 | var validator = require("../validators/validators.js"); 3 | 4 | var TaskMdl = ottoman.model("Task", { 5 | createdON: { type: "Date", default: function() {return new Date() }}, 6 | url: "string", 7 | name: "string", 8 | description: "string", 9 | type: "string", 10 | owner: {ref: "User"}, 11 | assignedTo: {ref: "User"}, 12 | users: [{ref: "User"}], 13 | priority: "string", 14 | status: "string", 15 | permalink: {type:"string", default: validator.permalinker}, 16 | history: [ 17 | { 18 | log: "string", 19 | photos: [{filename: "string",extension:"string"}], 20 | url: "string", 21 | user: {ref: "User"}, 22 | createdAt: { type: "Date", default: function() { return new Date() }} 23 | } 24 | ] 25 | }, { 26 | index: { 27 | findByName: { 28 | by: "name", 29 | type: "n1ql" 30 | }, 31 | findByType: { 32 | by: "type", 33 | type: "n1ql" 34 | }, 35 | findByStatus: { 36 | by: "status", 37 | type: "n1ql" 38 | }, 39 | findByPriority: { 40 | by: "priority", 41 | type: "n1ql" 42 | }, 43 | findByAssignedTo: 44 | { 45 | by: "assignedTo", 46 | type: "n1ql" 47 | }, 48 | findByOwner:{ 49 | by:"owner", 50 | type: "n1ql" 51 | }, 52 | findByLink:{ 53 | by:"permalink", 54 | type: "refdoc" 55 | } 56 | } 57 | }); 58 | 59 | module.exports=TaskMdl; 60 | -------------------------------------------------------------------------------- /models/user.js: -------------------------------------------------------------------------------- 1 | var ottoman = require("ottoman"); 2 | var validator = require("../validators/validators.js"); 3 | var CompanyMdl = require("./company.js"); 4 | 5 | var UserMdl = ottoman.model("User", { 6 | createdON: {type: "Date", default:function(){return new Date()}}, 7 | name: { 8 | first: "string", 9 | last: "string"}, 10 | address: { 11 | street: "string", 12 | city: "string", 13 | state: "string", 14 | zip: "integer", 15 | country: {type: "string", default: "USA"}}, 16 | phone: {type: "string", validator: validator.PhoneValidator}, 17 | email: "string", 18 | password: "string", 19 | company: {ref: "Company"}, 20 | active: {type: "boolean", default: true} 21 | }, { 22 | index: { 23 | findByEmail: { 24 | by: "email", 25 | type: "refdoc" 26 | }, 27 | findByLastName: { 28 | by: "name.last", 29 | type: "n1ql" 30 | }, 31 | findByCompany:{ 32 | by:"company", 33 | type: "n1ql" 34 | } 35 | } 36 | }); 37 | 38 | module.exports=UserMdl; 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cean-stack-webinar", 3 | "version": "1.1.0", 4 | "description": "An example of using the Node.js SDK for Couchbase with an Angular 2 frontend", 5 | "author": "Couchbase, Inc.", 6 | "license": "MIT", 7 | "dependencies": { 8 | "bcryptjs": "^2.3.0", 9 | "body-parser": "^1.14.2", 10 | "couchbase": "^2.6.7", 11 | "express": "^4.13.3", 12 | "hashids": "^1.2.2", 13 | "multer": "~1.4.2", 14 | "ottoman": "^1.0.6" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /routes/cdn.js: -------------------------------------------------------------------------------- 1 | var multer = require('multer'); 2 | var TaskModel = require("../models/task"); 3 | var ProjectModel = require("../models/project"); 4 | var UserModel = require("../models/user"); 5 | 6 | var appRouter = function (app) { 7 | 8 | app.post('/api/cdn/add', multer({dest: './cdn/'}).single('upl'), function (req, res) { 9 | TaskModel.getById(req.body.taskId, function (error, task) { 10 | if (error) { 11 | return res.status(400).send(error); 12 | } 13 | var history = { 14 | log: req.body.description, 15 | user: UserModel.ref(req.body.userId), 16 | photos: [{filename: req.file.filename, extension: req.file.originalname.split('.').pop()}], 17 | createdAt: (new Date()) 18 | } 19 | task.history.push(history); 20 | task.save(function (error) { 21 | if (error) { 22 | return res.status(400).send(error); 23 | } 24 | UserModel.getById(req.body.userId, function (error, user) { 25 | if (error) { 26 | return res.status(400).send(error); 27 | } 28 | res.send({log: req.body.description, user: user, createdAt: history.createdAt, 29 | photos: [{filename: req.file.filename, extension: req.file.originalname.split('.').pop()}]}); 30 | }); 31 | }); 32 | }); 33 | }); 34 | } 35 | 36 | module.exports = appRouter; -------------------------------------------------------------------------------- /routes/company.js: -------------------------------------------------------------------------------- 1 | var CompanyModel = require("../models/company"); 2 | 3 | var appRouter = function(app) { 4 | 5 | app.get("/api/company/get/:companyId", function(req, res) { 6 | if(!req.params.companyId) { 7 | return res.status(400).send({"status": "error", "message": "A company id is required"}); 8 | } 9 | CompanyModel.getById(req.params.companyId, function(error, company) { 10 | if(error) { 11 | return res.status(400).send(error); 12 | } 13 | res.send(comapny); 14 | }); 15 | }); 16 | 17 | app.get("/api/company/getAll", function(req, res) { 18 | CompanyModel.find({}, function(error, result) { 19 | if(error) { 20 | return res.status(400).send(error); 21 | } 22 | res.send(result); 23 | }); 24 | }); 25 | 26 | app.post("/api/company/create", function(req, res) { 27 | var company = new CompanyModel({ 28 | name: req.body.name, 29 | address: { 30 | street: req.body.address.street, 31 | city: req.body.address.city, 32 | state: req.body.address.state, 33 | zip: req.body.address.zip, 34 | country: req.body.address.country 35 | }, 36 | phone: req.body.phone, 37 | website: req.body.website 38 | }); 39 | company.save(function(error, result) { 40 | if(error) { 41 | return res.status(400).send(error); 42 | } 43 | res.send(req.body); 44 | }); 45 | }); 46 | 47 | }; 48 | 49 | module.exports = appRouter; 50 | -------------------------------------------------------------------------------- /routes/project.js: -------------------------------------------------------------------------------- 1 | var ProjectModel = require("../models/project"); 2 | var UserModel = require("../models/user"); 3 | 4 | var appRouter = function(app) { 5 | 6 | app.get("/api/project/link/:url",function(req,res){ 7 | if(!req.params.url) { 8 | return res.status(400).send({"status": "error", "message": "invalid link"}); 9 | } 10 | ProjectModel.findByLink(req.params.url,function(error,project){ 11 | if(error) { 12 | return res.status(400).send(error); 13 | } 14 | res.send(project[0]); 15 | }); 16 | }); 17 | 18 | app.get("/api/project/get/:projectId", function(req, res) { 19 | if(!req.params.projectId) { 20 | return res.status(400).send({"status": "error", "message": "A project id is required"}); 21 | } 22 | ProjectModel.getById(req.params.projectId, {load: ["users", "tasks"]}, function(error, project) { 23 | if(error) { 24 | return res.status(400).send(error); 25 | } 26 | res.send(project); 27 | }); 28 | }); 29 | 30 | app.get("/api/project/getAll/:ownerId?", function(req, res) { 31 | if(req.params.ownerId) { 32 | ProjectModel.findByOwner(UserModel.ref(req.params.ownerId), function(error, result) { 33 | if(error) { 34 | return res.status(400).send(error); 35 | } 36 | res.send(result); 37 | }); 38 | } else { 39 | ProjectModel.find({}, function(error, result) { 40 | if(error) { 41 | return res.status(400).send(error); 42 | } 43 | res.send(result); 44 | }); 45 | } 46 | }); 47 | 48 | app.get("/api/project/getOther/:userId?", function(req, res) { 49 | if(req.params.userId) { 50 | ProjectModel.find({users: {$contains: UserModel.ref(req.params.userId)}}, {load: ["owner"]}, function(error, result) { 51 | if(error) { 52 | return res.status(400).send(error); 53 | } 54 | res.send(result); 55 | }); 56 | } 57 | }); 58 | 59 | app.post("/api/project/create", function(req, res) { 60 | var project = new ProjectModel({ 61 | name: req.body.name, 62 | description: req.body.description, 63 | owner: UserModel.ref(req.body.owner), 64 | users: [UserModel.ref(req.body.owner)], 65 | status: "active" 66 | }); 67 | project.save(function(error, result) { 68 | if(error) { 69 | return res.status(400).send(error); 70 | } 71 | res.send(project); 72 | }); 73 | }); 74 | 75 | app.post("/api/project/addUser", function(req, res) { 76 | ProjectModel.getById(req.body.projectId, function(error, project) { 77 | if(error) { 78 | return res.status(400).send(error); 79 | } 80 | UserModel.find({email: req.body.email}, function(error, users) { 81 | if(error) { 82 | return res.status(400).send(error); 83 | } 84 | if(users.length > 0) { 85 | project.users.push(users[0]); 86 | project.save(function(error) { 87 | if(error) { 88 | return res.status(400).send(error); 89 | } 90 | res.send(users[0]); 91 | }); 92 | } else { 93 | return res.status(400).send({"status": "error", "message": "User does not exist"}); 94 | } 95 | }); 96 | }); 97 | }); 98 | 99 | app.get("/api/project/getUsers/:projectId", function(req, res) { 100 | if(!req.params.projectId) { 101 | return res.status(400).send({"status": "error", "message": "A project id is required"}); 102 | } 103 | ProjectModel.getById(req.params.projectId, {load: ["users"]}, function(error, project) { 104 | if(error) { 105 | return res.status(400).send(error); 106 | } 107 | res.send(project.users); 108 | }); 109 | }); 110 | 111 | }; 112 | 113 | module.exports = appRouter; 114 | -------------------------------------------------------------------------------- /routes/task.js: -------------------------------------------------------------------------------- 1 | var TaskModel = require("../models/task"); 2 | var ProjectModel = require("../models/project"); 3 | var UserModel = require("../models/user"); 4 | 5 | var appRouter = function(app) { 6 | 7 | app.get("/api/task/link/:url",function(req,res){ 8 | if(!req.params.url) { 9 | return res.status(400).send({"status": "error", "message": "invalid link"}); 10 | } 11 | TaskModel.findByLink(req.params.url, {load: ["users", "assignedTo", "history[*].user"]}, function(error, task) { 12 | if(error) { 13 | return res.status(400).send(error); 14 | } 15 | ProjectModel.find({tasks: {$contains: task[0]}}, function(error, projects) { 16 | if(error) { 17 | return res.status(400).send(error); 18 | } 19 | if(projects.length > 0) { 20 | res.send({projectId: projects[0]._id, task: task[0]}); 21 | } else { 22 | res.status(400).send({"status": "error", "message": "Project not found"}); 23 | } 24 | }); 25 | }); 26 | }); 27 | 28 | app.get("/api/task/get/:taskId", function(req, res) { 29 | if(!req.params.taskId) { 30 | return res.status(400).send({"status": "error", "message": "A task id is required"}); 31 | } 32 | TaskModel.getById(req.params.taskId, {load: ["users", "assignedTo", "history[*].user"]}, function(error, task) { 33 | if(error) { 34 | return res.status(400).send(error); 35 | } 36 | ProjectModel.find({tasks: {$contains: task}}, function(error, projects) { 37 | if(error) { 38 | return res.status(400).send(error); 39 | } 40 | if(projects.length > 0) { 41 | res.send({projectId: projects[0]._id, task: task}); 42 | } else { 43 | res.status(400).send({"status": "error", "message": "Project not found"}); 44 | } 45 | }); 46 | }); 47 | }); 48 | 49 | app.get("/api/task/getAssignedTo/:userId", function(req, res) { 50 | if(!req.params.userId) { 51 | return res.status(400).send({"status": "error", "message": "A user id is required"}); 52 | } 53 | TaskModel.findByAssignedTo(req.params.userId, {load: ["owner"]}, function(error, tasks) { 54 | if(error) { 55 | return res.status(400).send(error); 56 | } 57 | res.send(tasks); 58 | }); 59 | }); 60 | 61 | /* 62 | * Create a new task document and push a reference to the matching project document 63 | */ 64 | app.post("/api/task/create/:projectId", function(req, res) { 65 | var task = new TaskModel({ 66 | name: req.body.name, 67 | description: req.body.description, 68 | owner: UserModel.ref(req.body.owner), 69 | assignedTo: UserModel.ref(req.body.assignedTo), 70 | users: [UserModel.ref(req.body.owner)] 71 | }); 72 | task.save(function(error, result) { 73 | if(error) { 74 | return res.status(400).send(error); 75 | } 76 | ProjectModel.getById(req.params.projectId, function(error, project) { 77 | if(error) { 78 | return res.status(400).send(error); 79 | } 80 | project.tasks.push(task); 81 | project.save(function(error, result) { 82 | if(error) { 83 | return res.status(400).send(error); 84 | } 85 | res.send(task); 86 | }); 87 | }); 88 | }); 89 | }); 90 | 91 | app.post("/api/task/addUser", function(req, res) { 92 | TaskModel.getById(req.body.taskId, function(error, task) { 93 | if(error) { 94 | return res.status(400).send(error); 95 | } 96 | UserModel.find({email: req.body.email}, function(error, users) { 97 | if(error) { 98 | return res.status(400).send(error); 99 | } 100 | if(users.length > 0) { 101 | task.users.push(users[0]); 102 | task.save(function(error) { 103 | if(error) { 104 | return res.status(400).send(error); 105 | } 106 | res.send(users[0]); 107 | }); 108 | } else { 109 | return res.status(400).send({"status": "error", "message": "User does not exist"}); 110 | } 111 | }); 112 | }); 113 | }); 114 | 115 | app.post("/api/task/assignUser", function(req, res) { 116 | TaskModel.getById(req.body.taskId, function(error, task) { 117 | if(error) { 118 | return res.status(400).send(error); 119 | } 120 | UserModel.getById(req.body.userId, function(error, user) { 121 | if(error) { 122 | return res.status(400).send(error); 123 | } 124 | task.assignedTo = user; 125 | task.save(function(error) { 126 | if(error) { 127 | return res.status(400).send(error); 128 | } 129 | res.send(user); 130 | }); 131 | }); 132 | }); 133 | }); 134 | 135 | app.post("/api/task/addHistory", function(req, res) { 136 | TaskModel.getById(req.body.taskId, function(error, task) { 137 | if(error) { 138 | return res.status(400).send(error); 139 | } 140 | var history = { 141 | log: req.body.log, 142 | user: UserModel.ref(req.body.userId), 143 | createdAt: (new Date()) 144 | } 145 | task.history.push(history); 146 | task.save(function(error) { 147 | if(error) { 148 | return res.status(400).send(error); 149 | } 150 | UserModel.getById(req.body.userId, function(error, user) { 151 | if(error) { 152 | return res.status(400).send(error); 153 | } 154 | res.send({log: req.body.log, user: user, createdAt: history.createdAt}); 155 | }); 156 | }); 157 | }); 158 | }); 159 | 160 | app.post("/api/task/addPhoto", function(req,res){ 161 | TaskModel.getById(req.body.taskId,function(error,task){ 162 | if(error){ 163 | return res.status(400).send(error); 164 | } 165 | var history = { 166 | user: UserModel.ref(req.body.userId), 167 | createdAt: (new Date()), 168 | photos:[req.body.imageId] 169 | } 170 | task.save(function(error) { 171 | if (error) { 172 | return res.status(400).send(error); 173 | } 174 | UserModel.getById(req.body.userId, function(error, user) { 175 | if(error) { 176 | return res.status(400).send(error); 177 | } 178 | res.send({log: req.body.log, user: user, createdAt: history.createdAt, photos:[req.body.imageId]}); 179 | }); 180 | }); 181 | }); 182 | }); 183 | 184 | }; 185 | 186 | module.exports = appRouter; 187 | -------------------------------------------------------------------------------- /routes/user.js: -------------------------------------------------------------------------------- 1 | var bcrypt = require("bcryptjs"); 2 | var UserModel = require("../models/user"); 3 | var CompanyModel = require("../models/company"); 4 | 5 | var appRouter = function(app) { 6 | 7 | app.get("/api/user/get/:userId", function(req, res) { 8 | if(!req.params.userId) { 9 | return res.status(400).send({"status": "error", "message": "A user id is required"}); 10 | } 11 | UserModel.getById(req.params.userId, function(error, user) { 12 | if(error) { 13 | return res.status(400).send(error); 14 | } 15 | res.send(user); 16 | }); 17 | }); 18 | 19 | app.get("/api/user/getAll", function(req, res) { 20 | UserModel.find({}, {load: ["company"]}, function(error, result) { 21 | if(error) { 22 | return res.status(400).send(error); 23 | } 24 | res.send(result); 25 | }); 26 | }); 27 | 28 | app.get("/api/user/login/:email/:password", function(req, res) { 29 | if(!req.params.email) { 30 | return res.status(400).send({"status": "error", "message": "An email is required"}); 31 | } else if(!req.params.password) { 32 | return res.status(400).send({"status": "error", "message": "A password is required"}); 33 | } 34 | UserModel.findByEmail(req.params.email, function(error, users) { 35 | if(error) { 36 | return res.status(400).send(error); 37 | } 38 | if(users.length > 0) { 39 | if(bcrypt.compareSync(req.params.password, users[0].password)) { 40 | res.send(users[0]); 41 | } else { 42 | res.status(400).send({"status": "error", "message": "Password is invalid"}); 43 | } 44 | } else { 45 | res.status(400).send({"status": "error", "message": "Email does not exist"}); 46 | } 47 | }); 48 | }); 49 | 50 | app.post("/api/user/create", function(req, res) { 51 | var user = new UserModel({ 52 | name: { 53 | first: req.body.name.first, 54 | last: req.body.name.last 55 | }, 56 | address: { 57 | street: req.body.address.street, 58 | city: req.body.address.city, 59 | state: req.body.address.state, 60 | zip: req.body.address.zip, 61 | country: req.body.address.country 62 | }, 63 | phone: req.body.phone, 64 | email: req.body.email, 65 | password: bcrypt.hashSync(req.body.password, 10), 66 | company: CompanyModel.ref(req.body.company) 67 | }); 68 | user.save(function(error, result) { 69 | if(error) { 70 | return res.status(400).send(error); 71 | } 72 | CompanyModel.getById(req.body.company, function(error, company) { 73 | if(error) { 74 | return res.status(400).send(error); 75 | } 76 | user.company = company; 77 | res.send(user); 78 | }); 79 | }); 80 | }); 81 | 82 | }; 83 | 84 | module.exports = appRouter; 85 | -------------------------------------------------------------------------------- /validators/validators.js: -------------------------------------------------------------------------------- 1 | var Hashids = require("hashids"); 2 | var config = require("./../config.json"); 3 | 4 | module.exports.phoneValidator=function(val) { 5 | var phoneno = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/; 6 | if(val && !val.match(phoneno)) { 7 | throw new Error('Phone number is invalid.'); 8 | } 9 | } 10 | 11 | module.exports.permalinker=function(){ 12 | var milliseconds = (new Date).getTime(); 13 | var hashids = new Hashids(config.salt); 14 | var id = hashids.encode(milliseconds); 15 | return id; 16 | } 17 | --------------------------------------------------------------------------------