├── .gitignore ├── LICENSE.md ├── README.md ├── bs-config.json ├── db.json ├── demo.gif ├── gulpfile.js ├── index.html ├── package.json ├── src ├── html │ ├── app.html │ ├── dashboard │ │ └── dashboard.html │ └── post │ │ └── post.html ├── scss │ ├── _dashboard.scss │ ├── _post.scss │ └── app.scss └── ts │ ├── app.component.ts │ ├── app.module.ts │ ├── dashboard │ └── components │ │ └── dashboard.component.ts │ ├── main.ts │ ├── post │ ├── components │ │ └── post.component.ts │ ├── models │ │ └── comment.ts │ └── services │ │ └── comment.service.ts │ ├── rxjs-extensions.ts │ └── shared │ ├── models │ └── post.ts │ └── services │ ├── logging.service.ts │ └── post.service.ts ├── system-config.js ├── tsconfig.json └── tslint.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea/ 3 | node_modules 4 | app 5 | npm-debug.log -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Maximilian Schwarzmüller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 BeyondScheme Discussion Portal 2 | 3 | ## Description 4 | This project is a discussion portal written in Angular 2 which periodically pulls data from backend to keep fresh data on UI without refreshing the page. 5 | 6 | It is derived from the official Angular 2 Documentation which can be found [here](https://angular.io/docs/ts/latest/tutorial/). 7 | 8 | Quick demo: 9 | 10 | 11 | 12 | ## Usage 13 | Follow the following steps. 14 | 15 | 0: Install npm, typescript and json server 16 | ``` 17 | npm install -g json-server 18 | ``` 19 | ``` 20 | npm install -g typescript 21 | ``` 22 | 1: Clone repo 23 | ``` 24 | git clone 25 | ``` 26 | 2: Install packages 27 | ``` 28 | npm install 29 | ``` 30 | 3: Start server (includes auto refreshing) and gulp watcher 31 | ``` 32 | npm start 33 | ``` 34 | 35 | # Port bindings 36 | Json-server is bind to port 3000, lite server to port 8000 (application is visible at this port) and BrowserSync (used by lite server) to port 8001. 37 | You can change lite server and BrowserSync ports in `bs-config.json`. Json-server port can be changed in `package.json` file by changing: 38 | 39 | `"start": "concurrent \"json-server --watch db.json\" \"npm run gulp\" \"npm run lite\" "` to: 40 | 41 | `"start": "concurrent \"json-server --watch db.json --port NEW_PORT\" \"npm run gulp\" \"npm run lite\" "` 42 | 43 | Please remember that when you change json-server port you have to fix urls in files: 44 | 45 | * [`comment.service.ts`](https://github.com/BeyondScheme/angular2-discussion-portal/blob/master/src/ts/post/services/comment.service.ts) 46 | * [`post.service.ts`](https://github.com/BeyondScheme/angular2-discussion-portal/blob/master/src/ts/shared/services/post.service.ts) 47 | 48 | # About Beyond Scheme 49 | 50 | Angular 2 discussion portal is maintained by [BeyondScheme.com](http://beyondscheme.com/?utm_source=github) 51 | 52 | Yet another software engineers, are we? 53 | We build web applications on a daily basis. 54 | 55 | See [what we do or hire us](http://beyondscheme.com/?utm_source=github) to help you with your product. -------------------------------------------------------------------------------- /bs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "ghostMode": false, 3 | "port": 8000, 4 | "ui": { 5 | "port": 8001 6 | } 7 | } -------------------------------------------------------------------------------- /db.json: -------------------------------------------------------------------------------- 1 | { 2 | "posts": [ 3 | { 4 | "title": "angular2 released!", 5 | "id": 2 6 | } 7 | ], 8 | "comments": [] 9 | } -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BeyondScheme/angular2-discussion-portal/e1532051998c5088b29e72f8969ba38f6f2fae9c/demo.gif -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var $ = require('gulp-load-plugins')({lazy: true}); 3 | var sass = require('gulp-sass'); 4 | 5 | var paths = { 6 | src: { 7 | ts: './src/ts/**/*.ts', 8 | scss: './src/scss/app.scss' 9 | }, 10 | dest: { 11 | js: './app/js', 12 | css: './app/css' 13 | } 14 | }; 15 | 16 | gulp.task("tslint", function () { 17 | gulp.src([paths.src.ts]) 18 | .pipe($.tslint({ 19 | formatter: "verbose" 20 | })) 21 | .pipe($.tslint.report()); 22 | }); 23 | 24 | gulp.task('build-ts', ["tslint", "build-scss"], function () { 25 | return gulp.src(paths.src.ts) 26 | .pipe($.sourcemaps.init()) 27 | .pipe($.typescript.createProject('tsconfig.json', { 28 | typescript: require('typescript') 29 | })()) 30 | .pipe($.sourcemaps.write()) 31 | .pipe($.inlineNg2Template()) 32 | .pipe(gulp.dest(paths.dest.js)); 33 | }); 34 | 35 | gulp.task('build-scss', function () { 36 | return gulp.src(paths.src.scss) 37 | .pipe(sass().on('error', sass.logError)) 38 | .pipe(gulp.dest(paths.dest.css)); 39 | }); 40 | 41 | gulp.task('watch', function () { 42 | gulp.watch(paths.src.ts, ['build-ts']); 43 | gulp.watch(paths.src.scss, ['build-scss']); 44 | }); 45 | 46 | gulp.task('default', ['watch', 'build-ts', 'build-scss']); 47 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular BeyondScheme 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | Loading... 25 | 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-BeyondScheme", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "lite": "lite-server", 6 | "gulp": "gulp", 7 | "json-server": "json-server", 8 | "start": "concurrent \"json-server --watch db.json\" \"npm run gulp\" \"npm run lite\" " 9 | }, 10 | "license": "ISC", 11 | "dependencies": { 12 | "@angular/common": "~2.2.0", 13 | "@angular/compiler": "~2.2.0", 14 | "@angular/core": "~2.2.0", 15 | "@angular/forms": "~2.2.0", 16 | "@angular/http": "~2.2.0", 17 | "@angular/platform-browser": "~2.2.0", 18 | "@angular/platform-browser-dynamic": "~2.2.0", 19 | "@angular/router": "~3.2.0", 20 | "@angular/upgrade": "~2.2.0", 21 | 22 | "systemjs": "0.19.39", 23 | "core-js": "^2.4.1", 24 | "reflect-metadata": "^0.1.8", 25 | "rxjs": "5.0.0-beta.12", 26 | "zone.js": "^0.6.25" 27 | }, 28 | "devDependencies": { 29 | "concurrently": "^2.0.0", 30 | "gulp": "^3.9.0", 31 | "gulp-inline-ng2-template": "^4.0.0", 32 | "gulp-load-plugins": "1.4.0", 33 | "gulp-sourcemaps": "^2.2.0", 34 | "gulp-sass": "2.3.2", 35 | "gulp-tslint": "6.1.2", 36 | "gulp-typescript": "^3.1.3", 37 | "lite-server": "^2.1.0", 38 | "tslint": "^3.7.3", 39 | "typescript": "^2.0.10", 40 | 41 | "@types/core-js": "^0.9.34", 42 | "@types/node": "^6.0.46" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/html/app.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/html/dashboard/dashboard.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
6 |

Posts

7 |
8 |
9 |
10 |

{{post.title}}

11 | 12 |
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /src/html/post/post.html: -------------------------------------------------------------------------------- 1 |
2 |

{{post.title}}

3 |
4 | 5 | 6 |
7 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/scss/_dashboard.scss: -------------------------------------------------------------------------------- 1 | *, *:after, *:before { 2 | -webkit-box-sizing: border-box; 3 | -moz-box-sizing: border-box; 4 | box-sizing: border-box; 5 | } 6 | 7 | [class*='col-'] { 8 | float: left; 9 | padding-right: 20px; 10 | padding-bottom: 20px; 11 | } 12 | 13 | [class*='col-']:last-of-type { 14 | padding-right: 0; 15 | } 16 | 17 | .grid { 18 | margin: 0; 19 | display: inline-block; 20 | } 21 | 22 | .module { 23 | position: relative; 24 | padding: 20px; 25 | text-align: center; 26 | color: #eee; 27 | max-height: 120px; 28 | min-width: 120px; 29 | background-color: #607D8B; 30 | background-color: rgb(0, 120, 215); 31 | border-radius: 2px; 32 | } 33 | 34 | .module:hover { 35 | background-color: #EEE; 36 | background-color: #CCC; 37 | cursor: pointer; 38 | color: #607d8b; 39 | } 40 | 41 | #add-new-post { 42 | margin-top: 20px; 43 | } 44 | 45 | #add-new-post input { 46 | width: 400px; 47 | } 48 | 49 | button.delete-button { 50 | position: absolute; 51 | top: 0; 52 | right: 0; 53 | background-color: gray !important; 54 | color: white; 55 | } -------------------------------------------------------------------------------- /src/scss/_post.scss: -------------------------------------------------------------------------------- 1 | #add-button { 2 | vertical-align: text-bottom; 3 | } 4 | 5 | .comments { 6 | list-style-type: none; 7 | padding: 0; 8 | } 9 | 10 | .comments li { 11 | position: relative; 12 | left: 0; 13 | background-color: #e4f0f3; 14 | margin: .5em .5em .5em 0; 15 | padding: .3em 0; 16 | height: 1.6em; 17 | border-radius: 4px; 18 | } 19 | 20 | .comments .text { 21 | position: relative; 22 | top: -3px; 23 | } 24 | 25 | button.delete-button{ 26 | float:right; 27 | background-color: gray !important; 28 | background-color: rgb(216,59,1) !important; 29 | color:white; 30 | } 31 | -------------------------------------------------------------------------------- /src/scss/app.scss: -------------------------------------------------------------------------------- 1 | @import "_dashboard.scss"; 2 | @import "_post.scss"; 3 | 4 | body { 5 | margin: 32px; 6 | font-family: "Roboto", Arial, sans-serif; 7 | } 8 | nav a { 9 | padding: 5px 10px; 10 | text-decoration: none; 11 | margin-top: 10px; 12 | display: inline-block; 13 | background-color: #eee; 14 | border-radius: 5px; 15 | } 16 | 17 | nav a:visited, a:link { 18 | color: #607D8B; 19 | } 20 | 21 | nav a:hover { 22 | color: #039be5; 23 | background-color: #CFD8DC; 24 | } 25 | 26 | nav a.active { 27 | color: #039be5; 28 | } 29 | 30 | button { 31 | font-family: Arial; 32 | background-color: #eee; 33 | border: none; 34 | padding: 5px 10px; 35 | border-radius: 4px; 36 | cursor: pointer; 37 | cursor: hand; 38 | } 39 | 40 | button:hover { 41 | background-color: #cfd8dc; 42 | } -------------------------------------------------------------------------------- /src/ts/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from "@angular/core"; 2 | 3 | @Component({ 4 | selector: "my-app", 5 | templateUrl: "/src/html/app.html", 6 | }) 7 | export class AppComponent { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/ts/app.module.ts: -------------------------------------------------------------------------------- 1 | import {AppComponent} from "./app.component"; 2 | import {DashboardComponent} from "./dashboard/components/dashboard.component"; 3 | import {PostComponent} from "./post/components/post.component"; 4 | import "./rxjs-extensions"; 5 | import {LoggingService} from "./shared/services/logging.service"; 6 | import {PostService} from "./shared/services/post.service"; 7 | import {NgModule} from "@angular/core"; 8 | import {FormsModule} from "@angular/forms"; 9 | import {HttpModule} from "@angular/http"; 10 | import {BrowserModule} from "@angular/platform-browser"; 11 | import {RouterModule, Routes} from "@angular/router"; 12 | 13 | const routes: Routes = [ 14 | { 15 | path: "", 16 | pathMatch: "full", 17 | redirectTo: "/dashboard", 18 | }, 19 | { 20 | component: DashboardComponent, 21 | path: "dashboard", 22 | }, 23 | { 24 | component: PostComponent, 25 | path: "post/:id", 26 | }, 27 | ]; 28 | export const routedComponents = [DashboardComponent, PostComponent]; 29 | 30 | @NgModule({ 31 | bootstrap: [AppComponent], 32 | declarations: [AppComponent, routedComponents], 33 | imports: [BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(routes)], 34 | providers: [PostService, LoggingService], 35 | }) 36 | export class AppModule { 37 | } 38 | -------------------------------------------------------------------------------- /src/ts/dashboard/components/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import {Post} from "../../shared/models/post"; 2 | import {PostService} from "../../shared/services/post.service"; 3 | import {Component, OnDestroy, OnInit} from "@angular/core"; 4 | import {Observable} from "rxjs/Observable"; 5 | import {AnonymousSubscription} from "rxjs/Subscription"; 6 | 7 | @Component({ 8 | selector: "dashboard", 9 | templateUrl: "/src/html/dashboard/dashboard.html", 10 | }) 11 | export class DashboardComponent implements OnInit, OnDestroy { 12 | 13 | private timerSubscription: AnonymousSubscription; 14 | private postsSubscription: AnonymousSubscription; 15 | private posts: Post[]; 16 | private post: Post; 17 | 18 | constructor(private postService: PostService) { 19 | this.post = new Post(); 20 | } 21 | 22 | public ngOnInit(): void { 23 | this.refreshData(); 24 | } 25 | 26 | public ngOnDestroy(): void { 27 | if (this.postsSubscription) { 28 | this.postsSubscription.unsubscribe(); 29 | } 30 | if (this.timerSubscription) { 31 | this.timerSubscription.unsubscribe(); 32 | } 33 | } 34 | 35 | public save(): void { 36 | this.postService 37 | .save(this.post) 38 | .subscribe(post => { 39 | this.posts.unshift(post); 40 | this.post = new Post(); 41 | }); 42 | } 43 | 44 | public deletePost(postToDelete: Post, event: any): void { 45 | event.stopPropagation(); 46 | this.postService.delete(postToDelete).subscribe(() => { 47 | this.posts = this.posts.filter((post: Post) => post.id !== postToDelete.id); 48 | }); 49 | } 50 | 51 | private refreshData(): void { 52 | this.postsSubscription = this.postService.getPosts().subscribe(posts => { 53 | this.posts = posts; 54 | this.subscribeToData(); 55 | }); 56 | } 57 | 58 | private subscribeToData(): void { 59 | this.timerSubscription = Observable.timer(5000).first().subscribe(() => this.refreshData()); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/ts/main.ts: -------------------------------------------------------------------------------- 1 | import {AppModule} from "./app.module"; 2 | import {platformBrowserDynamic} from "@angular/platform-browser-dynamic"; 3 | 4 | platformBrowserDynamic().bootstrapModule(AppModule); 5 | -------------------------------------------------------------------------------- /src/ts/post/components/post.component.ts: -------------------------------------------------------------------------------- 1 | import {Post} from "../../shared/models/post"; 2 | import {PostService} from "../../shared/services/post.service"; 3 | import {Comment} from "../models/comment"; 4 | import {CommentService} from "../services/comment.service"; 5 | import {Component, OnDestroy, OnInit} from "@angular/core"; 6 | import {ActivatedRoute, Params, Router} from "@angular/router"; 7 | import {Observable} from "rxjs/Observable"; 8 | import {AnonymousSubscription} from "rxjs/Subscription"; 9 | 10 | @Component({ 11 | providers: [CommentService], 12 | selector: "bid", 13 | templateUrl: "src/html/post/post.html", 14 | }) 15 | export class PostComponent implements OnInit, OnDestroy { 16 | 17 | private static ID_ROUTE_PARAM: string = "id"; 18 | private timerSubscription: AnonymousSubscription; 19 | private commentsSubscription: AnonymousSubscription; 20 | private post: Post; 21 | private comments: Comment[]; 22 | private comment: Comment; 23 | 24 | constructor(private postService: PostService, private commentService: CommentService, 25 | private route: ActivatedRoute, private router: Router) { 26 | } 27 | 28 | public ngOnInit(): void { 29 | this.comment = new Comment(); 30 | this.route.params.forEach((params: Params) => { 31 | if (params[PostComponent.ID_ROUTE_PARAM] !== undefined) { 32 | let id: number = +params[PostComponent.ID_ROUTE_PARAM]; 33 | this.postService.getPost(id).subscribe(post => { 34 | this.post = post; 35 | this.comment = new Comment(); 36 | this.comment.postId = this.post.id; 37 | this.refreshData(); 38 | }); 39 | } else { 40 | this.router.navigate(["/dashboard"]); 41 | } 42 | }); 43 | } 44 | 45 | public ngOnDestroy(): void { 46 | if (this.commentsSubscription) { 47 | this.commentsSubscription.unsubscribe(); 48 | } 49 | if (this.timerSubscription) { 50 | this.timerSubscription.unsubscribe(); 51 | } 52 | } 53 | 54 | public save(): void { 55 | this.commentService 56 | .save(this.comment) 57 | .subscribe(comment => { 58 | this.comments.unshift(comment); 59 | this.comment = new Comment(); 60 | this.comment.postId = this.post.id; 61 | }); 62 | } 63 | 64 | public deleteComment(comment: Comment, event: any): void { 65 | event.stopPropagation(); 66 | this.commentService 67 | .delete(comment) 68 | .subscribe(() => { 69 | this.comments = this.comments.filter((returnableObjects: Comment) => { 70 | return returnableObjects.id !== comment.id; 71 | }); 72 | }); 73 | } 74 | 75 | private refreshData(): void { 76 | this.commentsSubscription = this.commentService.getComments(this.post.id).subscribe(comments => { 77 | this.comments = comments; 78 | this.subscribeToData(); 79 | }); 80 | } 81 | 82 | private subscribeToData(): void { 83 | this.timerSubscription = Observable.timer(5000).first().subscribe(() => this.refreshData()); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/ts/post/models/comment.ts: -------------------------------------------------------------------------------- 1 | export class Comment { 2 | public id: number; 3 | public postId: number; 4 | public content: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/ts/post/services/comment.service.ts: -------------------------------------------------------------------------------- 1 | import {LoggingService} from "../../shared/services/logging.service"; 2 | import {Comment} from "../models/comment"; 3 | import {Injectable} from "@angular/core"; 4 | import {Headers, Http, Response} from "@angular/http"; 5 | import {Observable} from "rxjs/Observable"; 6 | 7 | @Injectable() 8 | export class CommentService { 9 | private postsUrl = "http://localhost:3000/posts/"; 10 | private commentsUrl = "http://localhost:3000/comments/"; 11 | 12 | constructor(private http: Http, private loggingService: LoggingService) { 13 | } 14 | 15 | public getComments(postId: number): Observable { 16 | return this.http.get(this.postsUrl + postId + "/comments?_sort=id&_order=DESC") 17 | .map(res => res.json()) 18 | .catch(this.loggingService.handleError); 19 | } 20 | 21 | public save(comment: Comment): Observable { 22 | let headers = new Headers({ 23 | "Content-Type": "application/json", 24 | }); 25 | 26 | return this.http 27 | .post(this.postsUrl + comment.postId + "/comments", JSON.stringify(comment), {headers}) 28 | .map(res => res.json()) 29 | .catch(this.loggingService.handleError); 30 | } 31 | 32 | public delete(comment: Comment): Observable { 33 | let headers = new Headers(); 34 | headers.append("Content-Type", "application/json"); 35 | 36 | return this.http 37 | .delete(this.commentsUrl + comment.id, {headers}) 38 | .map(res => res.json()) 39 | .catch(this.loggingService.handleError); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ts/rxjs-extensions.ts: -------------------------------------------------------------------------------- 1 | // Observable class extensions 2 | import "rxjs/add/observable/of"; 3 | import "rxjs/add/observable/throw"; 4 | import "rxjs/add/observable/timer"; 5 | 6 | // Observable operators 7 | import "rxjs/add/operator/catch"; 8 | import "rxjs/add/operator/debounceTime"; 9 | import "rxjs/add/operator/distinctUntilChanged"; 10 | import "rxjs/add/operator/do"; 11 | import "rxjs/add/operator/filter"; 12 | import "rxjs/add/operator/first"; 13 | import "rxjs/add/operator/map"; 14 | import "rxjs/add/operator/switchMap"; 15 | -------------------------------------------------------------------------------- /src/ts/shared/models/post.ts: -------------------------------------------------------------------------------- 1 | export class Post { 2 | public id: number; 3 | public title: String; 4 | } 5 | -------------------------------------------------------------------------------- /src/ts/shared/services/logging.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from "@angular/core"; 2 | import {Observable} from "rxjs/Observable"; 3 | 4 | @Injectable() 5 | export class LoggingService { 6 | 7 | public handleError(error: any) { 8 | let errMsg = (error.message) ? error.message : 9 | error.status ? `${error.status} - ${error.statusText}` : "Server error"; 10 | console.error(errMsg); 11 | return Observable.throw(errMsg); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/ts/shared/services/post.service.ts: -------------------------------------------------------------------------------- 1 | import {Post} from "../models/post"; 2 | import {LoggingService} from "./logging.service"; 3 | import {Injectable} from "@angular/core"; 4 | import {Headers, Http, Response} from "@angular/http"; 5 | import {Observable} from "rxjs/Observable"; 6 | 7 | @Injectable() 8 | export class PostService { 9 | private postsUrl = "http://localhost:3000/posts/"; 10 | 11 | constructor(private http: Http, private loggingService: LoggingService) { 12 | } 13 | 14 | public getPosts(): Observable { 15 | return this.http.get(this.postsUrl + "?_sort=id&_order=DESC") 16 | .map(res => res.json()) 17 | .catch(this.loggingService.handleError); 18 | } 19 | 20 | public getPost(id: number): Observable { 21 | return this.http.get(this.postsUrl + id) 22 | .map(res => res.json()) 23 | .catch(this.loggingService.handleError); 24 | } 25 | 26 | public save(post: Post): Observable { 27 | let headers = new Headers({ 28 | "Content-Type": "application/json", 29 | }); 30 | 31 | return this.http 32 | .post(this.postsUrl, JSON.stringify(post), {headers}) 33 | .map(res => res.json()) 34 | .catch(this.loggingService.handleError); 35 | } 36 | 37 | public delete(post: Post): Observable { 38 | let headers = new Headers(); 39 | headers.append("Content-Type", "application/json"); 40 | 41 | return this.http 42 | .delete(this.postsUrl + post.id, {headers}) 43 | .map(res => res.json()) 44 | .catch(this.loggingService.handleError); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /system-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': 'node_modules/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | // our app is within the app folder 14 | app: 'app/js', 15 | 16 | // angular bundles 17 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 18 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 19 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 20 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 21 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 22 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 23 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 24 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 25 | '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', 26 | 27 | // other libraries 28 | 'rxjs': 'npm:rxjs' 29 | }, 30 | 31 | // packages tells the System loader how to load when no filename and/or no extension 32 | packages: { 33 | app: { 34 | main: './main.js', 35 | defaultExtension: 'js' 36 | }, 37 | api: {defaultExtension: 'js'}, 38 | rxjs: { 39 | defaultExtension: 'js' 40 | }, 41 | } 42 | }); 43 | })(this); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES5", 4 | "module": "system", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "removeComments": false, 10 | "noImplicitAny": false, 11 | "outDir": "app/js" 12 | }, 13 | "exclude": [ 14 | "node_modules" 15 | ] 16 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:latest", 3 | "rules": { 4 | } 5 | } --------------------------------------------------------------------------------