Update for the final version of Angular2

It lost some functionality, but it was never put to use.
This commit is contained in:
Gergely Polonkai 2016-10-27 17:52:55 +02:00
parent bfcabd7925
commit 3e02eb4abb
24 changed files with 243 additions and 360 deletions

27
app/app-routing.module.ts Normal file
View File

@ -0,0 +1,27 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { DashboardComponent } from "./dashboard.component";
import { DucksComponent } from "./ducks.component";
const routes: Routes = [
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
},
{
path: 'dashboard',
component: DashboardComponent,
},
{
path: 'ducks',
component: DucksComponent
}
]
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}

View File

@ -1,7 +1,10 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
@Component({ @Component({
selector: "duckbook-front", moduleId: module.id,
templateUrl: "/app/app.component.html" selector: "duckbook-front-app",
templateUrl: "app.component.html"
}) })
export class AppComponent {} export class AppComponent {
title = "Rubber Duck Booking Tool";
}

View File

@ -1,37 +1,32 @@
import "./rxjs-extensions";
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser"; import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import { HttpModule } from "@angular/http"; import { HttpModule } from "@angular/http";
import { InMemoryWebApiModule } from "angular2-in-memory-web-api"; import { AppRoutingModule } from "./app-routing.module";
import { InMemoryWebApiModule } from "angular-in-memory-web-api";
import { InMemoryDataService } from "./in-memory-data.service"; import { InMemoryDataService } from "./in-memory-data.service";
import { routing } from "./app.routing";
import { AppComponent } from "./app.component"; import { AppComponent } from "./app.component";
import { DucksComponent } from "./ducks.component";
import { DuckDetailComponent } from "./duck-detail.component"; import { DuckDetailComponent } from "./duck-detail.component";
import { DashboardComponent } from "./dashboard.component"; import { DashboardComponent } from "./dashboard.component";
import { DuckSearchComponent } from "./duck-search.component"; import { DucksComponent } from "./ducks.component";
import { DuckService } from "./duck.service"; import { DuckService } from "./duck.service";
@NgModule({ @NgModule({
imports: [ imports: [
BrowserModule, BrowserModule,
FormsModule,
HttpModule, HttpModule,
InMemoryWebApiModule.forRoot(InMemoryDataService), InMemoryWebApiModule.forRoot(InMemoryDataService),
routing AppRoutingModule
], ],
declarations: [ declarations: [
AppComponent, AppComponent,
DucksComponent, DashboardComponent,
DuckDetailComponent, DuckDetailComponent,
DuckSearchComponent, DucksComponent
DashboardComponent
], ],
providers: [ DuckService ], providers: [ DuckService ],
bootstrap: [ AppComponent ] bootstrap: [ AppComponent ]

View File

@ -1,28 +0,0 @@
import { ModuleWithProviders } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { DucksComponent } from "./ducks.component";
import { DuckDetailComponent } from "./duck-detail.component";
import { DashboardComponent } from "./dashboard.component";
const appRoutes: Routes = [
{
path: "",
redirectTo: "/dashboard",
pathMatch: "full"
},
{
path: "dashboard",
component: DashboardComponent
},
{
path: "ducks",
component: DucksComponent
},
{
path: "detail/:id",
component: DuckDetailComponent
}
]
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

View File

@ -0,0 +1,11 @@
.duck-link .image {
background-color: black;
width: 64px;
height: 64px;
border-radius: 50%;
margin-right: 1em;
}
.duck-link .small {
margin-bottom: 0;
}

View File

@ -1,4 +1,10 @@
<div *ngFor="let duck of ducks" (click)="gotoDetail(duck)"> <h3>Duck Dashboard!</h3>
{{ duck.color }} <div class="list-group">
<a *ngFor="let duck of ducks"
class="list-group-item duck-link"
href="#">
<div class="image pull-left"></div>
{{ duck.name }}
<p class="clearfix small">Something.</p>
</a>
</div> </div>
<duck-search></duck-search>

View File

@ -1,27 +1,19 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { DuckService } from "./duck.service"; import { DuckService } from "./duck.service";
import { Duck } from "./models";
@Component({ @Component({
selector: "dashboard", selector: "dashboard",
templateUrl: "/app/dashboard.component.html" templateUrl :"app/dashboard.component.html",
styleUrls: ["app/dashboard.component.css"]
}) })
export class DashboardComponent implements OnInit { export class DashboardComponent implements OnInit {
ducks: Duck[] = []; ducks: Duck[] = [];
constructor(private router: Router, constructor(private duckService: DuckService) {}
private duckService: DuckService)
{}
ngOnInit(): void { ngOnInit(): void {
this.duckService.getDucks() this.duckService.getDucks()
.then(ducks => this.ducks = ducks.slice(1, 5)); .then(ducks => this.ducks = ducks);
}
gotoDetail(duck: Duck): void {
let link = ['/detail', duck.id];
this.router.navigate(link);
} }
} }

View File

@ -1,12 +1,3 @@
<div *ngIf="duck"> <div *ngIf="duck">
<div> <h2>{{ duck.name }}</h2>
<label>id: </label>
{{ duck.id }}
</div>
<div>
<label>color: </label>
<input [(ngModel)]="duck.color" placeholder="Color" />
</div>
<button (click)="save()">Save</button>
<button (click)="goBack()">Back</button>
</div> </div>

View File

@ -1,17 +1,22 @@
import { Component, Input, OnInit } from "@angular/core"; import { Component, OnInit} from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router"; import { ActivatedRoute, Params } from "@angular/router";
import { Location } from "@angular/common";
import { DuckService } from "./duck.service";
import { Duck } from "./models"; import { Duck } from "./models";
import { DuckService } from "./duck.service";
@Component({ @Component({
moduleId: module.id,
selector: "duck-detail", selector: "duck-detail",
templateUrl: "/app/duck-detail.component.html" templateUrl: "duck-detail.component.html"
}) })
export class DuckDetailComponent implements OnInit { export class DuckDetailComponent {
constructor(private duckService: DuckService, duck: Duck;
private route: ActivatedRoute)
constructor(
private duckService: DuckService,
private route: ActivatedRoute,
private location: Location)
{} {}
ngOnInit(): void { ngOnInit(): void {
@ -19,18 +24,6 @@ export class DuckDetailComponent implements OnInit {
let id = +params['id']; let id = +params['id'];
this.duckService.getDuck(id) this.duckService.getDuck(id)
.then(duck => this.duck = duck); .then(duck => this.duck = duck);
}); })
} }
goBack(): void {
window.history.back();
}
save(): void {
this.duckService.update(this.duck)
.then(this.goBack);
}
@Input()
duck: Duck;
} }

View File

@ -1,11 +0,0 @@
<div id="search-component">
<h4>Duck search</h4>
<input #searchBox id="search-box" (keyup)="search(searchBox.value)">
<div>
<div *ngFor="let duck of ducks | async"
(click)="gotoDetail(duck)"
class="search-result">
{{ duck.color }}
</div>
</div>
</div>

View File

@ -1,43 +0,0 @@
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { Observable } from "rxjs/Observable";
import { Subject } from "rxjs/Subject";
import { DuckSearchService } from "./duck-search.service";
import { Duck } from "./models";
@Component({
selector: "duck-search",
templateUrl: "/app/duck-search.component.html",
providers: [ DuckSearchService ]
})
export class DuckSearchComponent implements OnInit {
ducks: Observable<Duck[]>;
private searchTerm = new Subject<string>();
constructor(private duckSearchService: DuckSearchService,
private router: Router)
{}
search(term: string): void {
this.searchTerm.next(term);
}
ngOnInit(): void {
this.ducks = this.searchTerm
.debounceTime(300) // wait for 300ms pause in events
.distinctUntilChanged() // ignore if next search term is same as previous
.switchMap(term => term // switch to new observable each time
? this.duckSearchService.search(term)
: Observable.of<Duck[]>([]))
.catch(error => {
console.log(error);
return Observable.of<Duck[]>([]);
});
}
gotoDetail(duck: Duck): void {
let link = ['/detail', duck.id];
this.router.navigate(link);
}
}

View File

@ -1,15 +0,0 @@
import { Injectable } from "@angular/core";
import { Http, Response } from "@angular/http";
import { Observable } from "rxjs";
import { Duck } from "./models";
@Injectable()
export class DuckSearchService {
constructor (private http: Http) {}
search(term: string): Observable<Duck[]> {
return this.http.get(`app/ducks/?color=${term}`)
.map((r: Response) => r.json().data as Duck[]);
}
}

View File

@ -7,50 +7,33 @@ import { Duck } from "./models";
@Injectable() @Injectable()
export class DuckService { export class DuckService {
private ducksUrl = 'app/ducks';
private headers = new Headers({"Content-Type": "application/json"}); private headers = new Headers({"Content-Type": "application/json"});
private ducksUrl = 'app/ducks';
constructor(private http: Http) {} constructor(private http: Http) {}
getDucks(): Promise<Duck[]> {
return this.http.get(this.ducksUrl)
.toPromise()
.then(response => response.json().data as Duck[])
.catch(this.handleError);
}
getDuck(id: number): Promise<Duck> {
return this.getDucks()
.then(ducks => ducks.find(duck => duck.id === id));
}
create(name: string): Promise<Duck> {
return this.http.post(this.ducksUrl, JSON.stringify({name: name}), {headers: this.headers})
.toPromise()
.then(res => res.json().data)
.catch(this.handleError);
}
private handleError(error: any): Promise<any> { private handleError(error: any): Promise<any> {
console.error("An error occured", error); console.error("An error occured", error);
return Promise.reject(error.message || error); return Promise.reject(error.message || error);
} }
create(color: string): Promise<Duck> {
return this.http.post(this.ducksUrl, JSON.stringify({color: color}), {headers: this.headers})
.toPromise()
.then((res) => res.json().data)
.catch(this.handleError);
}
update(duck: Duck): Promise<Duck> {
const url = `${this.ducksUrl}/${duck.id}`;
return this.http.put(url, JSON.stringify(duck), {headers: this.headers})
.toPromise()
.then(() => duck)
.catch(this.handleError);
}
delete(id: number): Promise<void> {
let url = `${this.ducksUrl}/${id}`;
return this.http.delete(url, {headers: this.headers})
.toPromise()
.then(() => null)
.catch(this.handleError);
}
getDucks(): Promise<Duck[]> {
return this.http.get(this.ducksUrl)
.toPromise()
.then(response => response.json().data as Duck[])
.catch(this.handleError);
}
getDuck(id: number): Promise<Duck> {
return this.getDucks().then(ducks => ducks.find(duck => duck.id === id));
}
} }

View File

@ -1,17 +1,6 @@
<h1>Hello!</h1>
<ul> <ul>
<li *ngFor="let duck of ducks" (click)="onSelect(duck)"> <li *ngFor="let duck of ducks">
{{ duck.color }} <span class="badge">{{ duck.id }}</span>
<button (click)="delete(duck); $event.stopPropagation()">Delete</button> {{ duck.name }}
</li> </li>
</ul> </ul>
<div>
<label>Duck color:</label>
<input #duckColor>
<button (click)="add(duckColor.value); duckColor.value = ''">Add</button>
</div>
<div *ngIf="selectedDuck">
{{ selectedDuck.color }}
<button (click)="gotoDetail(selectedDuck)">Edit</button>
</div>

View File

@ -5,54 +5,42 @@ import { Duck } from "./models";
import { DuckService } from "./duck.service"; import { DuckService } from "./duck.service";
@Component({ @Component({
moduleId: module.id,
selector: "ducks", selector: "ducks",
templateUrl: "/app/ducks.component.html", templateUrl: "ducks.component.html"
providers: [ DuckService ]
}) })
export class DucksComponent implements OnInit { export class DucksComponent {
ducks = []; ducks: Duck[];
selectedDuck: Duck; selectedDuck: Duck;
constructor(private router: Router, constructor(private duckService: DuckService,
private duckService: DuckService) private router: Router)
{} {}
ngOnInit(): void { getDucks(): void
this.getDucks(); {
this.duckService
.getDucks()
.then(ducks => this.ducks = ducks);
} }
getDucks(): void { add(name: string): void {
this.duckService.getDucks().then(ducks => this.ducks = ducks); name = name.trim();
}
onSelect(duck: Duck): void { if (!name) { return; }
this.selectedDuck = duck;
}
gotoDetail(duck: Duck): void { this.duckService.create(name)
this.router.navigate(['/detail', duck.id]);
}
add(color: string): void {
// Make sure the color is not empty
color = color.trim();
if (!color) { return; }
this.duckService.create(color)
.then(duck => { .then(duck => {
this.ducks.push(duck); this.ducks.push(duck);
this.selectedDuck = null; this.selectedDuck = null;
}); });
} }
delete(duck: Duck): void { ngOnInit(): void {
this.duckService.delete(duck.id) this.getDucks();
.then(() => { }
this.ducks = this.ducks.filter(d => d !== duck);
if (this.selectedDuck === duck) { onSelect(duck: Duck): void {
this.selectedDuck = null; this.selectedDuck = duck;
}
});
} }
} }

View File

@ -1,11 +1,18 @@
import { InMemoryDbService } from "angular2-in-memory-web-api"; import { InMemoryDbService } from "angular-in-memory-web-api";
export class InMemoryDataService implements InMemoryDbService { export class InMemoryDataService implements InMemoryDbService {
createDb() { createDb() {
let ducks = [ let ducks = [
{ id: 1, color: 'yellow' }, {
{ id: 2, color: 'blue' }, id: 1,
{ id: 3, color: 'pink' } name: "Fastfingers",
color: "#ee6aa7"
},
{
id: 2,
name: "Lady Pickett",
color: "#8b8b00"
}
]; ];
return {ducks}; return {ducks};

View File

@ -1,4 +1,5 @@
export class Duck { export class Duck {
id: number; id: number;
name: string;
color: string; color: string;
} }

View File

@ -1,12 +0,0 @@
// Observable class extensions
import "rxjs/add/observable/of";
import "rxjs/add/observable/throw";
// Observable operators
import "rxjs/add/operator/catch";
import "rxjs/add/operator/debounceTime";
import "rxjs/add/operator/distinctUntilChanged";
import "rxjs/add/operator/do";
import "rxjs/add/operator/filter";
import "rxjs/add/operator/map";
import "rxjs/add/operator/switchMap";

View File

@ -1,29 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Rubber Duck Booking Tool</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script> <script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script> <script src="systemjs.config.js"></script>
<script> <script>
System.import('app').catch(function(err){ console.error(err); }); System.import('app').catch(function(err){ console.error(err); });
</script> </script>
</head> </head>
<!-- 3. Display the application -->
<body> <body>
<duckbook-front>Loading…</duckbook-front> <duckbook-front-app>Loading…</duckbook-front-app>
</body> </body>
</html> </html>

View File

@ -1,43 +1,48 @@
{ {
"name": "duck-booking-front", "name": "duck-booking-front",
"description": "Front-end for the Rubber Duck Booking Tool", "description": "Front-end for the Rubber Duck Booking Tool",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/gergelypolonkai/duckbook-front" "url": "https://github.com/gergelypolonkai/duck-booking-tool-front"
}, },
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ", "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
"lite": "lite-server", "lite": "lite-server",
"postinstall": "typings install", "tsc": "tsc",
"tsc": "tsc", "tsc:w": "tsc -w"
"tsc:w": "tsc -w", },
"typings": "typings" "licenses": [
}, {
"license": "ISC", "type": "MIT",
"dependencies": { "url": "https://github.com/angular/angular.io/blob/master/LICENSE"
"@angular/common": "2.0.0-rc.6", }
"@angular/compiler": "2.0.0-rc.6", ],
"@angular/compiler-cli": "0.6.0", "dependencies": {
"@angular/core": "2.0.0-rc.6", "@angular/common": "~2.1.1",
"@angular/forms": "2.0.0-rc.6", "@angular/compiler": "~2.1.1",
"@angular/http": "2.0.0-rc.6", "@angular/core": "~2.1.1",
"@angular/platform-browser": "2.0.0-rc.6", "@angular/forms": "~2.1.1",
"@angular/platform-browser-dynamic": "2.0.0-rc.6", "@angular/http": "~2.1.1",
"@angular/router": "3.0.0-rc.2", "@angular/platform-browser": "~2.1.1",
"@angular/upgrade": "2.0.0-rc.6", "@angular/platform-browser-dynamic": "~2.1.1",
"core-js": "^2.4.1", "@angular/router": "~3.1.1",
"reflect-metadata": "^0.1.3", "@angular/upgrade": "~2.1.1",
"rxjs": "5.0.0-beta.11",
"systemjs": "0.19.27", "angular-in-memory-web-api": "~0.1.13",
"zone.js": "^0.6.17", "bootstrap": "^3.3.7",
"angular2-in-memory-web-api": "0.0.18", "core-js": "^2.4.1",
"bootstrap": "^3.3.6" "ng2-bootstrap": "^1.1.16",
}, "reflect-metadata": "^0.1.8",
"devDependencies": { "rxjs": "5.0.0-beta.12",
"concurrently": "^2.2.0", "systemjs": "0.19.39",
"lite-server": "^2.2.2", "zone.js": "^0.6.25"
"typescript": "^1.8.10", },
"typings": "^1.3.2" "devDependencies": {
} "@types/core-js": "^0.9.34",
"@types/node": "^6.0.45",
"concurrently": "^3.0.0",
"lite-server": "^2.2.2",
"typescript": "^2.0.3"
}
} }

View File

@ -0,0 +1,14 @@
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}

View File

@ -1,43 +1,39 @@
/** /**
* System configuration for Angular 2 samples * System configuration for the Rubber Duck Booking Tool
* Adjust as necessary for your application needs.
*/ */
(function (global) { (function (global) {
System.config({ System.config({
paths: { paths: {
// paths serve as alias // paths serve as alias
'npm:': 'node_modules/' 'npm:': 'node_modules/'
}, },
// map tells the System loader where to look for things // map tells the System loader where to look for things
map: { map: {
// our app is within the app folder // our app is within the app folder
app: 'app', app: 'app',
// angular bundles // angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js', '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js', '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.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': '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/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js', '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js', '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
// other libraries // other libraries
'rxjs': 'npm:rxjs', 'rxjs': 'npm:rxjs',
'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api', 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
}, 'ng2-bootstrap/ng2-bootstrap': 'node_modules/ng2-bootstrap/bundles/ng2-bootstrap.umd.js"',
// packages tells the System loader how to load when no filename and/or no extension },
packages: { // packages tells the System loader how to load when no filename and/or no extension
app: { packages: {
main: './main.js', app: {
defaultExtension: 'js' main: './main.js',
}, defaultExtension: 'js'
rxjs: { },
defaultExtension: 'js' rxjs: {
}, defaultExtension: 'js'
'angular2-in-memory-web-api': { }
main: './index.js', }
defaultExtension: 'js' });
}
}
});
})(this); })(this);

View File

@ -1,12 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node", "moduleResolution": "node",
"sourceMap": true, "sourceMap": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"removeComments": false, "removeComments": false,
"noImplicitAny": false "noImplicitAny": false
} }
} }

View File

@ -1,7 +0,0 @@
{
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160725163759",
"jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
"node": "registry:dt/node#6.0.0+20160831021119"
}
}