done state

This commit is contained in:
Märt Kalmo 2017-04-29 11:26:20 +03:00
commit cec00f891c
19 changed files with 308 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
node_modules
/build
/.settings
/.classpath
/.project
/.idea
*.iml
*.log

7
app/app.cmp.ts Normal file
View File

@ -0,0 +1,7 @@
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: 'app/app.html'
})
export class AppComponent {}

1
app/app.html Normal file
View File

@ -0,0 +1 @@
<router-outlet></router-outlet>

22
app/app.module.ts Normal file
View File

@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.cmp';
import { RouterModule } from "@angular/router";
import { routes } from "./routes";
import { ListComponent } from "./list/list.cmp";
import { ViewComponent } from "./view/view.cmp";
import { TaskService } from "./task.srv";
@NgModule({
imports: [
BrowserModule,
HttpModule, FormsModule,
RouterModule.forRoot(routes, { useHash: true }) ],
declarations: [ AppComponent, ListComponent, ViewComponent ],
providers: [ TaskService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

37
app/list/list.cmp.ts Normal file
View File

@ -0,0 +1,37 @@
import { Component, OnInit } from '@angular/core';
import { Task, TaskService } from '../task.srv';
@Component({
selector: 'list',
templateUrl: 'app/list/list.html',
styleUrls: ['app/list/list.css']
})
export class ListComponent implements OnInit {
tasks: Task[] = [];
newTaskTitle: string;
constructor(private taskService: TaskService) {}
private updateTasks(): void {
this.taskService.getTasks().then(tasks => this.tasks = tasks);
}
addNewTask(): void {
this.taskService.saveTask(new Task(this.newTaskTitle))
.then(() => {
this.updateTasks();
this.newTaskTitle = '';
});
}
deleteTask(taskId : number): void {
this.taskService.deleteTask(taskId)
.then(() => this.updateTasks());
}
ngOnInit(): void {
this.updateTasks();
}
}

3
app/list/list.css Normal file
View File

@ -0,0 +1,3 @@
.done {
text-decoration: line-through;
}

10
app/list/list.html Normal file
View File

@ -0,0 +1,10 @@
<input [(ngModel)]="newTaskTitle"/>
<button (click)="addNewTask()">Lisa ülesanne</button ><br><br>
<div *ngFor='let task of tasks'>
<a [class]="task.done ? 'done' : ''" routerLink="/view/{{ task._id }}">{{ task.title }}</a>
<input type="checkbox" [(ngModel)]="task.done"/>
<button (click)="deleteTask(task._id)">X</button>
</div>

9
app/main.ts Normal file
View File

@ -0,0 +1,9 @@
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

3
app/polyfills.ts Normal file
View File

@ -0,0 +1,3 @@
import 'core-js/es6';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';

10
app/routes.ts Normal file
View File

@ -0,0 +1,10 @@
import { Routes } from '@angular/router';
import { ListComponent } from './list/list.cmp';
import { ViewComponent } from './view/view.cmp';
export const routes: Routes = [
{ path: 'list', component: ListComponent },
{ path: 'view/:id', component: ViewComponent },
{ path: '', redirectTo: 'list', pathMatch: 'full' }
];

46
app/task.srv.ts Normal file
View File

@ -0,0 +1,46 @@
import { Http, Response } from "@angular/http";
import { Injectable } from "@angular/core";
export class Task {
added: Date;
_id: number;
done: boolean = false;
constructor(public title : string) {
this.added = new Date();
};
}
@Injectable()
export class TaskService {
constructor(private http: Http) {}
getTasks(): Promise<Task[]> {
return this.http
.get('api/tasks')
.toPromise()
.then((response: Response) => response.json());
}
getTask(id: number): Promise<Task> {
return this.http
.get('api/tasks/' + id)
.toPromise()
.then((response: Response) => response.json());
}
saveTask(task: Task): Promise<void> {
return this.http
.post('api/tasks', task)
.toPromise()
.then(() => <void>null);
}
deleteTask(id: number): Promise<void> {
return this.http
.delete('api/tasks/' + id)
.toPromise()
.then(() => <void>null);
}
}

26
app/view/view.cmp.ts Normal file
View File

@ -0,0 +1,26 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'
import { Task, TaskService } from '../task.srv';
@Component({
templateUrl: 'app/view/view.html'
})
export class ViewComponent implements OnInit {
task: Task;
constructor(private route: ActivatedRoute,
private router: Router,
private taskService: TaskService) {}
back() {
this.router.navigateByUrl('/list');
}
ngOnInit(): void {
const id = parseInt(this.route.snapshot.paramMap.get('id'));
this.taskService.getTask(id).then(task => this.task = task);
}
}

5
app/view/view.html Normal file
View File

@ -0,0 +1,5 @@
Title: {{ task?.title }}<br>
Added: {{ task?.added | date: 'dd-MM-yyyy hh:mm' }}<br><br>
<button (click)="back()">Back</button>

14
data/db.json Normal file
View File

@ -0,0 +1,14 @@
{
"tasks": [
{
"title": "Call Jill",
"added": "2017-03-13T09:46:46.127Z",
"_id": 1
},
{
"title": "Write to John",
"added": "2017-03-13T10:09:38.867Z",
"_id": 2
}
]
}

3
data/routes.json Normal file
View File

@ -0,0 +1,3 @@
{
"/api/": "/"
}

18
index.html Normal file
View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>i399exng2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<my-app></my-app>
<script src="/build/polyfills.js"></script>
<script src="/build/app.js"></script>
</body>
</html>

31
package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "i399exng2",
"version": "1.0.0",
"scripts": {
"serve": "webpack-dev-server --port 3001",
"build": "webpack -p",
"back-end": "json-server ./data/db.json --static ./ --id _id --port 3000 --routes ./data/routes.json"
},
"dependencies": {
"@angular/common": "^4.0.2",
"@angular/compiler": "^4.0.2",
"@angular/compiler-cli": "^4.0.2",
"@angular/core": "^4.0.2",
"@angular/forms": "^4.0.2",
"@angular/http": "^4.0.2",
"@angular/platform-browser": "^4.0.2",
"@angular/platform-browser-dynamic": "^4.0.2",
"@angular/platform-server": "^4.0.2",
"@angular/router": "^4.0.2",
"core-js": "^2.4.1",
"rxjs": "^5.3.0",
"zone.js": "^0.8.5"
},
"devDependencies": {
"awesome-typescript-loader": "^3.1.2",
"typescript": "^2.2.2",
"webpack": "^2.3.3",
"webpack-dev-server": "^2.4.2",
"json-server": "^0.8.22"
}
}

14
tsconfig.json Normal file
View File

@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"sourceMap": false,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": false,
"suppressImplicitAnyIndexErrors": true
}
}

39
webpack.config.js Normal file
View File

@ -0,0 +1,39 @@
var path = require('path');
module.exports = {
entry: {
polyfills: './app/polyfills.ts',
app: './app/main.ts'
},
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/build/',
filename: '[name].js'
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}
],
exprContextCritical: false
},
resolve: {
extensions: ['.js', '.ts']
},
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
secure: false
}
}
}
};