:sparlkes: project setup

This commit is contained in:
Alicia Sykes
2017-04-29 11:42:07 +01:00
commit 3b48091c13
81 changed files with 8975 additions and 0 deletions

18
.alivrc Normal file
View File

@@ -0,0 +1,18 @@
{
"quiet": true,
"port": 3000,
"http2": false,
"pathIndex": "client/dev",
"only": [
"client/dev/**/*"
],
"static": [
"node_modules",
"jspm_packages"
],
"proxy": true,
"proxyWhen": "/api/*",
"proxyTarget": "http://localhost:3333"
}

6
.babelrc Normal file
View File

@@ -0,0 +1,6 @@
{
"presets": [
"es2015",
"stage-0"
]
}

3
.bowerrc Normal file
View File

@@ -0,0 +1,3 @@
{
"directory": "client/dev/bower_components"
}

12
.editorconfig Normal file
View File

@@ -0,0 +1,12 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.idea
coverage
node_modules
unit_coverage
client/dev/bower_components
typings

29
.jshintrc Normal file
View File

@@ -0,0 +1,29 @@
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"undef": true,
"unused": true,
"strict": true,
"browser": true,
"globals": {
"describe": false,
"it": false,
"before": false,
"beforeEach": false,
"after": false,
"afterEach": false,
"inject": false,
"expect": false,
"spyOn": false
}
}

17
.travis.yml Normal file
View File

@@ -0,0 +1,17 @@
language: node_js
node_js:
- "5"
before_script:
- npm install -g bower gulp-cli mocha
- npm run-script test-on-travis
- bower install
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
script:
- gulp coverage_frontend
- npm run-script test-on-travis
services: mongodb

18
.yo-rc.json Normal file
View File

@@ -0,0 +1,18 @@
{
"generator-ng-fullstack": {
"appName": "happy-team",
"username": "alicia",
"userEmail": "alicia.sykes@accenture.com",
"stack": "fullstack",
"repoHostUrl": "github.com",
"userNameSpace": "alicia",
"client": "ng2",
"stylePreprocessor": "sass",
"server": "node",
"nodeWebFrameworkServer": "express",
"transpilerServer": "babel",
"secure": false,
"testsSeparated": true,
"differentStaticServer": false
}
}

0
README.md Normal file
View File

22
client/dev/app.js Normal file
View File

@@ -0,0 +1,22 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var App = (function () {
function App() {
}
return App;
}());
App = __decorate([
core_1.Component({
selector: "app",
template: "\n\t\t<router-outlet></router-outlet>\n\t"
})
], App);
exports.App = App;
//# sourceMappingURL=app.js.map

1
client/dev/app.js.map Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":";;;;;;;;AAAA,sCAEuB;AAQvB,IAAa,GAAG;IAAhB;IAEA,CAAC;IAAD,UAAC;AAAD,CAAC,AAFD,IAEC;AAFY,GAAG;IANf,gBAAS,CAAC;QACV,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,2CAET;KACD,CAAC;GACW,GAAG,CAEf;AAFY,kBAAG"}

43
client/dev/app.module.js Normal file
View File

@@ -0,0 +1,43 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var http_1 = require("@angular/http");
var forms_1 = require("@angular/forms");
var platform_browser_1 = require("@angular/platform-browser");
var app_1 = require("./app");
var todo_cmp_1 = require("./todo/components/todo-cmp");
var todo_route_1 = require("./todo/components/todo-route");
var todo_service_1 = require("./todo/services/todo-service");
var AppModule = (function () {
function AppModule() {
}
return AppModule;
}());
AppModule = __decorate([
core_1.NgModule({
imports: [
platform_browser_1.BrowserModule,
forms_1.FormsModule,
http_1.HttpModule,
todo_route_1.todoRouting
],
declarations: [
app_1.App,
todo_cmp_1.TodoCmp,
],
providers: [
todo_service_1.TodoService,
],
bootstrap: [
app_1.App,
],
})
], AppModule);
exports.AppModule = AppModule;
//# sourceMappingURL=app.module.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["app.module.ts"],"names":[],"mappings":";;;;;;;;AAAA,sCAAyC;AACzC,sCAA2C;AAC3C,wCAA0D;AAC1D,8DAA2D;AAC3D,6BAA8B;AAC9B,uDAAuD;AACvD,2DAA2D;AAC3D,6DAA6D;AAoB7D,IAAa,SAAS;IAAtB;IAAwB,CAAC;IAAD,gBAAC;AAAD,CAAC,AAAzB,IAAyB;AAAZ,SAAS;IAlBrB,eAAQ,CAAC;QACN,OAAO,EAAE;YACP,gCAAa;YACb,mBAAW;YACX,iBAAU;YACV,wBAAW;SACZ;QACD,YAAY,EAAE;YACZ,SAAG;YACH,kBAAO;SACR;QACD,SAAS,EAAE;YACT,0BAAW;SACZ;QACD,SAAS,EAAE;YACT,SAAG;SACJ;KACJ,CAAC;GACW,SAAS,CAAG;AAAZ,8BAAS"}

28
client/dev/app.module.ts Normal file
View File

@@ -0,0 +1,28 @@
import { NgModule } from "@angular/core";
import { HttpModule } from "@angular/http";
import { FormsModule, FormBuilder } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { App } from "./app";
import { TodoCmp } from "./todo/components/todo-cmp";
import { todoRouting } from "./todo/components/todo-route";
import { TodoService } from "./todo/services/todo-service";
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
todoRouting
],
declarations: [
App,
TodoCmp,
],
providers: [
TodoService,
],
bootstrap: [
App,
],
})
export class AppModule {}

13
client/dev/app.ts Normal file
View File

@@ -0,0 +1,13 @@
import {
Component
} from "@angular/core";
@Component({
selector: "app",
template: `
<router-outlet></router-outlet>
`
})
export class App {
}

25
client/dev/config.js Normal file
View File

@@ -0,0 +1,25 @@
System.config({
defaultJSExtensions: true,
paths: {
// paths serve as alias
'npm:': './'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs'
}
});

28
client/dev/index.html Normal file
View File

@@ -0,0 +1,28 @@
<!doctype html>
<html>
<head>
<base href="/" >
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<link rel="shortcut icon" type="image/ico" href="favicon.png" />
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css">
<title>ng2do</title>
</head>
<body>
<app></app>
<script src="./systemjs/dist/system.js?rev=@@hash"></script>
<script src="./reflect-metadata/Reflect.js?rev=@@hash"></script>
<script src="./zone.js/dist/zone.js?rev=@@hash"></script>
<script src="./config.js?rev=@@hash"></script>
<script>
System.import("./index.js");
</script>
</body>
</html>

6
client/dev/index.js Normal file
View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var platform_browser_dynamic_1 = require("@angular/platform-browser-dynamic");
var app_module_1 = require("./app.module");
platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule);
//# sourceMappingURL=index.js.map

1
client/dev/index.js.map Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;AAAA,8EAE2C;AAE3C,2CAEsB;AAEtB,iDAAsB,EAAE,CAAC,eAAe,CAAC,sBAAS,CAAC,CAAC"}

9
client/dev/index.ts Normal file
View File

@@ -0,0 +1,9 @@
import {
platformBrowserDynamic
} from "@angular/platform-browser-dynamic";
import {
AppModule
} from "./app.module";
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@@ -0,0 +1,65 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var todo_service_1 = require("../services/todo-service");
var TodoCmp = (function () {
function TodoCmp(_todoService) {
this._todoService = _todoService;
this.title = "ng2do";
this.todos = [];
this.todoForm = {
"todoMessage": ""
};
}
TodoCmp.prototype.ngOnInit = function () {
this._getAll();
};
TodoCmp.prototype._getAll = function () {
var _this = this;
this._todoService
.getAll()
.subscribe(function (todos) {
_this.todos = todos;
});
};
TodoCmp.prototype.add = function (message) {
var _this = this;
this._todoService
.add(message)
.subscribe(function (m) {
_this.todos.push(m);
_this.todoForm.todoMessage = "";
});
};
TodoCmp.prototype.remove = function (id) {
var _this = this;
this._todoService
.remove(id)
.subscribe(function () {
_this.todos.forEach(function (t, i) {
if (t._id === id)
return _this.todos.splice(i, 1);
});
});
};
return TodoCmp;
}());
TodoCmp = __decorate([
core_1.Component({
selector: "todo-cmp",
templateUrl: "todo/templates/todo.html",
styleUrls: ["todo/styles/todo.css"]
}),
__metadata("design:paramtypes", [todo_service_1.TodoService])
], TodoCmp);
exports.TodoCmp = TodoCmp;
//# sourceMappingURL=todo-cmp.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"todo-cmp.js","sourceRoot":"","sources":["todo-cmp.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,sCAGuB;AAQvB,yDAEkC;AAYlC,IAAa,OAAO;IAKlB,iBAAoB,YAAyB;QAAzB,iBAAY,GAAZ,YAAY,CAAa;QAJ7C,UAAK,GAAW,OAAO,CAAC;QACxB,UAAK,GAAW,EAAE,CAAC;QAIjB,IAAI,CAAC,QAAQ,GAAG;YACd,aAAa,EAAE,EAAE;SAClB,CAAC;IACJ,CAAC;IAED,0BAAQ,GAAR;QACE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEO,yBAAO,GAAf;QAAA,iBAMC;QALC,IAAI,CAAC,YAAY;aACZ,MAAM,EAAE;aACR,SAAS,CAAC,UAAC,KAAK;YACf,KAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC,CAAC,CAAC;IACT,CAAC;IAED,qBAAG,GAAH,UAAI,OAAe;QAAnB,iBAOC;QANC,IAAI,CAAC,YAAY;aACZ,GAAG,CAAC,OAAO,CAAC;aACZ,SAAS,CAAC,UAAC,CAAC;YACX,KAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,KAAI,CAAC,QAAQ,CAAC,WAAW,GAAG,EAAE,CAAC;QACjC,CAAC,CAAC,CAAC;IACT,CAAC;IAED,wBAAM,GAAN,UAAO,EAAU;QAAjB,iBASC;QARC,IAAI,CAAC,YAAY;aACd,MAAM,CAAC,EAAE,CAAC;aACV,SAAS,CAAC;YACT,KAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAC,CAAC,EAAE,CAAC;gBACtB,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IACH,cAAC;AAAD,CAAC,AA1CD,IA0CC;AA1CY,OAAO;IALnB,gBAAS,CAAC;QACT,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,0BAA0B;QACvC,SAAS,EAAE,CAAC,sBAAsB,CAAC;KACpC,CAAC;qCAMkC,0BAAW;GALlC,OAAO,CA0CnB;AA1CY,0BAAO"}

View File

@@ -0,0 +1,68 @@
import {
Component,
OnInit
} from "@angular/core";
import {
Validators,
FormGroup,
FormControl
} from "@angular/forms";
import {
TodoService
} from "../services/todo-service";
type Todo = {
todoMessage: string;
_id?: string;
};
@Component({
selector: "todo-cmp",
templateUrl: "todo/templates/todo.html",
styleUrls: ["todo/styles/todo.css"]
})
export class TodoCmp implements OnInit {
title: string = "ng2do";
todos: Todo[] = [];
todoForm: Todo;
constructor(private _todoService: TodoService) {
this.todoForm = {
"todoMessage": ""
};
}
ngOnInit() {
this._getAll();
}
private _getAll(): void {
this._todoService
.getAll()
.subscribe((todos) => {
this.todos = todos;
});
}
add(message: string): void {
this._todoService
.add(message)
.subscribe((m) => {
this.todos.push(m);
this.todoForm.todoMessage = "";
});
}
remove(id: string): void {
this._todoService
.remove(id)
.subscribe(() => {
this.todos.forEach((t, i) => {
if (t._id === id)
return this.todos.splice(i, 1);
});
});
}
}

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var router_1 = require("@angular/router");
var todo_cmp_1 = require("../components/todo-cmp");
var todoRoutes = [
{
path: "",
component: todo_cmp_1.TodoCmp,
pathMatch: "full"
}
];
exports.todoRouting = router_1.RouterModule.forRoot(todoRoutes);
//# sourceMappingURL=todo-route.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"todo-route.js","sourceRoot":"","sources":["todo-route.ts"],"names":[],"mappings":";;AAAA,0CAGyB;AAEzB,mDAEgC;AAEhC,IAAM,UAAU,GAAU;IACzB;QACC,IAAI,EAAE,EAAE;QACR,SAAS,EAAE,kBAAO;QAClB,SAAS,EAAE,MAAM;KACjB;CACD,CAAA;AAEY,QAAA,WAAW,GAAG,qBAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC"}

View File

@@ -0,0 +1,18 @@
import {
Routes,
RouterModule
} from "@angular/router";
import {
TodoCmp
} from "../components/todo-cmp";
const todoRoutes:Routes = [
{
path: "",
component: TodoCmp,
pathMatch: "full"
}
]
export const todoRouting = RouterModule.forRoot(todoRoutes);

View File

@@ -0,0 +1,54 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
var core_1 = require("@angular/core");
var http_1 = require("@angular/http");
require("rxjs/add/operator/map");
var TodoService = TodoService_1 = (function () {
function TodoService(_http) {
this._http = _http;
}
TodoService.prototype.getAll = function () {
return this._http
.get(TodoService_1.ENDPOINT.replace(/:id/, ""))
.map(function (r) { return r.json(); });
};
TodoService.prototype.getById = function (id) {
return this._http
.get(TodoService_1.ENDPOINT.replace(/:id/, id))
.map(function (r) { return r.json(); });
};
TodoService.prototype.add = function (message) {
var _messageStringified = JSON.stringify({ todoMessage: message });
var headers = new http_1.Headers();
headers.append("Content-Type", "application/json");
return this._http
.post(TodoService_1.ENDPOINT.replace(/:id/, ""), _messageStringified, { headers: headers })
.map(function (r) { return r.json(); });
};
TodoService.prototype.remove = function (id) {
return this._http
.delete(TodoService_1.ENDPOINT.replace(/:id/, id));
};
return TodoService;
}());
TodoService.ENDPOINT = "/api/todos/:id";
TodoService = TodoService_1 = __decorate([
core_1.Injectable(),
__param(0, core_1.Inject(http_1.Http)),
__metadata("design:paramtypes", [http_1.Http])
], TodoService);
exports.TodoService = TodoService;
var TodoService_1;
//# sourceMappingURL=todo-service.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"todo-service.js","sourceRoot":"","sources":["todo-service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,sCAGuB;AAMvB,sCAGuB;AAEvB,iCAA+B;AAG/B,IAAa,WAAW;IAGtB,qBAAkC,KAAW;QAAX,UAAK,GAAL,KAAK,CAAM;IAE7C,CAAC;IAED,4BAAM,GAAN;QACE,MAAM,CAAC,IAAI,CAAC,KAAK;aACL,GAAG,CAAC,aAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;aAC5C,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAE,EAAR,CAAQ,CAAC,CAAC;IACnC,CAAC;IAED,6BAAO,GAAP,UAAQ,EAAU;QAChB,MAAM,CAAC,IAAI,CAAC,KAAK;aACL,GAAG,CAAC,aAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;aAC5C,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAE,EAAR,CAAQ,CAAC,CAAC;IACnC,CAAC;IAED,yBAAG,GAAH,UAAI,OAAe;QACjB,IAAI,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,EAAC,WAAW,EAAE,OAAO,EAAC,CAAC,CAAC;QAEjE,IAAI,OAAO,GAAG,IAAI,cAAO,EAAE,CAAC;QAE5B,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QAEnD,MAAM,CAAC,IAAI,CAAC,KAAK;aACL,IAAI,CAAC,aAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,mBAAmB,EAAE,EAAC,OAAO,SAAA,EAAC,CAAC;aAC7E,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC,CAAC,IAAI,EAAE,EAAR,CAAQ,CAAC,CAAC;IACnC,CAAC;IAED,4BAAM,GAAN,UAAO,EAAU;QACf,MAAM,CAAC,IAAI,CAAC,KAAK;aACL,MAAM,CAAC,aAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC;IACH,kBAAC;AAAD,CAAC,AAnCD,IAmCC;AAlCQ,oBAAQ,GAAW,gBAAgB,CAAC;AADhC,WAAW;IADvB,iBAAU,EAAE;IAIE,WAAA,aAAM,CAAC,WAAI,CAAC,CAAA;qCAAgB,WAAI;GAHlC,WAAW,CAmCvB;AAnCY,kCAAW"}

View File

@@ -0,0 +1,53 @@
import {
Inject,
Injectable
} from "@angular/core";
import {
Observable
} from "rxjs/Observable";
import {
Http,
Headers
} from "@angular/http";
import "rxjs/add/operator/map";
@Injectable()
export class TodoService {
static ENDPOINT: string = "/api/todos/:id";
constructor(@Inject(Http) private _http: Http) {
}
getAll(): Observable<any> {
return this._http
.get(TodoService.ENDPOINT.replace(/:id/, ""))
.map((r) => r.json());
}
getById(id: string):Observable<any> {
return this._http
.get(TodoService.ENDPOINT.replace(/:id/, id))
.map((r) => r.json());
}
add(message: string): Observable<any> {
let _messageStringified = JSON.stringify({todoMessage: message});
let headers = new Headers();
headers.append("Content-Type", "application/json");
return this._http
.post(TodoService.ENDPOINT.replace(/:id/, ""), _messageStringified, {headers})
.map((r) => r.json());
}
remove(id: string): Observable<any> {
return this._http
.delete(TodoService.ENDPOINT.replace(/:id/, id));
}
}

View File

@@ -0,0 +1,76 @@
.todo-container {
font-family: "Roboto";
position: relative;
max-width: 900px;
margin: 30px auto 0;
padding: 20px 10px 10px 10px;
box-shadow: 0 -1px 0 #e5e5e5,
0 0 2px rgba(0,0,0,.12),
0 2px 4px rgba(0,0,0,.24);
}
.todo-container .todo-title {
padding: 5px;
background-color: #fff;
position: absolute;
font-size: 30px;
top: -45px;
left: 0;
color: steelblue;
}
.todo-container .todo-form {
margin-top: 20px;
}
.todo-container input {
border: none;
border-bottom: 2px solid #ddd;
font-size: 17px;
padding: 5px 3px;
width: 90%;
box-sizing: border-box;
}
.todo-container input:focus {
outline: 0;
}
.todo-container button {
border-radius: 100%;
padding: 10px 14px;
font-weight: bold;
color: #fff;
background-color: steelblue;
cursor: pointer;
border: 2px solid #ddd;
font-size: 15px;
transition: all .2s;
}
.todo-container button:focus,
.todo-container button:active {
outline: none;
}
.todo-container button:disabled {
opacity: .7;
color: steelblue;
background-color: #fff;
cursor: not-allowed;
}
.todo-container .todo-error {
border-bottom-color: #E22323;
}
.todo-container .todo-item {
padding: 3px;
border-bottom: 1px solid #ddd;
cursor: pointer;
}
.todo-container .todo-item:hover {
background-color: #f1f2f3;
}

View File

@@ -0,0 +1,25 @@
<div class="todo-container">
<form class="todo-form"
(submit)="add(todoForm.todoMessage)">
<h1 class="todo-title">{{title}}</h1>
<input type="text"
name="todoMessage"
[(ngModel)]="todoForm.todoMessage"
[class.todo-error]="!todoForm.todoMessage.length"
placeholder="What do you have todo?"
autofocus />
<button type="submit"
[disabled]="!todoForm.todoMessage.length">+</button>
</form>
<div class="todo-list">
<div *ngFor="let todo of todos;"
class="todo-item"
(click)="remove(todo._id);">
<p>{{todo.todoMessage}}</p>
</div>
</div>
</div>

1
gulpfile.babel.js Normal file
View File

@@ -0,0 +1 @@
require('require-dir')('tasks');

91
karma-test-shim.js Normal file
View File

@@ -0,0 +1,91 @@
"use strict";
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000;
__karma__.loaded = function () {};
function isJsFile(path) {
return path.slice(-3) == '.js';
}
function isSpecFile(path) {
return path.slice(-8) == '_test.js';
}
function isTestFileBuilt(path) {
var builtPath = '/base/tests/client/';
return isJsFile(path) && (path.substr(0, builtPath.length) == builtPath);
}
var allSpecFiles = Object.keys(window.__karma__.files)
.filter(isSpecFile)
.filter(isTestFileBuilt);
// Load our SystemJS configuration.
System.config({
baseURL: '/base'
});
System.config({
map: {
'@angular': 'node_modules/@angular',
'rxjs': 'node_modules/rxjs',
'app': 'client/dev'
},
packages: {
'app': {
main: 'main.js',
defaultExtension: 'js'
},
'@angular/core': {
main: 'index.js',
defaultExtension: 'js'
},
'@angular/compiler': {
main: 'index.js',
defaultExtension: 'js'
},
'@angular/common': {
main: 'index.js',
defaultExtension: 'js'
},
'@angular/forms': {
main: 'index.js',
defaultExtension: 'js'
},
'@angular/platform-browser': {
main: 'index.js',
defaultExtension: 'js'
},
'@angular/platform-browser-dynamic': {
main: 'index.js',
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
}
}
});
Promise.all([
System.import('@angular/core/testing'),
System.import('@angular/platform-browser-dynamic/testing')
])
.then(function (providers) {
var testing = providers[0];
var testingBrowser = providers[1];
testing.setBaseTestProviders(testingBrowser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
testingBrowser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
})
.then(() => {
return Promise.all(
allSpecFiles.map((moduleName) => {
return System.import(moduleName);
}));
})
.then(__karma__.start)
.catch(__karma__.error);

64
karma.conf.js Normal file
View File

@@ -0,0 +1,64 @@
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
// paths loaded by Karma
'node_modules/reflect-metadata/Reflect.js',
// System.js for module loading
'node_modules/systemjs/dist/system-polyfills.js',
'node_modules/systemjs/dist/system.src.js',
// Zone.js dependencies
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/jasmine-patch.js',
'node_modules/zone.js/dist/async-test.js',
'node_modules/zone.js/dist/fake-async-test.js',
{pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false},
{pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false},
{pattern: 'karma-test-shim.js', included: true, watched: true},
// paths loaded via module imports
// Angular itself
{pattern: 'node_modules/@angular/**/*.js', included: false, watched: true},
{pattern: 'node_modules/@angular/**/*.js.map', included: false, watched: true},
// paths loaded via module imports
{pattern: 'client/dev/**/*.js', included: false, watched: true},
// paths loaded via Angular's component compiler
// (these paths need to be rewritten, see proxies section)
{pattern: 'client/dev/**/*.html', included: false, watched: true},
{pattern: 'client/dev/**/*.css', included: false, watched: true},
// paths to support debugging with source maps in dev tools
{pattern: 'client/dev/**/*.ts', included: false, watched: false},
{pattern: 'client/dev/**/*.js.map', included: false, watched: false},
{pattern: 'tests/client/**/*_test.js', included: false, watched: false},
],
// proxied base paths
proxies: {
// required for component assests fetched by Angular's compiler
"/app/": "/base/client/dev/"
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: true
})
}

24
newrelic.js Normal file
View File

@@ -0,0 +1,24 @@
/**
* New Relic agent configuration.
*
* See lib/config.defaults.js in the agent distribution for a more complete
* description of configuration variables and their potential values.
*/
exports.config = {
/**
* Array of application names.
*/
app_name : [process.env.NEW_RELIC_APP_NAME],
/**
* Your New Relic license key.
*/
license_key : process.env.NEW_RELIC_LICENSE_KEY,
logging : {
/**
* Level at which to log. 'trace' is most useful to New Relic when diagnosing
* issues with the agent, 'info' and higher will impose the least overhead on
* production applications.
*/
level : 'trace'
}
};

117
package.json Normal file
View File

@@ -0,0 +1,117 @@
{
"name": "happy-team",
"version": "0.0.1",
"main": "src/happy-team.js",
"scripts": {
"start": "node server/index",
"watch": "gulp",
"dev": "tsc && concurrently \"nodemon ./server/index --watch server\" \"gulp\"",
"build-dev": "gulp client.build:dev",
"build-dist": "gulp client.build:dist",
"test-client": "gulp client.unit_test",
"test-server": "mocha 'tests/server/**/*_test.js' --recursive --check-leaks --reporter min --compilers js:babel-register",
"coverage-server": "istanbul cover ./node_modules/mocha/bin/_mocha -- 'tests/server/**/*_test.js' --compilers js:babel-register",
"coveralls-server": "istanbul cover ./node_modules/mocha/bin/_mocha -- 'tests/server/**/*_test.js' --compilers js:babel-register --report lcovonly && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
},
"dependencies": {
"lodash": "^4.6.1",
"bluebird": "^3.3.4",
"body-parser": "^1.5.0",
"express": "~4.14.0",
"express-content-length-validator": "1.0.0",
"morgan": "^1.5.2",
"compression": "^1.6.2",
"helmet": "^2.1.1",
"nodemon": "^1.9.2",
"mongoose": "^4.4.7",
"@angular/common": "^2.4.4",
"@angular/compiler": "^2.4.4",
"@angular/core": "^2.4.4",
"@angular/forms": "^2.4.4",
"@angular/http": "^2.4.4",
"@angular/platform-browser": "^2.4.4",
"@angular/platform-browser-dynamic": "^2.4.4",
"@angular/router": "^3.4.4",
"zone.js": "^0.7.6",
"reflect-metadata": "^0.1.3",
"rxjs": "^5.0.0-beta.12",
"systemjs": "^0.19.24",
"typescript": "^2.1.5",
"zone.js": "^0.6.23",
"babel-register": "^6.7.2",
"babel-regenerator-runtime": "^6.5.0",
"babel-preset-es2015": "^6.1.18",
"babel-preset-es2016": "^6.0.11",
"babel-preset-stage-0": "^6.1.18",
"newrelic": "^1.18.2"
},
"devDependencies": {
"aliv": "^1.6.0",
"del": "^2.2.1",
"gulp": "^3.9.0",
"protractor": "^3.1.0",
"browser-sync": "^2.5.2",
"require-dir": "^0.3.0",
"babili": "0.0.6",
"gulp-babel": "^6.1.2",
"gulp-concat": "^2.4.3",
"gulp-coveralls": "^0.1.3",
"gulp-typescript": "~3.1.4",
"gulp-clean-css": "^2.0.3",
"gulp-rename": "^1.2.0",
"gulp-rev-append": "^0.1.6",
"gulp-uglify": "^1.1.0",
"gulp-htmlmin": "^2.0.0",
"gulp-imagemin": "^3.0.1",
"gulp-util": "^3.0.3",
"gulp-sass": "^2.3.2",
"jasmine-core": "^2.2.0",
"run-sequence": "^1.1.5",
"karma": "^1.3.0",
"karma-jasmine": "^1.0.2",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-firefox-launcher": "^1.0.0",
"karma-ie-launcher": "^1.0.0",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-opera-launcher": "^1.0.0",
"karma-phantomjs-launcher": "^1.0.1",
"karma-safari-launcher": "^1.0.0",
"mocha": "^2.4.5",
"chai": "^3.5.0",
"coveralls": "^2.11.2",
"istanbul": "^0.4.4",
"concurrently": "^2.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/alicia/happy-team.git"
},
"author": "alicia",
"license": "MIT",
"bugs": {
"url": "https://github.com/alicia/happy-team/issues"
},
"homepage": "https://github.com/alicia/happy-team",
"engines": {
"node": "stable"
}
}

1
procfile.txt Normal file
View File

@@ -0,0 +1 @@
web: npm start

4
protractor.conf.js Normal file
View File

@@ -0,0 +1,4 @@
exports.config = {
specs: ['./tests/e2e/**/*_test.js'],
baseUrl: 'http://localhost:3333/'
}

View File

@@ -0,0 +1,35 @@
import TodoDAO from "../dao/todo-dao";
export default class TodoController {
static getAll(req, res) {
TodoDAO
.getAll()
.then(todos => res.status(200).json(todos))
.catch(error => res.status(400).json(error));
}
static getById(req, res) {
TodoDAO
.getById(req.params.id)
.then(todo => res.status(200).json(todo))
.catch(error => res.status(400).json(error));
}
static createTodo(req, res) {
let _todo = req.body;
TodoDAO
.createTodo(_todo)
.then(todo => res.status(201).json(todo))
.catch(error => res.status(400).json(error));
}
static deleteTodo(req, res) {
let _id = req.params.id;
TodoDAO
.deleteTodo(_id)
.then(() => res.status(200).end())
.catch(error => res.status(400).json(error));
}
}

View File

@@ -0,0 +1,63 @@
import mongoose from "mongoose";
import Promise from "bluebird";
import todoSchema from "../model/todo-model";
import _ from "lodash";
todoSchema.statics.getAll = () => {
return new Promise((resolve, reject) => {
var _query = {};
Todo.find(_query)
.exec((err, todos) => {
err ? reject(err)
: resolve(todos);
});
});
}
todoSchema.statics.getById = (id) => {
return new Promise((resolve, reject) => {
if (!id) {
return reject(new TypeError("Id is not defined."));
}
Todo.findById(id)
.exec((err, todo) => {
err ? reject(err)
: resolve(todo);
});
});
}
todoSchema.statics.createTodo = (todo) => {
return new Promise((resolve, reject) => {
if (!_.isObject(todo)) {
return reject(new TypeError("Todo is not a valid object."));
}
var _todo = new Todo(todo);
_todo.save((err, saved) => {
err ? reject(err)
: resolve(saved);
});
});
}
todoSchema.statics.deleteTodo = (id) => {
return new Promise((resolve, reject) => {
if (!_.isString(id)) {
return reject(new TypeError("Id is not a valid string."));
}
Todo.findByIdAndRemove(id)
.exec((err, deleted) => {
err ? reject(err)
: resolve();
});
});
}
var Todo = mongoose.model("Todo", todoSchema);
export default Todo;

View File

@@ -0,0 +1,8 @@
import mongoose from "mongoose";
const _todoSchema = {
todoMessage: {type: String, required: true, trim: true},
createdAt: {type: Date, default: Date.now}
}
export default mongoose.Schema(_todoSchema);

View File

@@ -0,0 +1,14 @@
import TodoController from "../controller/todo-controller";
export default class TodoRoutes {
static init(router) {
router
.route("/api/todos")
.get(TodoController.getAll)
.post(TodoController.createTodo);
router
.route("/api/todos/:id")
.delete(TodoController.deleteTodo);
}
}

View File

View File

@@ -0,0 +1,14 @@
import fs from "fs";
import path from "path";
export default class StaticDispatcher {
static sendIndex(req, res) {
const _root = process.cwd();
const _env = process.env.NODE_ENV;
const _folder = _env === "production" ? "dist" : "dev";
res.type(".html");
fs.createReadStream(path.join(`${_root}/client/${_folder}/index.html`)).pipe(res);
}
}

14
server/config/db.conf.js Normal file
View File

@@ -0,0 +1,14 @@
import mongoose from "mongoose";
import Promise from "bluebird";
import dbConst from "../constants/db.json";
export default class DBConfig {
static init() {
const URL = (process.env.NODE_ENV === "production") ? process.env.MONGOHQ_URL
: dbConst.localhost;
mongoose.Promise = Promise;
mongoose.connect(URL);
mongoose.connection.on("error", console.error.bind(console, "An error ocurred with the DB connection: "));
}
};

View File

@@ -0,0 +1,29 @@
import morgan from "morgan";
import bodyParser from "body-parser";
import contentLength from "express-content-length-validator";
import helmet from "helmet";
import express from "express";
import compression from "compression";
import zlib from "zlib";
export default class RouteConfig {
static init(application) {
let _root = process.cwd();
let _nodeModules = "/node_modules/";
let _jspmPackages = "/jspm_packages/";
let _clientFiles = (process.env.NODE_ENV === "production") ? "/client/dist/" : "/client/dev/";
application.use(compression({
level: zlib.Z_BEST_COMPRESSION,
threshold: "1kb"
}));
application.use(express.static(_root + _nodeModules));
application.use(express.static(_root + _jspmPackages));
application.use(express.static(_root + _clientFiles));
application.use(bodyParser.json());
application.use(morgan("dev"));
application.use(contentLength.validateMax({max: 999}));
application.use(helmet());
}
}

3
server/constants/db.json Normal file
View File

@@ -0,0 +1,3 @@
{
"localhost": "mongodb://localhost/happy-team"
}

6
server/index.js Normal file
View File

@@ -0,0 +1,6 @@
"use strict";
require('babel-core/register');
require("babel-regenerator-runtime");
require('./server');

17
server/routes/index.js Normal file
View File

@@ -0,0 +1,17 @@
import TodoRoutes from "../api/todo/route/todo-route";
import StaticDispatcher from "../commons/static/index";
export default class Routes {
static init(app, router) {
TodoRoutes.init(router);
router
.route("*")
.get(StaticDispatcher.sendIndex);
app.use("/", router);
}
}

23
server/server.js Normal file
View File

@@ -0,0 +1,23 @@
if (process.env.NODE_ENV === "production")
require("newrelic");
const PORT = process.env.PORT || 3333;
import os from "os";
import express from "express";
import http from "http";
import RoutesConfig from "./config/routes.conf";
import DBConfig from "./config/db.conf";
import Routes from "./routes/index";
const app = express();
RoutesConfig.init(app);
DBConfig.init();
Routes.init(app, express.Router());
http.createServer(app)
.listen(PORT, () => {
console.log(`up and running @: ${os.hostname()} on port: ${PORT}`);
console.log(`enviroment: ${process.env.NODE_ENV}`);
});

36
tasks/client/build_css.js Normal file
View File

@@ -0,0 +1,36 @@
import gulp from "gulp";
import cssmin from "gulp-clean-css";
import {join} from "path";
import {base, tasks} from "./const";
import sass from "gulp-sass";
const CSS = base.DIST + "**/*.css";
const SASS = [
base.DEV + "**/*.{sass,scss}",
"!" + base.DEV + "bower_components/**/*.{sass,scss}",
"!node_modules/**/*.{sass,scss}",
];
gulp.task(tasks.CLIENT_COMPILE_TO_CSS, () => {
return gulp.src(SASS)
.pipe(sass())
.on("error", sass.logError)
.pipe(gulp.dest(base.DEV));
});
gulp.task(tasks.CLIENT_BUILD_CSS_DIST, () => {
return gulp.src(CSS, {base: base.DIST})
.pipe(cssmin())
.pipe(gulp.dest(base.DIST));
});

View File

@@ -0,0 +1,16 @@
import gulp from "gulp";
import htmlmin from "gulp-htmlmin";
import rev from "gulp-rev-append";
import {base, tasks} from "./const";
const VIEWS = base.DIST + "**/*.html";
gulp.task(tasks.CLIENT_VIEWS_DIST, () => {
return gulp.src(VIEWS, {base: base.DIST})
.pipe(rev())
.pipe(htmlmin({
collapseWhitespace: true,
caseSensitive: true
}))
.pipe(gulp.dest(base.DIST));
});

View File

@@ -0,0 +1,11 @@
import gulp from "gulp";
import imageMin from "gulp-imagemin";
import {base, tasks} from "./const";
const IMAGES = base.DIST + "**/*.{png,jpg,jpeg,svg,gif}";
gulp.task(tasks.CLIENT_IMAGE_DIST, () => {
return gulp.src(IMAGES, {base: base.DIST})
.pipe(imageMin())
.pipe(gulp.dest(base.DIST));
});

11
tasks/client/build_js.js Normal file
View File

@@ -0,0 +1,11 @@
import gulp from "gulp";
import uglify from "gulp-uglify";
import {base, tasks} from "./const";
const JS = base.DIST + "**/*.js";
gulp.task(tasks.CLIENT_JS_DIST, () => {
return gulp.src(JS, {base: base.DIST})
.pipe(uglify())
.pipe(gulp.dest(base.DIST));
});

14
tasks/client/build_ts.js Normal file
View File

@@ -0,0 +1,14 @@
import gulp from "gulp";
import tsc from "gulp-typescript";
import {base, tasks} from "./const";
const TS_CONFIG = base.ROOT + "tsconfig.json";
gulp.task(tasks.CLIENT_BUILD_TS, () => {
let _tsProject = tsc.createProject(TS_CONFIG);
return _tsProject.src()
.pipe(_tsProject())
.js
.pipe(gulp.dest("."));
});

34
tasks/client/const.js Normal file
View File

@@ -0,0 +1,34 @@
export const base = {
ROOT: "./",
DEV: "./client/dev/",
DIST: "./client/dist/",
TEST: "./tests/"
}
export const tasks = {
CLIENT_BUILD_DEV: "client.build:dev",
CLIENT_BUILD_DIST: "client.build:dist",
CLIENT_BUILD_CSS_DIST: "client.build_css:dist",
CLIENT_JS_DIST: "client.build_js:dist",
CLIENT_VIEWS_DIST: "client.views:dist",
CLIENT_IMAGE_DIST: "client.imgs:dist",
CLIENT_DEL_DIST: "client.del:dist",
CLIENT_COPY: "client.copy",
CLIENT_UNIT_TEST: "client.unit_test",
CLIENT_COVERAGE: "client.coverage",
CLIENT_RELOAD: "client.reload",
CLIENT_WATCH: "client.watch",
CLIENT_BUILD_TS: "client.build_ts",
CLIENT_COMPILE_TO_CSS: "client.compile_from_sass_to_css:dev"
}

7
tasks/client/copy.js Normal file
View File

@@ -0,0 +1,7 @@
import gulp from "gulp";
import {base, tasks} from "./const";
gulp.task(tasks.CLIENT_COPY, () => {
return gulp.src(base.DEV + "**/*")
.pipe(gulp.dest(base.DIST));
});

5
tasks/client/del.js Normal file
View File

@@ -0,0 +1,5 @@
import gulp from "gulp";
import del from "del";
import {base, tasks} from "./const";
gulp.task(tasks.CLIENT_DEL_DIST, () => del.sync([base.DIST]));

26
tasks/client/index.js Normal file
View File

@@ -0,0 +1,26 @@
import gulp from "gulp";
import runSequence from "run-sequence";
import {tasks} from "./const";
gulp.task(tasks.CLIENT_BUILD_DEV, [
tasks.CLIENT_BUILD_TS
]);
gulp.task(tasks.CLIENT_BUILD_DIST, () => {
return new Promise((resolve, reject) => {
runSequence(
tasks.CLIENT_BUILD_TS,
//tasks.CLIENT_UNIT_TEST,
tasks.CLIENT_DEL_DIST,
tasks.CLIENT_COPY,
tasks.CLIENT_VIEWS_DIST,
[
tasks.CLIENT_IMAGE_DIST,
tasks.CLIENT_JS_DIST
],
resolve
);
});
});

16
tasks/client/test.js Normal file
View File

@@ -0,0 +1,16 @@
import gulp from "gulp";
import coveralls from "gulp-coveralls";
import {Server as Karma} from "karma";
import {tasks} from "./const";
gulp.task(tasks.CLIENT_UNIT_TEST, (done) => {
return new Karma({
configFile: process.cwd() + "/karma.conf.js",
browsers: ["Chrome"],
singleRun: true
}, done).start();
});
gulp.task(tasks.CLIENT_COVERAGE, [tasks.CLIENT_UNIT_TEST], () => {
return gulp.src("unit_coverage/**/lcov.info").pipe(coveralls());
});

34
tasks/client/watch.js Normal file
View File

@@ -0,0 +1,34 @@
import gulp from "gulp";
import Server from "aliv";
import {base, tasks} from "./const";
let aliv = new Server({
watch: false,
root: process.cwd()
});
gulp.task(tasks.CLIENT_RELOAD, () => {
return aliv.reload();
});
gulp.task(tasks.CLIENT_WATCH, [tasks.CLIENT_BUILD_TS, tasks.CLIENT_COMPILE_TO_CSS ], () => {
aliv.start();
let _watchable = [];
_watchable.push(base.DEV + "**/*.ts");
_watchable.push(base.DEV + "**/*.css");
_watchable.push(base.DEV + "**/*.html");
_watchable.push(base.DEV + "**/*.{sass,scss}");
return gulp.watch(_watchable, [
tasks.CLIENT_BUILD_TS,
tasks.CLIENT_COMPILE_TO_CSS,
tasks.CLIENT_RELOAD,
]);
});

11
tasks/index.js Normal file
View File

@@ -0,0 +1,11 @@
import gulp from "gulp";
import {tasks} from "./client/const";
gulp.task("default", [tasks.CLIENT_WATCH]);
require("require-dir")("client");
require("require-dir")("server");

13
tasks/server/build_tsc.js Normal file
View File

@@ -0,0 +1,13 @@
import gulp from "gulp";
import tsc from "gulp-typescript";
const TS_CONFIG = "./tsconfig.json";
gulp.task("server.compile_tsc", () => {
let tsconfigSrc = tsc.createProject(TS_CONFIG);
return tsconfigSrc.src()
.pipe(tsconfigSrc())
.js
.pipe(gulp.dest("."));
});

1
tasks/server/index.js Normal file
View File

@@ -0,0 +1 @@
import gulp from 'gulp';

0
tasks/server/test.js Normal file
View File

View File

@@ -0,0 +1,71 @@
"use strict";
/// <reference path="../../../../typings/index.d.ts" />
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var testing_1 = require("@angular/core/testing");
var Observable_1 = require("rxjs/Observable");
var todo_cmp_1 = require("../../../../client/dev/todo/components/todo-cmp");
var todo_service_1 = require("../../../../client/dev/todo/services/todo-service");
var MockTodoService = (function (_super) {
__extends(MockTodoService, _super);
function MockTodoService() {
return _super !== null && _super.apply(this, arguments) || this;
}
MockTodoService.prototype.getAll = function () {
return new Observable_1.Observable(function (o) {
o.next([]);
});
};
MockTodoService.prototype.add = function (message) {
return new Observable_1.Observable(function (o) {
o.next(message);
});
};
MockTodoService.prototype.remove = function (id) {
return new Observable_1.Observable(function (o) {
o.next(id);
});
};
return MockTodoService;
}(todo_service_1.TodoService));
describe("todo_component", function () {
describe("creation", function () {
it("should create the component correctly", testing_1.async(function () {
var fixture = testing_1.TestBed.createComponent(todo_cmp_1.TodoCmp);
fixture.detectChanges();
var compiled = fixture.debugElement.nativeElement;
expect(compiled).toBeDefined();
}));
it("should inicialize the cmp correctly", testing_1.async(function () {
var fixture = testing_1.TestBed.createComponent(todo_cmp_1.TodoCmp);
var instance = fixture.debugElement.componentInstance;
spyOn(instance, "_getAll").and.callFake(function () { });
fixture.detectChanges();
expect(instance._getAll).toHaveBeenCalled();
}));
it("should call add correctly", testing_1.async(function () {
var fixture = testing_1.TestBed.createComponent(todo_cmp_1.TodoCmp);
fixture.detectChanges();
var instance = fixture.debugElement.componentInstance;
var _todoMsg = "yo";
instance.add(_todoMsg);
}));
it("should call remove correctly", testing_1.async(function () {
var fixture = testing_1.TestBed.createComponent(todo_cmp_1.TodoCmp);
fixture.detectChanges();
var instance = fixture.debugElement.componentInstance;
var _id = "abc123";
instance.remove(_id);
}));
});
});
//# sourceMappingURL=todo-cmp_test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"todo-cmp_test.js","sourceRoot":"","sources":["todo-cmp_test.ts"],"names":[],"mappings":";AAAA,uDAAuD;;;;;;;;;;;;AAEvD,iDAG+B;AAE/B,8CAEyB;AAEzB,4EAAwE;AACxE,kFAA8E;AAE9E;IAA8B,mCAAW;IAAzC;;IAkBA,CAAC;IAjBC,gCAAM,GAAN;QACE,MAAM,CAAC,IAAI,uBAAU,CAAC,UAAC,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6BAAG,GAAH,UAAI,OAAe;QACjB,MAAM,CAAC,IAAI,uBAAU,CAAC,UAAC,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,gCAAM,GAAN,UAAO,EAAU;QACf,MAAM,CAAC,IAAI,uBAAU,CAAC,UAAC,CAAC;YACtB,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IACH,sBAAC;AAAD,CAAC,AAlBD,CAA8B,0BAAW,GAkBxC;AAED,QAAQ,CAAC,gBAAgB,EAAE;IACzB,QAAQ,CAAC,UAAU,EAAE;QACnB,EAAE,CAAC,uCAAuC,EAAE,eAAK,CAAC;YAChD,IAAI,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,kBAAO,CAAC,CAAC;YAClD,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC;YAElD,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC,CAAC;QAEJ,EAAE,CAAC,qCAAqC,EAAE,eAAK,CAAC;YAC9C,IAAI,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,kBAAO,CAAC,CAAC;YAClD,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC;YAEtD,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAO,CAAC,CAAC,CAAC;YAClD,OAAO,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,gBAAgB,EAAE,CAAC;QAC3C,CAAC,CAAC,CAAC,CAAC;QAEJ,EAAE,CAAC,2BAA2B,EAAE,eAAK,CAAC;YACpC,IAAI,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,kBAAO,CAAC,CAAC;YAClD,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC;YAEtD,IAAI,QAAQ,GAAG,IAAI,CAAC;YACpB,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC,CAAC;QAEJ,EAAE,CAAC,8BAA8B,EAAE,eAAK,CAAC;YACvC,IAAI,OAAO,GAAG,iBAAO,CAAC,eAAe,CAAC,kBAAO,CAAC,CAAC;YAClD,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,iBAAiB,CAAC;YACtD,IAAI,GAAG,GAAG,QAAQ,CAAC;YAEnB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC,CAAC;IACN,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,75 @@
/// <reference path="../../../../typings/index.d.ts" />
import {
TestBed,
async
} from "@angular/core/testing";
import {
Observable
} from "rxjs/Observable";
import {TodoCmp} from "../../../../client/dev/todo/components/todo-cmp";
import {TodoService} from "../../../../client/dev/todo/services/todo-service";
class MockTodoService extends TodoService {
getAll(): Observable<any> {
return new Observable((o) => {
o.next([]);
});
}
add(message: string): Observable<any> {
return new Observable((o) => {
o.next(message);
});
}
remove(id: string): Observable<any> {
return new Observable((o) => {
o.next(id);
});
}
}
describe("todo_component", () => {
describe("creation", () => {
it("should create the component correctly", async(() => {
let fixture = TestBed.createComponent(TodoCmp);
fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement;
expect(compiled).toBeDefined();
}));
it("should inicialize the cmp correctly", async(() => {
let fixture = TestBed.createComponent(TodoCmp);
let instance = fixture.debugElement.componentInstance;
spyOn(instance, "_getAll").and.callFake(() => {});
fixture.detectChanges();
expect(instance._getAll).toHaveBeenCalled();
}));
it("should call add correctly", async(() => {
let fixture = TestBed.createComponent(TodoCmp);
fixture.detectChanges();
let instance = fixture.debugElement.componentInstance;
let _todoMsg = "yo";
instance.add(_todoMsg);
}));
it("should call remove correctly", async(() => {
let fixture = TestBed.createComponent(TodoCmp);
fixture.detectChanges();
let instance = fixture.debugElement.componentInstance;
let _id = "abc123";
instance.remove(_id);
}));
});
});

View File

@@ -0,0 +1,11 @@
"use strict";
/// <reference path="../../../../typings/index.d.ts" />
Object.defineProperty(exports, "__esModule", { value: true });
describe("todo_service", function () {
describe("creation", function () {
it("should create the service correctly", function () {
expect(true).toBe(true);
});
});
});
//# sourceMappingURL=todo-service_test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"todo-service_test.js","sourceRoot":"","sources":["todo-service_test.ts"],"names":[],"mappings":";AAAA,uDAAuD;;AAMvD,QAAQ,CAAC,cAAc,EAAE;IACvB,QAAQ,CAAC,UAAU,EAAE;QACnB,EAAE,CAAC,qCAAqC,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,13 @@
/// <reference path="../../../../typings/index.d.ts" />
import {TodoService} from "../../../../client/dev/todo/services/todo-service";
describe("todo_service", () => {
describe("creation", () => {
it("should create the service correctly", () => {
expect(true).toBe(true);
});
});
});

View File

@@ -0,0 +1,61 @@
"use strict";
describe("todo.e2e", function() {
var SUBMIT_TODO_BUTTON = "#submit-todo-button";
var TODO_MODEL = "todosCtrl.todo.todoMessage";
var CLOSE_TODO = ".todo-done";
beforeEach(function() {
browser.get("/");
})
describe("creation", function() {
it("should have the submit button disabled", function() {
expect($(SUBMIT_TODO_BUTTON).isEnabled()).toBeFalsy();
})
it("should have the right title", function() {
expect(browser.getTitle()).toEqual("Stuff Todo!");
})
})
describe("addition", function() {
it("should add a new todo - enter", function() {
element(by.model(TODO_MODEL)).sendKeys("This was added by Protractor :D (at "+String(new Date())+")");
element(by.model(TODO_MODEL)).sendKeys(protractor.Key.ENTER);
var _count = element.all(by.repeater("t in todosCtrl.todos")).count();
expect(_count).toBeGreaterThan(0);
})
it("should add a new todo - click", function() {
element(by.model(TODO_MODEL)).sendKeys("Added by Protractor :D (at "+String(new Date())+")");
$(SUBMIT_TODO_BUTTON)
.click()
.then(function() {
element.all(by.repeater("t in todosCtrl.todos"))
.count()
.then(function(count) {
expect(count).toBeGreaterThan(0);
});
});
})
})
describe("deletion", function() {
it("should delete a todo", function() {
var _firstCount = element.all(by.repeater("t in todosCtrl.todos")).count();
$$(CLOSE_TODO)
.get(0)
.click(function() {
var _secondCount = element.all(by.repeater("t in todosCtrl.todos")).count();
expect(_secondCount).toBeLessThan(_firstCount);
});
})
})
})

View File

@@ -0,0 +1,18 @@
import Todo from "../../../server/api/todo/dao/todo-dao";
import dbJson from "./db.json";
exports.setupMongoose = (mongoose) => {
mongoose.models = {};
mongoose.connect(dbJson.db.test.url);
mongoose.connection.on("error", () => {});
}
exports.createTodos = () => {
let _array = [];
for (let i = 0; i < 10; i++) {
_array.push({_id: "507c7f79bcf86cd7994f6c"+ (i + 10), todoMessage: "aaaaaaa"+i});
}
return Todo.create(_array);
}

View File

@@ -0,0 +1,7 @@
{
"db": {
"test": {
"url": "mongodb://localhost/happy-team_test"
}
}
}

View File

@@ -0,0 +1,129 @@
import mongoose from "mongoose";
import TodoDAO from "../../../../server/api/todo/dao/todo-dao";
import {expect} from "chai";
import {setupMongoose, createTodos} from "../../_helpers/db";
describe("todo.dao", () => {
before(() => {
setupMongoose(mongoose);
});
afterEach((done) => {
TodoDAO.remove({}, () => done());
})
describe("getAll", () => {
beforeEach((done) => {
createTodos()
.then(() => done())
.catch(() => done());
})
it("should get all todos", (done) => {
let _onSuccess = todos => {
expect(todos).to.be.defined;
expect(todos[0]).to.have.property("todoMessage").and.to.equal("aaaaaaa0");
expect(todos[0]).to.have.property("createdAt").and.to.be.defined;
done();
}
let _onError = (err) => {
expect(true).to.be.false; // should not come here
}
TodoDAO
.getAll()
.then(_onSuccess)
.catch(_onError);
})
})
describe("createTodo", () => {
it("should throw an error, object passed is not defined", (done) => {
let _undefinedTodo = undefined;
let _onSuccess = () => {
expect(true).to.be.false; // should not come here;
}
let _onError = error => {
expect(error).to.be.defined;
done();
}
TodoDAO
.createTodo(_undefinedTodo)
.then(_onSuccess)
.catch(_onError);
})
it("should create the todo correctly", (done) => {
let _todo = {todoMessage: "abc"};
let _onSuccess = todo => {
expect(todo).to.be.defined;
expect(todo.todoMessage).to.equal("abc");
expect(todo.createdAt).to.be.defined;
done();
}
let _onError = () => {
expect(true).to.be.false;
}
TodoDAO
.createTodo(_todo)
.then(_onSuccess)
.catch(_onError);
})
})
describe("deleteTodo", () => {
beforeEach((done) => {
createTodos()
.then(() => done())
.catch(() => done());
})
it("should get an error back, id is not defined", (done) => {
let _id = null;
let _onSuccess = () => {
expect(true).to.be.false;
}
let _onError = error => {
expect(error).to.be.defined;
done();
}
TodoDAO
.deleteTodo(_id)
.then(_onSuccess)
.catch(_onError);
})
it("should delete the doc successfully", (done) => {
let _id = "507c7f79bcf86cd7994f6c10";
let _onSuccess = () => {
expect(true).to.be.true;
done();
}
let _onError = () => {
expect(true).to.be.false;
}
TodoDAO
.deleteTodo(_id)
.then(_onSuccess)
.catch(_onError);
})
})
})

20
tsconfig.json Normal file
View File

@@ -0,0 +1,20 @@
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"target": "es5",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noImplicitAny": false
},
"exclude": [
"node_modules",
"typings"
],
"filesGlob": [
"**/*.ts",
"typings/main",
"typings/index.d.ts"
]
}

6
typings.json Normal file
View File

@@ -0,0 +1,6 @@
{
"globalDependencies": {
"es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654",
"jasmine": "registry:dt/jasmine#2.2.0+20160308082659"
}
}

7138
yarn.lock Normal file

File diff suppressed because it is too large Load Diff