diff --git a/.gitignore b/.gitignore
index 463f60b..a2d37fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ typings
app/**/*.js
app/**/*.js.map
npm-debug.log*
-.DS_store
\ No newline at end of file
+.DS_store
+.idea
\ No newline at end of file
diff --git a/README.md b/README.md
index 471bece..ec181ea 100644
--- a/README.md
+++ b/README.md
@@ -1,51 +1,4 @@
-# Angular 2 Essential Training
+# UPDATE
+The repository for the **Angular Essential Training** course can be found at https://github.com/coursefiles/angular2-essential-training.
-This is the repository for my course, [Angular 2 Essential Training](https://www.lynda.com/AngularJS-tutorials/AngularJS-2-Essential-Training/422834-2.html).
-The full course is available at [lynda.com](https://lynda.com).
-
-## Course Description
-
-JavaScript frameworks help you code more quickly, by providing special functionality for developing specific types of web projects. Angular was designed by Google to address challenges programmers face building single-page applications. This course introduces you to the essentials of this "superheroic" framework, including declarative templates, two-way data binding, and dependency injection. Justin Schwartzenberger steps through the framework one feature at a time, focusing on the new component-based architecture of Angular 2. After completing this training, you'll be able to tackle the other project-based courses in our library and create your own Angular app.
-
-Topics include:
-- What is Angular?
-- Setting up an Angular template
-- Creating a component
-- Displaying data
-- Working with events
-- Using two-way data binding
-- Creating a subcomponent
-- Using the built-in HTTP module
-- Using the built-in router module
-
-## Instructions
-
-1. Make sure you have these installed
- - [node.js](http://nodejs.org/)
- - [git](http://git-scm.com/)
-
-2. Clone this repository into your local machine using the terminal (mac) or Gitbash (PC)
-
- `git clone https://github.com/LyndaExerciseFiles/angular2-essential-training.git`
-
-3. CD to the folder
-
- `cd angular2-essential-training`
-
-4. Run the following to install the project dependencies:
-
- `npm install`
-
-5. Run the npm start command to build the code, watch for file changes, and serve up the site locally:
-
- `npm start`
-
-Note that the site will run using `lite-server` and will be served up at the following local address:
- http://localhost:3000
-
-*If you use a code editor that launches its own web server please note that it may run on a different port number.
-You will want to use `npm start` for this project.*
-
-## More Stuff
-Check out some of my [other courses on lynda.com](https://lynda.com/justinschwartzenberger).
-You can also [follow me on twitter](https://twitter.com/schwarty), or read [my blog](http://schwarty.com).
\ No newline at end of file
+*This is the old location of the code and is no longer being maintained*
diff --git a/app/app.component.css b/app/app.component.css
new file mode 100755
index 0000000..779f65e
--- /dev/null
+++ b/app/app.component.css
@@ -0,0 +1,30 @@
+:host {
+ display: flex;
+ font-family: Arial, Helvetica, sans-serif;
+ min-height: 100%;
+}
+nav {
+ display: flex;
+ flex-direction: column;
+ width: 68px;
+ background-color: #53ace4;
+}
+nav .icon {
+ width: 48px;
+ height: 48px;
+ margin: 10px;
+}
+section {
+ width: 100%;
+ background-color: #32435b;
+}
+section > header {
+ color: #ffffff;
+ padding: 10px;
+}
+section > header > h1 {
+ font-size: 2em;
+}
+section > header .description {
+ font-style: italic;
+}
\ No newline at end of file
diff --git a/app/app.component.html b/app/app.component.html
new file mode 100755
index 0000000..cbf7b49
--- /dev/null
+++ b/app/app.component.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/app.component.ts b/app/app.component.ts
old mode 100644
new mode 100755
index e69de29..ba31e20
--- a/app/app.component.ts
+++ b/app/app.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'mw-app',
+ templateUrl: 'app/app.component.html',
+ styleUrls: ['app/app.component.css']
+})
+export class AppComponent { }
diff --git a/app/app.module.ts b/app/app.module.ts
new file mode 100644
index 0000000..ce3feab
--- /dev/null
+++ b/app/app.module.ts
@@ -0,0 +1,41 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { ReactiveFormsModule } from '@angular/forms';
+import { HttpModule, XHRBackend } from '@angular/http';
+
+import { AppComponent } from './app.component';
+import { MediaItemComponent } from './media-item.component';
+import { MediaItemListComponent } from './media-item-list.component';
+import { FavoriteDirective } from './favorite.directive';
+import { CategoryListPipe } from './category-list.pipe';
+import { MediaItemFormComponent } from './media-item-form.component';
+import { MediaItemService } from './media-item.service';
+import { lookupListToken, lookupLists } from './providers';
+import { MockXHRBackend } from './mock-xhr-backend';
+import { routing } from './app.routing';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ ReactiveFormsModule,
+ HttpModule,
+ routing
+ ],
+ declarations: [
+ AppComponent,
+ MediaItemComponent,
+ MediaItemListComponent,
+ FavoriteDirective,
+ CategoryListPipe,
+ MediaItemFormComponent
+ ],
+ providers: [
+ MediaItemService,
+ { provide: lookupListToken, useValue: lookupLists },
+ { provide: XHRBackend, useClass: MockXHRBackend }
+ ],
+ bootstrap: [
+ AppComponent
+ ]
+})
+export class AppModule {}
\ No newline at end of file
diff --git a/app/app.routing.ts b/app/app.routing.ts
new file mode 100644
index 0000000..828565c
--- /dev/null
+++ b/app/app.routing.ts
@@ -0,0 +1,12 @@
+import { Routes, RouterModule } from '@angular/router';
+
+import { MediaItemFormComponent } from './media-item-form.component';
+import { MediaItemListComponent } from './media-item-list.component';
+
+const appRoutes: Routes = [
+ { path: 'add', component: MediaItemFormComponent },
+ { path: ':medium', component: MediaItemListComponent },
+ { path: '', pathMatch: 'full', redirectTo: 'all' }
+];
+
+export const routing = RouterModule.forRoot(appRoutes);
diff --git a/app/category-list.pipe.ts b/app/category-list.pipe.ts
new file mode 100755
index 0000000..1e3b9a1
--- /dev/null
+++ b/app/category-list.pipe.ts
@@ -0,0 +1,16 @@
+import { Pipe } from '@angular/core';
+
+@Pipe({
+ name: 'categoryList'
+})
+export class CategoryListPipe {
+ transform(mediaItems) {
+ var categories = [];
+ mediaItems.forEach(mediaItem => {
+ if (categories.indexOf(mediaItem.category) <= -1) {
+ categories.push(mediaItem.category);
+ }
+ });
+ return categories.join(', ');
+ }
+}
\ No newline at end of file
diff --git a/app/favorite.directive.ts b/app/favorite.directive.ts
new file mode 100755
index 0000000..d186912
--- /dev/null
+++ b/app/favorite.directive.ts
@@ -0,0 +1,22 @@
+import { Directive, HostBinding, HostListener, Input } from '@angular/core';
+
+@Directive({
+ selector: '[mwFavorite]'
+})
+export class FavoriteDirective {
+ @HostBinding('class.is-favorite') isFavorite = true;
+
+ @HostBinding('class.is-favorite-hovering') hovering = false;
+
+ @HostListener('mouseenter') onMouseEnter() {
+ this.hovering = true;
+ }
+
+ @HostListener('mouseleave') onMouseLeave() {
+ this.hovering = false;
+ }
+
+ @Input() set mwFavorite(value) {
+ this.isFavorite = value;
+ }
+}
diff --git a/app/main.ts b/app/main.ts
old mode 100644
new mode 100755
index e69de29..7cc80b5
--- a/app/main.ts
+++ b/app/main.ts
@@ -0,0 +1,4 @@
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+import { AppModule } from './app.module';
+
+platformBrowserDynamic().bootstrapModule(AppModule);
diff --git a/app/media-item-form.component.css b/app/media-item-form.component.css
new file mode 100755
index 0000000..32da063
--- /dev/null
+++ b/app/media-item-form.component.css
@@ -0,0 +1,52 @@
+:host {
+ display: block;
+ padding: 10px;
+}
+ul {
+ list-style-type: none;
+}
+ul li {
+ margin: 10px 0;
+}
+header, label {
+ color: #53ace4;
+}
+input, select {
+ background-color: #29394b;
+ color: #c6c5c3;
+ border-radius: 3px;
+ border: none;
+ box-shadow: 0 1px 2px rgba(0,0,0,0.2) inset, 0 -1px 0 rgba(0,0,0,0.05) inset;
+ border-color: #53ace4;
+ padding: 6px;
+}
+.ng-invalid:not(form):not(.ng-pristine):not(.required-invalid) {
+ border: 1px solid #d93a3e;
+}
+input[required].ng-invalid {
+ border-right: 5px solid #d93a3e;
+}
+input[required]:not(.required-invalid),
+input[required].ng-invalid:not(.required-invalid) {
+ border-right: 5px solid #37ad79;
+}
+.error {
+ color: #d93a3e;
+}
+#year {
+ width: 50px;
+}
+button[type=submit] {
+ background-color: #45bf94;
+ border: 0;
+ padding: 10px;
+ font-size: 1em;
+ border-radius: 4px;
+ color: #ffffff;
+ cursor: pointer;
+}
+button[type=submit]:disabled {
+ background-color: #333;
+ color: #666;
+ cursor: default;
+}
\ No newline at end of file
diff --git a/app/media-item-form.component.html b/app/media-item-form.component.html
new file mode 100755
index 0000000..cf5171c
--- /dev/null
+++ b/app/media-item-form.component.html
@@ -0,0 +1,44 @@
+
+
\ No newline at end of file
diff --git a/app/media-item-form.component.ts b/app/media-item-form.component.ts
new file mode 100755
index 0000000..8df7f9e
--- /dev/null
+++ b/app/media-item-form.component.ts
@@ -0,0 +1,59 @@
+import { Component, Inject } from '@angular/core';
+import { Validators, FormBuilder } from '@angular/forms';
+import { Router } from '@angular/router';
+
+import { MediaItemService } from './media-item.service';
+import { lookupListToken } from './providers';
+
+@Component({
+ selector: 'mw-media-item-form',
+ templateUrl: 'app/media-item-form.component.html',
+ styleUrls: ['app/media-item-form.component.css']
+})
+export class MediaItemFormComponent {
+ form;
+
+ constructor(
+ private formBuilder: FormBuilder,
+ private mediaItemService: MediaItemService,
+ @Inject(lookupListToken) public lookupLists,
+ private router: Router) {}
+
+ ngOnInit() {
+ this.form = this.formBuilder.group({
+ medium: this.formBuilder.control('Movies'),
+ name: this.formBuilder.control('', Validators.compose([
+ Validators.required,
+ Validators.pattern('[\\w\\-\\s\\/]+')
+ ])),
+ category: this.formBuilder.control(''),
+ year: this.formBuilder.control('', this.yearValidator),
+ });
+ }
+
+ yearValidator(control) {
+ if (control.value.trim().length === 0) {
+ return null;
+ }
+ let year = parseInt(control.value);
+ let minYear = 1800;
+ let maxYear = 2500;
+ if (year >= minYear && year <= maxYear) {
+ return null;
+ } else {
+ return {
+ 'year': {
+ min: minYear,
+ max: maxYear
+ }
+ };
+ }
+ }
+
+ onSubmit(mediaItem) {
+ this.mediaItemService.add(mediaItem)
+ .subscribe(() => {
+ this.router.navigate(['/', mediaItem.medium]);
+ });
+ }
+}
diff --git a/app/media-item-list.component.css b/app/media-item-list.component.css
new file mode 100755
index 0000000..fa81f78
--- /dev/null
+++ b/app/media-item-list.component.css
@@ -0,0 +1,38 @@
+:host {
+ display: block;
+ flex-direction: column;
+ padding: 0 10px;
+ margin-bottom: 20px;
+}
+header {
+ color: #c6c5c3;
+}
+header.medium-movies {
+ color: #53ace4;
+}
+header.medium-series {
+ color: #45bf94;
+}
+header > h2 {
+ font-size: 1.4em;
+}
+header > h2.error {
+ color: #d93a3e;
+}
+section {
+ flex: 1;
+ display: flex;
+ flex-flow: row wrap;
+ align-content: flex-start;
+}
+section > media-item {
+ margin: 10px;
+}
+footer {
+ text-align: right;
+}
+footer .icon {
+ width: 64px;
+ height: 64px;
+ margin: 15px;
+}
\ No newline at end of file
diff --git a/app/media-item-list.component.html b/app/media-item-list.component.html
new file mode 100755
index 0000000..6bc2880
--- /dev/null
+++ b/app/media-item-list.component.html
@@ -0,0 +1,17 @@
+
+
+
\ No newline at end of file
diff --git a/app/media-item-list.component.ts b/app/media-item-list.component.ts
new file mode 100755
index 0000000..8d00e67
--- /dev/null
+++ b/app/media-item-list.component.ts
@@ -0,0 +1,49 @@
+import { Component } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+
+import { MediaItemService } from './media-item.service';
+
+@Component({
+ selector: 'mw-media-item-list',
+ templateUrl: 'app/media-item-list.component.html',
+ styleUrls: ['app/media-item-list.component.css']
+})
+export class MediaItemListComponent {
+ medium = '';
+ mediaItems = [];
+ paramsSubscription;
+
+ constructor(
+ private mediaItemService: MediaItemService,
+ private activatedRoute: ActivatedRoute) {}
+
+ ngOnInit() {
+ this.paramsSubscription = this.activatedRoute.params
+ .subscribe(params => {
+ let medium = params['medium'];
+ if(medium.toLowerCase() === 'all') {
+ medium = '';
+ }
+ this.getMediaItems(medium);
+ });
+ }
+
+ ngOnDestroy() {
+ this.paramsSubscription.unsubscribe();
+ }
+
+ onMediaItemDelete(mediaItem) {
+ this.mediaItemService.delete(mediaItem)
+ .subscribe(() => {
+ this.getMediaItems(this.medium);
+ });
+ }
+
+ getMediaItems(medium) {
+ this.medium = medium;
+ this.mediaItemService.get(medium)
+ .subscribe(mediaItems => {
+ this.mediaItems = mediaItems;
+ });
+ }
+}
diff --git a/app/media-item.component.css b/app/media-item.component.css
new file mode 100755
index 0000000..789b72b
--- /dev/null
+++ b/app/media-item.component.css
@@ -0,0 +1,64 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ width: 140px;
+ height: 200px;
+ border: 2px solid;
+ background-color: #29394b;
+ padding: 10px;
+ color: #bdc2c5;
+}
+h2 {
+ font-size: 1.6em;
+ flex: 1;
+}
+:host.medium-movies {
+ border-color: #53ace4;
+}
+:host.medium-movies > h2 {
+ color: #53ace4;
+}
+:host.medium-series {
+ border-color: #45bf94;
+}
+:host.medium-series > h2 {
+ color: #45bf94;
+}
+.tools {
+ margin-top: 8px;
+ display: flex;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+}
+.favorite {
+ width: 24px;
+ height: 24px;
+ fill: #bdc2c5;
+}
+.favorite.is-favorite {
+ fill: #37ad79;
+}
+.favorite.is-favorite-hovering {
+ fill: #45bf94;
+}
+.favorite.is-favorite.is-favorite-hovering {
+ fill: #ec4342;
+}
+.delete {
+ display: block;
+ background-color: #ec4342;
+ padding: 4px;
+ font-size: .8em;
+ border-radius: 4px;
+ color: #ffffff;
+ cursor: pointer;
+}
+.details {
+ display: block;
+ background-color: #37ad79;
+ padding: 4px;
+ font-size: .8em;
+ border-radius: 4px;
+ color: #ffffff;
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/app/media-item.component.html b/app/media-item.component.html
new file mode 100755
index 0000000..7defcf2
--- /dev/null
+++ b/app/media-item.component.html
@@ -0,0 +1,20 @@
+{{ mediaItem.name }}
+
+ Watched on {{ mediaItem.watchedOn | date: 'shortDate' }}
+
+{{ mediaItem.category }}
+{{ mediaItem.year }}
+
\ No newline at end of file
diff --git a/app/media-item.component.ts b/app/media-item.component.ts
new file mode 100755
index 0000000..224c247
--- /dev/null
+++ b/app/media-item.component.ts
@@ -0,0 +1,15 @@
+import { Component, Input, Output, EventEmitter } from '@angular/core';
+
+@Component({
+ selector: 'mw-media-item',
+ templateUrl: 'app/media-item.component.html',
+ styleUrls: ['app/media-item.component.css']
+})
+export class MediaItemComponent {
+ @Input() mediaItem;
+ @Output() delete = new EventEmitter();
+
+ onDelete() {
+ this.delete.emit(this.mediaItem);
+ }
+}
diff --git a/app/media-item.service.ts b/app/media-item.service.ts
new file mode 100755
index 0000000..bd16331
--- /dev/null
+++ b/app/media-item.service.ts
@@ -0,0 +1,27 @@
+import { Injectable } from '@angular/core';
+import { Http, URLSearchParams } from '@angular/http';
+import 'rxjs/add/operator/map';
+
+@Injectable()
+export class MediaItemService {
+ constructor(private http: Http) {}
+
+ get(medium) {
+ let searchParams = new URLSearchParams();
+ searchParams.append('medium', medium);
+ return this.http.get('mediaitems', { search: searchParams })
+ .map(response => {
+ return response.json().mediaItems;
+ });
+ }
+
+ add(mediaItem) {
+ return this.http.post('mediaitems', mediaItem)
+ .map(response => {});
+ }
+
+ delete(mediaItem) {
+ return this.http.delete(`mediaitems/${mediaItem.id}`)
+ .map(response => {});
+ }
+}
diff --git a/app/mock-xhr-backend.ts b/app/mock-xhr-backend.ts
new file mode 100755
index 0000000..84641b5
--- /dev/null
+++ b/app/mock-xhr-backend.ts
@@ -0,0 +1,118 @@
+import { Request, Response, ResponseOptions, RequestMethod } from '@angular/http';
+import { Observable } from 'rxjs/Observable';
+import { Observer } from 'rxjs/Observer';
+
+export class MockXHRBackend {
+ constructor() {
+ }
+
+ createConnection(request: Request) {
+ var response = new Observable((responseObserver: Observer) => {
+ var responseData;
+ var responseOptions;
+ switch (request.method) {
+ case RequestMethod.Get:
+ if (request.url.indexOf('mediaitems?medium=') >= 0 || request.url === 'mediaitems') {
+ var medium;
+ if (request.url.indexOf('?') >= 0) {
+ medium = request.url.split('=')[1];
+ if (medium === 'undefined') medium = '';
+ }
+ var mediaItems;
+ if (medium) {
+ mediaItems = this._mediaItems.filter(mediaItem => mediaItem.medium === medium);
+ } else {
+ mediaItems = this._mediaItems;
+ }
+ responseOptions = new ResponseOptions({
+ body: { mediaItems: JSON.parse(JSON.stringify(mediaItems)) },
+ status: 200
+ });
+ } else {
+ var id = parseInt(request.url.split('/')[1]);
+ mediaItems = this._mediaItems.filter(mediaItem => mediaItem.id === id);
+ responseOptions = new ResponseOptions({
+ body: JSON.parse(JSON.stringify(mediaItems[0])),
+ status: 200
+ });
+ }
+ break;
+ case RequestMethod.Post:
+ var mediaItem = JSON.parse(request.text().toString());
+ mediaItem.id = this._getNewId();
+ this._mediaItems.push(mediaItem);
+ responseOptions = new ResponseOptions({ status: 201 });
+ break;
+ case RequestMethod.Delete:
+ var id = parseInt(request.url.split('/')[1]);
+ this._deleteMediaItem(id);
+ responseOptions = new ResponseOptions({ status: 200 });
+ }
+
+ var responseObject = new Response(responseOptions);
+ responseObserver.next(responseObject);
+ responseObserver.complete();
+ return () => { };
+ });
+ return { response };
+ }
+
+ _deleteMediaItem(id) {
+ var mediaItem = this._mediaItems.find(mediaItem => mediaItem.id === id);
+ var index = this._mediaItems.indexOf(mediaItem);
+ if (index >= 0) {
+ this._mediaItems.splice(index, 1);
+ }
+ }
+
+ _getNewId() {
+ if (this._mediaItems.length > 0) {
+ return Math.max.apply(Math, this._mediaItems.map(mediaItem => mediaItem.id)) + 1;
+ }
+ }
+
+ _mediaItems = [
+ {
+ id: 1,
+ name: "Firebug",
+ medium: "Series",
+ category: "Science Fiction",
+ year: 2010,
+ watchedOn: 1294166565384,
+ isFavorite: false
+ },
+ {
+ id: 2,
+ name: "The Small Tall",
+ medium: "Movies",
+ category: "Comedy",
+ year: 2015,
+ watchedOn: null,
+ isFavorite: true
+ }, {
+ id: 3,
+ name: "The Redemption",
+ medium: "Movies",
+ category: "Action",
+ year: 2016,
+ watchedOn: null,
+ isFavorite: false
+ }, {
+ id: 4,
+ name: "Hoopers",
+ medium: "Series",
+ category: "Drama",
+ year: null,
+ watchedOn: null,
+ isFavorite: true
+ }, {
+ id: 5,
+ name: "Happy Joe: Cheery Road",
+ medium: "Movies",
+ category: "Action",
+ year: 2015,
+ watchedOn: 1457166565384,
+ isFavorite: false
+ }
+ ];
+}
\ No newline at end of file
diff --git a/app/providers.ts b/app/providers.ts
new file mode 100755
index 0000000..4665768
--- /dev/null
+++ b/app/providers.ts
@@ -0,0 +1,7 @@
+import { OpaqueToken } from '@angular/core';
+
+export const lookupListToken = new OpaqueToken('lookupListToken');
+
+export const lookupLists = {
+ mediums: ['Movies', 'Series']
+};
\ No newline at end of file
diff --git a/index.html b/index.html
old mode 100644
new mode 100755
index 1233aed..0cd8fdd
--- a/index.html
+++ b/index.html
@@ -1,29 +1,30 @@
- MeWL
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- Loading...
+ Loading...
\ No newline at end of file
diff --git a/media/01.png b/media/01.png
new file mode 100755
index 0000000..ae2671b
Binary files /dev/null and b/media/01.png differ
diff --git a/media/02.png b/media/02.png
new file mode 100755
index 0000000..7ab30ba
Binary files /dev/null and b/media/02.png differ
diff --git a/media/03.png b/media/03.png
new file mode 100755
index 0000000..2c9af84
Binary files /dev/null and b/media/03.png differ
diff --git a/media/04.png b/media/04.png
new file mode 100755
index 0000000..7b44937
Binary files /dev/null and b/media/04.png differ
diff --git a/package.json b/package.json
index d60797f..d15f5e1 100644
--- a/package.json
+++ b/package.json
@@ -1,39 +1,41 @@
{
- "name": "angular2-essential-training",
- "version": "1.0.0",
- "author": "Justin Schwartzenberger",
- "description": "This project is the repository for my Angular 2 Essential Training course on Lynda.com.",
- "repository": {
- "type": "git",
- "url": "https://github.com/LyndaExerciseFiles/angular2-essential-training.git"
- },
- "scripts": {
- "postinstall": "npm run typings install",
- "tsc": "tsc",
- "tsc:w": "tsc -w",
- "lite": "lite-server",
- "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
- "typings": "typings"
- },
- "dependencies": {
- "@angular/common": "2.0.0-rc.4",
- "@angular/compiler": "2.0.0-rc.4",
- "@angular/core": "2.0.0-rc.4",
- "@angular/forms": "0.2.0",
- "@angular/http": "2.0.0-rc.4",
- "@angular/platform-browser": "2.0.0-rc.4",
- "@angular/platform-browser-dynamic": "2.0.0-rc.4",
- "@angular/router": "3.0.0-beta.2",
- "systemjs": "0.19.27",
- "core-js": "^2.4.0",
- "reflect-metadata": "^0.1.3",
- "rxjs": "5.0.0-beta.6",
- "zone.js": "^0.6.12"
- },
- "devDependencies": {
- "concurrently": "^2.2.0",
- "lite-server": "^2.2.0",
- "typescript": "^1.8.10",
- "typings": "^1.0.4"
- }
-}
\ No newline at end of file
+ "name": "angular2-essential-training",
+ "version": "1.0.0",
+ "author": "Justin Schwartzenberger",
+ "description": "This project is the repository for my Angular 2 Essential Training course on Lynda.com.",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/LyndaExerciseFiles/angular2-essential-training.git"
+ },
+ "scripts": {
+ "clean": "rimraf app/**/*.js app/**/*.js.map",
+ "tsc": "tsc",
+ "tsc:w": "tsc -w",
+ "lite": "lite-server",
+ "prestart": "npm run clean",
+ "start": "tsc && concurrently \"tsc -w\" \"lite-server\" "
+ },
+ "dependencies": {
+ "@angular/common": "2.0.0",
+ "@angular/compiler": "2.0.0",
+ "@angular/core": "2.0.0",
+ "@angular/forms": "2.0.0",
+ "@angular/http": "2.0.0",
+ "@angular/platform-browser": "2.0.0",
+ "@angular/platform-browser-dynamic": "2.0.0",
+ "@angular/router": "3.0.0",
+ "systemjs": "0.19.27",
+ "core-js": "2.4.1",
+ "reflect-metadata": "0.1.3",
+ "rxjs": "5.0.0-beta.12",
+ "zone.js": "0.6.23"
+ },
+ "devDependencies": {
+ "@types/core-js": "^0.9.34",
+ "@types/node": "^6.0.41",
+ "concurrently": "2.2.0",
+ "lite-server": "2.2.2",
+ "rimraf": "2.5.4",
+ "typescript": "2.0.2"
+ }
+}
diff --git a/sample.txt b/sample.txt
new file mode 100755
index 0000000..8c96068
--- /dev/null
+++ b/sample.txt
@@ -0,0 +1,10 @@
+var categories = [];
+mediaItems.forEach(mediaItem => {
+ if (categories.indexOf(mediaItem.category) <= -1) {
+ categories.push(mediaItem.category);
+ }
+});
+return categories.join(', ');
+
+
+[\\w\\-\\s\\/]+
diff --git a/systemjs.config.js b/systemjs.config.js
index 0e29e06..b32efb1 100644
--- a/systemjs.config.js
+++ b/systemjs.config.js
@@ -2,20 +2,20 @@
* System configuration for Angular 2 samples
* Adjust as necessary for your application needs.
*/
-(function(global) {
+(function (global) {
// map tells the System loader where to look for things
var map = {
- 'app': 'app', // 'dist',
+ 'app': 'app', // 'dist',
- '@angular': 'node_modules/@angular',
- 'rxjs': 'node_modules/rxjs'
+ '@angular': 'node_modules/@angular',
+ 'rxjs': 'node_modules/rxjs'
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
- 'app': { main: 'main.js', defaultExtension: 'js' },
- 'rxjs': { defaultExtension: 'js' }
+ 'app': { main: 'main.js', defaultExtension: 'js' },
+ 'rxjs': { defaultExtension: 'js' }
};
var ngPackageNames = [
@@ -31,12 +31,12 @@
// Individual files (~300 requests):
function packIndex(pkgName) {
- packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
+ packages['@angular/' + pkgName] = { main: 'index.js', defaultExtension: 'js' };
}
// Bundled (~40 requests):
function packUmd(pkgName) {
- packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
+ packages['@angular/' + pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
}
// Most environments should use UMD; some (Karma) need the individual index files
@@ -45,9 +45,6 @@
// Add package entries for angular packages
ngPackageNames.forEach(setPackageConfig);
- // No umd for router yet
- packages['@angular/router'] = { main: 'index.js', defaultExtension: 'js' };
-
var config = {
map: map,
packages: packages
diff --git a/typings.json b/typings.json
deleted file mode 100644
index b8c238f..0000000
--- a/typings.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "globalDependencies": {
- "core-js": "registry:dt/core-js#0.0.0+20160602141332",
- "node": "registry:dt/node#6.0.0+20160621231320"
- }
-}
\ No newline at end of file