diff --git a/day5/README.md b/day5/README.md index b6fb535..e687838 100644 --- a/day5/README.md +++ b/day5/README.md @@ -2,7 +2,7 @@ ## Adding a Feature -Look around [the comments app](comments/). This is just a basic app that displays a list of comments +Look around [the comments app](comments/). This is just a basic app that displays a list of comments. You may need to run `npm install` for it to work. - Alter it so that each comment has an author, represented by a string. - Add a feature that allows you to add more comments @@ -19,3 +19,5 @@ Look again at what you did in [the comments app](comments/). It's all in one co At the moment, there's no styling. Add some by incorporating [Bootstrap](http://getbootstrap.com/), [Materialize](http://materializecss.com/), or [Skeleton](http://getskeleton.com/). Feel free to write your own CSS as an alternative to using one of the above CSS frameworks. ## Fixing Bugs + +Someone has hacked up the [Tour Of Heroes](https://angular.io/tutorial/toh-pt5) demo from google! Go into [heroes](heroes/), run `npm install` and `npm start` to start the app. Try to fix all the errors so that it works like [this](https://embed.plnkr.co/?show=preview). Try not to look at the code listed in the previous link, unless you're absolutely stumped. diff --git a/day5/heroes/.gitignore b/day5/heroes/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/day5/heroes/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/day5/heroes/bs-config.json b/day5/heroes/bs-config.json new file mode 100644 index 0000000..4e58595 --- /dev/null +++ b/day5/heroes/bs-config.json @@ -0,0 +1,8 @@ +{ + "server": { + "baseDir": "src", + "routes": { + "/node_modules": "node_modules" + } + } +} diff --git a/day5/heroes/e2e-spec.ts b/day5/heroes/e2e-spec.ts new file mode 100644 index 0000000..a49f2dd --- /dev/null +++ b/day5/heroes/e2e-spec.ts @@ -0,0 +1,190 @@ +'use strict'; // necessary for es6 output in node + +import { browser, element, by, ElementFinder } from 'protractor'; +import { promise } from 'selenium-webdriver'; + +const expectedH1 = 'Tour of Heroes'; +const expectedTitle = `Angular ${expectedH1}`; +const targetHero = { id: 15, name: 'Magneta' }; +const targetHeroDashboardIndex = 3; +const nameSuffix = 'X'; +const newHeroName = targetHero.name + nameSuffix; + +class Hero { + id: number; + name: string; + + // Factory methods + + // Get hero from s formatted as ' '. + static fromString(s: string): Hero { + return { + id: +s.substr(0, s.indexOf(' ')), + name: s.substr(s.indexOf(' ') + 1), + }; + } + + // Get hero id and name from the given detail element. + static async fromDetail(detail: ElementFinder): Promise { + // Get hero id from the first
+ let _id = await detail.all(by.css('div')).first().getText(); + // Get name from the h2 + let _name = await detail.element(by.css('h2')).getText(); + return { + id: +_id.substr(_id.indexOf(' ') + 1), + name: _name.substr(0, _name.lastIndexOf(' ')) + }; + } +} + +describe('Tutorial part 5', () => { + + beforeAll(() => browser.get('')); + + function getPageElts() { + let navElts = element.all(by.css('my-app nav a')); + + return { + navElts: navElts, + + myDashboardHref: navElts.get(0), + myDashboard: element(by.css('my-app my-dashboard')), + topHeroes: element.all(by.css('my-app my-dashboard > div h4')), + + myHeroesHref: navElts.get(1), + myHeroes: element(by.css('my-app my-heroes')), + allHeroes: element.all(by.css('my-app my-heroes li')), + selectedHero: element(by.css('my-app li.selected')), + selectedHeroSubview: element(by.css('my-app my-heroes > div')), + + heroDetail: element(by.css('my-app hero-detail > div')) + }; + } + + describe('Initial page', () => { + + it(`has title '${expectedTitle}'`, () => { + expect(browser.getTitle()).toEqual(expectedTitle); + }); + + it(`has h1 '${expectedH1}'`, () => { + expectHeading(1, expectedH1); + }); + + const expectedViewNames = ['Dashboard', 'Heroes']; + it(`has views ${expectedViewNames}`, () => { + let viewNames = getPageElts().navElts.map((el: ElementFinder) => el.getText()); + expect(viewNames).toEqual(expectedViewNames); + }); + + it('has dashboard as the active view', () => { + let page = getPageElts(); + expect(page.myDashboard.isPresent()).toBeTruthy(); + }); + + }); + + describe('Dashboard tests', () => { + + beforeAll(() => browser.get('')); + + it('has top heroes', () => { + let page = getPageElts(); + expect(page.topHeroes.count()).toEqual(4); + }); + + it(`selects and routes to ${targetHero.name} details`, dashboardSelectTargetHero); + + it(`updates hero name (${newHeroName}) in details view`, updateHeroNameInDetailView); + + it(`saves and shows ${newHeroName} in Dashboard`, () => { + element(by.buttonText('Back')).click(); + let targetHeroElt = getPageElts().topHeroes.get(targetHeroDashboardIndex); + expect(targetHeroElt.getText()).toEqual(newHeroName); + }); + + }); + + describe('Heroes tests', () => { + + beforeAll(() => browser.get('')); + + it('can switch to Heroes view', () => { + getPageElts().myHeroesHref.click(); + let page = getPageElts(); + expect(page.myHeroes.isPresent()).toBeTruthy(); + expect(page.allHeroes.count()).toEqual(10, 'number of heroes'); + }); + + it(`selects and shows ${targetHero.name} as selected in list`, () => { + getHeroLiEltById(targetHero.id).click(); + let expectedText = `${targetHero.id} ${targetHero.name}`; + expect(getPageElts().selectedHero.getText()).toBe(expectedText); + }); + + it('shows selected hero subview', async () => { + let page = getPageElts(); + let title = page.selectedHeroSubview.element(by.css('h2')).getText(); + let expectedTitle = `${targetHero.name.toUpperCase()} is my hero`; + expect(title).toEqual(expectedTitle); + }); + + it('can route to hero details', async () => { + element(by.buttonText('View Details')).click(); + + let page = getPageElts(); + expect(page.heroDetail.isPresent()).toBeTruthy('shows hero detail'); + let hero = await Hero.fromDetail(page.heroDetail); + expect(hero.id).toEqual(targetHero.id); + expect(hero.name).toEqual(targetHero.name); + }); + + it(`updates hero name (${newHeroName}) in details view`, updateHeroNameInDetailView); + + it(`shows ${newHeroName} in Heroes list`, () => { + element(by.buttonText('Back')).click(); + let expectedText = `${targetHero.id} ${newHeroName}`; + expect(getHeroLiEltById(targetHero.id).getText()).toEqual(expectedText); + }); + + }); + + async function dashboardSelectTargetHero() { + let targetHeroElt = getPageElts().topHeroes.get(targetHeroDashboardIndex); + expect(targetHeroElt.getText()).toEqual(targetHero.name); + targetHeroElt.click(); + + let page = getPageElts(); + expect(page.heroDetail.isPresent()).toBeTruthy('shows hero detail'); + let hero = await Hero.fromDetail(page.heroDetail); + expect(hero.id).toEqual(targetHero.id); + expect(hero.name).toEqual(targetHero.name); + } + + async function updateHeroNameInDetailView() { + // Assumes that the current view is the hero details view. + addToHeroName(nameSuffix); + + let page = getPageElts(); + let hero = await Hero.fromDetail(page.heroDetail); + expect(hero.id).toEqual(targetHero.id); + expect(hero.name).toEqual(newHeroName); + } + +}); + +function addToHeroName(text: string): promise.Promise { + let input = element(by.css('input')); + return input.sendKeys(text); +} + +function expectHeading(hLevel: number, expectedText: string): void { + let hTag = `h${hLevel}`; + let hText = element(by.css(hTag)).getText(); + expect(hText).toEqual(expectedText, hTag); +}; + +function getHeroLiEltById(id: number) { + let spanForId = element(by.cssContainingText('li span.badge', id.toString())); + return spanForId.element(by.xpath('..')); +} diff --git a/day5/heroes/package.json b/day5/heroes/package.json new file mode 100644 index 0000000..2a91cb5 --- /dev/null +++ b/day5/heroes/package.json @@ -0,0 +1,85 @@ +{ + "name": "angular-io-example", + "version": "1.0.0", + "private": true, + "description": "Example project from an angular.io guide.", + "scripts": { + "test:once": "karma start karma.conf.js --single-run", + "build": "tsc -p src/", + "serve": "lite-server -c=bs-config.json", + "prestart": "npm run build", + "start": "concurrently \"npm run build:watch\" \"npm run serve\"", + "pretest": "npm run build", + "test": "concurrently \"npm run build:watch\" \"karma start karma.conf.js\"", + "pretest:once": "npm run build", + "build:watch": "tsc -p src/ -w", + "build:upgrade": "tsc", + "serve:upgrade": "http-server", + "build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js", + "serve:aot": "lite-server -c bs-config.aot.json", + "build:babel": "babel src -d src --extensions \".es6\" --source-maps", + "copy-dist-files": "node ./copy-dist-files.js", + "i18n": "ng-xi18n", + "lint": "tslint ./src/**/*.ts -t verbose" + }, + "keywords": [], + "author": "", + "license": "MIT", + "dependencies": { + "@angular/animations": "~4.2.0", + "@angular/common": "~4.2.0", + "@angular/compiler": "~4.2.0", + "@angular/compiler-cli": "~4.2.0", + "@angular/core": "~4.2.0", + "@angular/forms": "~4.2.0", + "@angular/http": "~4.2.0", + "@angular/platform-browser": "~4.2.0", + "@angular/platform-browser-dynamic": "~4.2.0", + "@angular/platform-server": "~4.2.0", + "@angular/router": "~4.2.0", + "@angular/tsc-wrapped": "~4.2.0", + "@angular/upgrade": "~4.2.0", + "angular-in-memory-web-api": "~0.3.2", + "core-js": "^2.4.1", + "rxjs": "^5.1.0", + "systemjs": "0.19.39", + "zone.js": "^0.8.4" + }, + "devDependencies": { + "@types/angular": "^1.5.16", + "@types/angular-animate": "^1.5.5", + "@types/angular-cookies": "^1.4.2", + "@types/angular-mocks": "^1.5.5", + "@types/angular-resource": "^1.5.6", + "@types/angular-route": "^1.3.2", + "@types/angular-sanitize": "^1.3.3", + "@types/jasmine": "2.5.36", + "@types/node": "^6.0.45", + "babel-cli": "^6.16.0", + "babel-preset-angular2": "^0.0.2", + "babel-preset-es2015": "^6.16.0", + "canonical-path": "0.0.2", + "concurrently": "^3.0.0", + "http-server": "^0.9.0", + "jasmine": "~2.4.1", + "jasmine-core": "~2.4.1", + "karma": "^1.3.0", + "karma-chrome-launcher": "^2.0.0", + "karma-cli": "^1.0.1", + "karma-jasmine": "^1.0.2", + "karma-jasmine-html-reporter": "^0.2.2", + "karma-phantomjs-launcher": "^1.0.2", + "lite-server": "^2.2.2", + "lodash": "^4.16.2", + "phantomjs-prebuilt": "^2.1.7", + "protractor": "~5.1.0", + "rollup": "^0.41.6", + "rollup-plugin-commonjs": "^8.0.2", + "rollup-plugin-node-resolve": "2.0.0", + "rollup-plugin-uglify": "^1.0.1", + "source-map-explorer": "^1.3.2", + "tslint": "^3.15.1", + "typescript": "~2.3.2" + }, + "repository": {} +} \ No newline at end of file diff --git a/day5/heroes/src/app/app-routing.module.js b/day5/heroes/src/app/app-routing.module.js new file mode 100644 index 0000000..0963a7d --- /dev/null +++ b/day5/heroes/src/app/app-routing.module.js @@ -0,0 +1,32 @@ +"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 router_1 = require("@angular/router"); +var dashboard_component_1 = require("./dashboard.component"); +var heroes_component_1 = require("./heroes.component"); +var hero_detail_component_1 = require("./hero-detail.component"); +var routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: dashboard_component_1.DashboardComponent }, + { path: 'detail/:id', component: hero_detail_component_1.HeroDetailComponent }, + { path: 'heroes', component: heroes_component_1.HeroesComponent } +]; +var AppRoutingModule = (function () { + function AppRoutingModule() { + } + return AppRoutingModule; +}()); +AppRoutingModule = __decorate([ + core_1.NgModule({ + imports: [router_1.RouterModule.forRoot(routes)], + exports: [router_1.RouterModule] + }) +], AppRoutingModule); +exports.AppRoutingModule = AppRoutingModule; +//# sourceMappingURL=app-routing.module.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/app-routing.module.js.map b/day5/heroes/src/app/app-routing.module.js.map new file mode 100644 index 0000000..7d618f9 --- /dev/null +++ b/day5/heroes/src/app/app-routing.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app-routing.module.js","sourceRoot":"","sources":["app-routing.module.ts"],"names":[],"mappings":";;;;;;;;AAAA,sCAAqD;AACrD,0CAAuD;AAEvD,6DAA6D;AAC7D,uDAA0D;AAC1D,iEAA+D;AAE/D,IAAM,MAAM,GAAW;IACrB,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE;IACzD,EAAE,IAAI,EAAE,WAAW,EAAG,SAAS,EAAE,wCAAkB,EAAE;IACrD,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,2CAAmB,EAAE;IACtD,EAAE,IAAI,EAAE,QAAQ,EAAM,SAAS,EAAE,kCAAe,EAAE;CACnD,CAAC;AAMF,IAAa,gBAAgB;IAA7B;IAA+B,CAAC;IAAD,uBAAC;AAAD,CAAC,AAAhC,IAAgC;AAAnB,gBAAgB;IAJ5B,eAAQ,CAAC;QACR,OAAO,EAAE,CAAE,qBAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAE;QACzC,OAAO,EAAE,CAAE,qBAAY,CAAE;KAC1B,CAAC;GACW,gBAAgB,CAAG;AAAnB,4CAAgB"} \ No newline at end of file diff --git a/day5/heroes/src/app/app-routing.module.ts b/day5/heroes/src/app/app-routing.module.ts new file mode 100644 index 0000000..bc070f6 --- /dev/null +++ b/day5/heroes/src/app/app-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { DashboardComponent } from './dashboard.component'; +import { HeroesComponent } from './heroes.component'; +import { HeroDetailComponent } from './hero-detail.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: DashboardComponent }, + { path: 'detail/:id', component: HeroDetailComponent }, + { path: 'heroes', component: HeroesComponent } +]; + +@NgModule({ + imports: [ RouterModule.forRoot(routes) ], + exports: [ RouterModule ] +}) +export class AppRoutingModule {} diff --git a/day5/heroes/src/app/app.component.css b/day5/heroes/src/app/app.component.css new file mode 100644 index 0000000..40e1aba --- /dev/null +++ b/day5/heroes/src/app/app.component.css @@ -0,0 +1,28 @@ +h1 { + font-size: 1.2em; + color: #999; + margin-bottom: 0; +} +h2 { + font-size: 2em; + margin-top: 0; + padding-top: 0; +} +nav a { + padding: 5px 10px; + text-decoration: none; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; +} +nav a:visited, a:link { + color: #607D8B; +} +nav a:hover { + color: #039be5; + background-color: #CFD8DC; +} +nav a.active { + color: #039be5; +} diff --git a/day5/heroes/src/app/app.component.js b/day5/heroes/src/app/app.component.js new file mode 100644 index 0000000..1889019 --- /dev/null +++ b/day5/heroes/src/app/app.component.js @@ -0,0 +1,24 @@ +"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 AppComponent = (function () { + function AppComponent() { + this.title = 'Tour of Heroes'; + } + return AppComponent; +}()); +AppComponent = __decorate([ + core_1.Component({ + selector: 'my-app', + template: "\n

{{title}}

\n \n \n ", + styleUrls: ['./app.component.css'], + }) +], AppComponent); +exports.AppComponent = AppComponent; +//# sourceMappingURL=app.component.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/app.component.js.map b/day5/heroes/src/app/app.component.js.map new file mode 100644 index 0000000..ab070c2 --- /dev/null +++ b/day5/heroes/src/app/app.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.component.js","sourceRoot":"","sources":["app.component.ts"],"names":[],"mappings":";;;;;;;;AAAA,sCAA0C;AAc1C,IAAa,YAAY;IAZzB;QAaE,UAAK,GAAG,gBAAgB,CAAC;IAC3B,CAAC;IAAD,mBAAC;AAAD,CAAC,AAFD,IAEC;AAFY,YAAY;IAZxB,gBAAS,CAAC;QACT,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,gPAOT;QACD,SAAS,EAAE,CAAC,qBAAqB,CAAC;KACnC,CAAC;GACW,YAAY,CAExB;AAFY,oCAAY"} \ No newline at end of file diff --git a/day5/heroes/src/app/app.component.ts b/day5/heroes/src/app/app.component.ts new file mode 100644 index 0000000..564651e --- /dev/null +++ b/day5/heroes/src/app/app.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'my-app', + template: ` +

{{title}}

+ + + `, + styleUrls: ['./app.component.css'], +}) +export class AppComponent { + title = 'Tour of Heroes'; +} diff --git a/day5/heroes/src/app/app.module.js b/day5/heroes/src/app/app.module.js new file mode 100644 index 0000000..3528c9a --- /dev/null +++ b/day5/heroes/src/app/app.module.js @@ -0,0 +1,41 @@ +"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 platform_browser_1 = require("@angular/platform-browser"); +var forms_1 = require("@angular/forms"); +var app_component_1 = require("./app.component"); +var dashboard_component_1 = require("./dashboard.component"); +var hero_detail_component_1 = require("./hero-detail.component"); +var heroes_component_1 = require("./heroes.component"); +var hero_service_1 = require("./hero.service"); +var app_routing_module_1 = require("./app-routing.module"); +var AppModule = (function () { + function AppModule() { + } + return AppModule; +}()); +AppModule = __decorate([ + core_1.NgModule({ + imports: [ + platform_browser_1.BrowserModule, + forms_1.FormsModule, + app_routing_module_1.AppRoutingModule + ], + declarations: [ + app_component_1.AppComponent, + dashboard_component_1.DashboardComponent, + hero_detail_component_1.HeroDetailComponent, + heroes_component_1.HeroesComponent + ], + providers: [hero_service_1.HeroService], + bootstrap: [app_component_1.AppComponent] + }) +], AppModule); +exports.AppModule = AppModule; +//# sourceMappingURL=app.module.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/app.module.js.map b/day5/heroes/src/app/app.module.js.map new file mode 100644 index 0000000..30e200b --- /dev/null +++ b/day5/heroes/src/app/app.module.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.module.js","sourceRoot":"","sources":["app.module.ts"],"names":[],"mappings":";;;;;;;;AAAA,sCAA+C;AAC/C,8DAA2D;AAC3D,wCAAgD;AAEhD,iDAAuD;AACvD,6DAA6D;AAC7D,iEAA+D;AAC/D,uDAA0D;AAC1D,+CAAsD;AAEtD,2DAA4D;AAiB5D,IAAa,SAAS;IAAtB;IAAyB,CAAC;IAAD,gBAAC;AAAD,CAAC,AAA1B,IAA0B;AAAb,SAAS;IAfrB,eAAQ,CAAC;QACR,OAAO,EAAE;YACP,gCAAa;YACb,mBAAW;YACX,qCAAgB;SACjB;QACD,YAAY,EAAE;YACZ,4BAAY;YACZ,wCAAkB;YAClB,2CAAmB;YACnB,kCAAe;SAChB;QACD,SAAS,EAAE,CAAE,0BAAW,CAAE;QAC1B,SAAS,EAAE,CAAE,4BAAY,CAAE;KAC5B,CAAC;GACW,SAAS,CAAI;AAAb,8BAAS"} \ No newline at end of file diff --git a/day5/heroes/src/app/app.module.ts b/day5/heroes/src/app/app.module.ts new file mode 100644 index 0000000..795b1b2 --- /dev/null +++ b/day5/heroes/src/app/app.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { FormsModule } from '@angular/forms'; + +import { AppComponent } from './app.component'; +import { DashboardComponent } from './dashboard.component'; +import { HeroDetailComponent } from './hero-detail.component'; +import { HeroesComponent } from './heroes.component'; +import { HeroService } from './hero.service'; + +import { AppRoutingModule } from './app-routing.module'; + +@NgModule({ + imports: [ + BrowserModule, + FormsModule, + AppRoutingModule + ], + declarations: [ + AppComponent, + DashboardComponent, + HeroDetailComponent, + HeroesComponent + ], + providers: [ HeroService ], + bootstrap: [ AppComponent ] +}) +export class AppModule { } diff --git a/day5/heroes/src/app/dashboard.component.css b/day5/heroes/src/app/dashboard.component.css new file mode 100644 index 0000000..096cec7 --- /dev/null +++ b/day5/heroes/src/app/dashboard.component.css @@ -0,0 +1,61 @@ +[class*='col-'] { + float: left; + padding-right: 20px; + padding-bottom: 20px; +} +[class*='col-']:last-of-type { + padding-right: 0; +} +a { + text-decoration: none; +} +*, *:after, *:before { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +h3 { + text-align: center; margin-bottom: 0; +} +h4 { + position: relative; +} +.grid { + margin: 0; +} +.col-1-4 { + width: 25%; +} +.module { + padding: 20px; + text-align: center; + color: #eee; + max-height: 120px; + min-width: 120px; + background-color: #607D8B; + border-radius: 2px; +} +.module:hover { + background-color: #EEE; + cursor: pointer; + color: #607d8b; +} +.grid-pad { + padding: 10px 0; +} +.grid-pad > [class*='col-']:last-of-type { + padding-right: 20px; +} +@media (max-width: 600px) { + .module { + font-size: 10px; + max-height: 75px; } +} +@media (max-width: 1024px) { + .grid { + margin: 0; + } + .module { + min-width: 60px; + } +} diff --git a/day5/heroes/src/app/dashboard.component.html b/day5/heroes/src/app/dashboard.component.html new file mode 100644 index 0000000..b66fd68 --- /dev/null +++ b/day5/heroes/src/app/dashboard.component.html @@ -0,0 +1,8 @@ +

Top Heroes

+ diff --git a/day5/heroes/src/app/dashboard.component.js b/day5/heroes/src/app/dashboard.component.js new file mode 100644 index 0000000..7a2ab87 --- /dev/null +++ b/day5/heroes/src/app/dashboard.component.js @@ -0,0 +1,35 @@ +"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 hero_service_1 = require("./hero.service"); +var DashboardComponent = (function () { + function DashboardComponent(heroService) { + this.heroService = heroService; + this.heroes = []; + } + DashboardComponent.prototype.ngOnInit = function () { + var _this = this; + this.heroService.getHeroes() + .then(function (heroes) { return _this.heroes = heroes.slice(1, 5); }); + }; + return DashboardComponent; +}()); +DashboardComponent = __decorate([ + core_1.Component({ + selector: 'my-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.css'] + }), + __metadata("design:paramtypes", [hero_service_1.HeroService]) +], DashboardComponent); +exports.DashboardComponent = DashboardComponent; +//# sourceMappingURL=dashboard.component.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/dashboard.component.js.map b/day5/heroes/src/app/dashboard.component.js.map new file mode 100644 index 0000000..ea77ac3 --- /dev/null +++ b/day5/heroes/src/app/dashboard.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dashboard.component.js","sourceRoot":"","sources":["dashboard.component.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,sCAAkD;AAGlD,+CAA6C;AAO7C,IAAa,kBAAkB;IAI7B,4BAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;QAF5C,WAAM,GAAW,EAAE,CAAC;IAE4B,CAAC;IAEjD,qCAAQ,GAAR;QAAA,iBAGC;QAFC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE;aACzB,IAAI,CAAC,UAAA,MAAM,IAAI,OAAA,KAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAhC,CAAgC,CAAC,CAAC;IACtD,CAAC;IACH,yBAAC;AAAD,CAAC,AAVD,IAUC;AAVY,kBAAkB;IAL9B,gBAAS,CAAC;QACT,QAAQ,EAAE,cAAc;QACxB,WAAW,EAAE,4BAA4B;QACzC,SAAS,EAAE,CAAE,2BAA2B,CAAE;KAC3C,CAAC;qCAKiC,0BAAW;GAJjC,kBAAkB,CAU9B;AAVY,gDAAkB"} \ No newline at end of file diff --git a/day5/heroes/src/app/dashboard.component.ts b/day5/heroes/src/app/dashboard.component.ts new file mode 100644 index 0000000..8a86b19 --- /dev/null +++ b/day5/heroes/src/app/dashboard.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit } from '@angular/core'; + +import { Hero } from './hero'; +import { HeroService } from './hero.service'; + +@Component({ + selector: 'my-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: [ './dashboard.component.css' ] +}) +export class DashboardComponent implements OnInit { + + heroes: Hero[] = []; + + constructor(private heroService: HeroService) { } + + ngOnInit(): void { + this.heroService.getHeroes() + .then(heroes => this.heroes = heroes.slice(1, 5)); + } +} diff --git a/day5/heroes/src/app/hero-detail.component.css b/day5/heroes/src/app/hero-detail.component.css new file mode 100644 index 0000000..b5ab6e6 --- /dev/null +++ b/day5/heroes/src/app/hero-detail.component.css @@ -0,0 +1,29 @@ +label { + display: inline-block; + width: 3em; + margin: .5em 0; + color: #607D8B; + font-weight: bold; +} +input { + height: 2em; + font-size: 1em; + padding-left: .4em; +} +button { + margin-top: 20px; + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; cursor: hand; +} +button:hover { + background-color: #cfd8dc; +} +button:disabled { + background-color: #eee; + color: #ccc; + cursor: auto; +} diff --git a/day5/heroes/src/app/hero-detail.component.html b/day5/heroes/src/app/hero-detail.component.html new file mode 100644 index 0000000..6a78d67 --- /dev/null +++ b/day5/heroes/src/app/hero-detail.component.html @@ -0,0 +1,10 @@ +
+

{{hero.name}} details!

+
+ {{hero.id}}
+
+ + +
+ +
diff --git a/day5/heroes/src/app/hero-detail.component.js b/day5/heroes/src/app/hero-detail.component.js new file mode 100644 index 0000000..a3684d4 --- /dev/null +++ b/day5/heroes/src/app/hero-detail.component.js @@ -0,0 +1,45 @@ +"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 }); +require("rxjs/add/operator/switchMap"); +var core_1 = require("@angular/core"); +var router_1 = require("@angular/router"); +var common_1 = require("@angular/common"); +var hero_service_1 = require("./hero.service"); +var HeroDetailComponent = (function () { + function HeroDetailComponent(heroService, route, location) { + this.heroService = heroService; + this.route = route; + this.location = location; + } + HeroDetailComponent.prototype.ngOnInit = function () { + var _this = this; + this.route.paramMap + .switchMap(function (params) { return _this.heroService.getHero(+params.get('id')); }) + .subscribe(function (hero) { return _this.hero = hero; }); + }; + HeroDetailComponent.prototype.goBack = function () { + this.location.back(); + }; + return HeroDetailComponent; +}()); +HeroDetailComponent = __decorate([ + core_1.Component({ + selector: 'hero-detail', + templateUrl: './hero-detail.component.html', + styleUrls: ['./hero-detail.component.css'] + }), + __metadata("design:paramtypes", [hero_service_1.HeroService, + router_1.ActivatedRoute, + common_1.Location]) +], HeroDetailComponent); +exports.HeroDetailComponent = HeroDetailComponent; +//# sourceMappingURL=hero-detail.component.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/hero-detail.component.js.map b/day5/heroes/src/app/hero-detail.component.js.map new file mode 100644 index 0000000..b8af7ce --- /dev/null +++ b/day5/heroes/src/app/hero-detail.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hero-detail.component.js","sourceRoot":"","sources":["hero-detail.component.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,uCAAqC;AACrC,sCAAyD;AACzD,0CAA2D;AAC3D,0CAA2D;AAG3D,+CAA8C;AAM9C,IAAa,mBAAmB;IAG9B,6BACU,WAAwB,EACxB,KAAqB,EACrB,QAAkB;QAFlB,gBAAW,GAAX,WAAW,CAAa;QACxB,UAAK,GAAL,KAAK,CAAgB;QACrB,aAAQ,GAAR,QAAQ,CAAU;IACzB,CAAC;IAEJ,sCAAQ,GAAR;QAAA,iBAIC;QAHC,IAAI,CAAC,KAAK,CAAC,QAAQ;aAChB,SAAS,CAAC,UAAC,MAAgB,IAAK,OAAA,KAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAA3C,CAA2C,CAAC;aAC5E,SAAS,CAAC,UAAA,IAAI,IAAI,OAAA,KAAI,CAAC,IAAI,GAAG,IAAI,EAAhB,CAAgB,CAAC,CAAC;IACzC,CAAC;IAED,oCAAM,GAAN;QACE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IACH,0BAAC;AAAD,CAAC,AAlBD,IAkBC;AAlBY,mBAAmB;IAL/B,gBAAS,CAAC;QACT,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,8BAA8B;QAC3C,SAAS,EAAE,CAAE,6BAA6B,CAAE;KAC7C,CAAC;qCAKuB,0BAAW;QACjB,uBAAc;QACX,iBAAQ;GANjB,mBAAmB,CAkB/B;AAlBY,kDAAmB"} \ No newline at end of file diff --git a/day5/heroes/src/app/hero-detail.component.ts b/day5/heroes/src/app/hero-detail.component.ts new file mode 100644 index 0000000..8a00edd --- /dev/null +++ b/day5/heroes/src/app/hero-detail.component.ts @@ -0,0 +1,31 @@ +import 'rxjs/add/operator/switchMap'; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, ParamMap } from '@angular/router'; +import { Location } from '@angular/common'; + +import { Hero } from './hero'; +import { HeroService } from './hero.service'; +@Component({ + selector: 'hero-detail', + templateUrl: './hero-detail.component.html', + styleUrls: [ './hero-detail.component.css' ] +}) +export class HeroDetailComponent implements OnInit { + hero: Hero; + + constructor( + private heroService: HeroService, + private route: ActivatedRoute, + private location: Location + ) {} + + ngOnInit(): void { + this.route.paramMap + .switchMap((params: ParamMap) => this.heroService.getHero(+params.get('id'))) + .subscribe(hero => this.hero = hero); + } + + goBack(): void { + this.location.back(); + } +} diff --git a/day5/heroes/src/app/hero.js b/day5/heroes/src/app/hero.js new file mode 100644 index 0000000..da5dd1e --- /dev/null +++ b/day5/heroes/src/app/hero.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Hero = (function () { + function Hero() { + } + return Hero; +}()); +exports.Hero = Hero; +//# sourceMappingURL=hero.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/hero.js.map b/day5/heroes/src/app/hero.js.map new file mode 100644 index 0000000..d84dacc --- /dev/null +++ b/day5/heroes/src/app/hero.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hero.js","sourceRoot":"","sources":["hero.ts"],"names":[],"mappings":";;AAAA;IAAA;IAGA,CAAC;IAAD,WAAC;AAAD,CAAC,AAHD,IAGC;AAHY,oBAAI"} \ No newline at end of file diff --git a/day5/heroes/src/app/hero.service.js b/day5/heroes/src/app/hero.service.js new file mode 100644 index 0000000..59115a3 --- /dev/null +++ b/day5/heroes/src/app/hero.service.js @@ -0,0 +1,34 @@ +"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 mock_heroes_1 = require("./mock-heroes"); +var core_1 = require("@angular/core"); +var HeroService = (function () { + function HeroService() { + } + HeroService.prototype.getHeroes = function () { + return Promise.resolve(mock_heroes_1.HEROES); + }; + HeroService.prototype.getHeroesSlowly = function () { + var _this = this; + return new Promise(function (resolve) { + // Simulate server latency with 2 second delay + setTimeout(function () { return resolve(_this.getHeroes()); }, 2000); + }); + }; + HeroService.prototype.getHero = function (id) { + return this.getHeroes() + .then(function (heroes) { return heroes.find(function (hero) { return hero.id === id; }); }); + }; + return HeroService; +}()); +HeroService = __decorate([ + core_1.Injectable() +], HeroService); +exports.HeroService = HeroService; +//# sourceMappingURL=hero.service.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/hero.service.js.map b/day5/heroes/src/app/hero.service.js.map new file mode 100644 index 0000000..23ed471 --- /dev/null +++ b/day5/heroes/src/app/hero.service.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hero.service.js","sourceRoot":"","sources":["hero.service.ts"],"names":[],"mappings":";;;;;;;;AACA,6CAAuC;AACvC,sCAA2C;AAG3C,IAAa,WAAW;IAAxB;IAgBA,CAAC;IAfC,+BAAS,GAAT;QACE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAM,CAAC,CAAC;IACjC,CAAC;IAED,qCAAe,GAAf;QAAA,iBAKC;QAJC,MAAM,CAAC,IAAI,OAAO,CAAC,UAAA,OAAO;YACxB,8CAA8C;YAC9C,UAAU,CAAC,cAAM,OAAA,OAAO,CAAC,KAAI,CAAC,SAAS,EAAE,CAAC,EAAzB,CAAyB,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6BAAO,GAAP,UAAQ,EAAU;QAChB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE;aACX,IAAI,CAAC,UAAA,MAAM,IAAI,OAAA,MAAM,CAAC,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,CAAC,EAAE,KAAK,EAAE,EAAd,CAAc,CAAC,EAAnC,CAAmC,CAAC,CAAC;IAClE,CAAC;IACH,kBAAC;AAAD,CAAC,AAhBD,IAgBC;AAhBY,WAAW;IADvB,iBAAU,EAAE;GACA,WAAW,CAgBvB;AAhBY,kCAAW"} \ No newline at end of file diff --git a/day5/heroes/src/app/hero.service.ts b/day5/heroes/src/app/hero.service.ts new file mode 100644 index 0000000..8687f2d --- /dev/null +++ b/day5/heroes/src/app/hero.service.ts @@ -0,0 +1,22 @@ +import { Hero } from './hero'; +import { HEROES } from './mock-heroes'; +import { Injectable } from '@angular/core'; + +@Injectable() +export class HeroService { + getHeroes(): Promise { + return Promise.resolve(HEROES); + } + + getHeroesSlowly(): Promise { + return new Promise(resolve => { + // Simulate server latency with 2 second delay + setTimeout(() => resolve(this.getHeroes()), 2000); + }); + } + + getHero(id: number): Promise { + return this.getHeroes() + .then(heroes => heroes.find(hero => hero.id === id)); + } +} diff --git a/day5/heroes/src/app/hero.ts b/day5/heroes/src/app/hero.ts new file mode 100644 index 0000000..e3eac51 --- /dev/null +++ b/day5/heroes/src/app/hero.ts @@ -0,0 +1,4 @@ +export class Hero { + id: number; + name: string; +} diff --git a/day5/heroes/src/app/heroes.component.css b/day5/heroes/src/app/heroes.component.css new file mode 100644 index 0000000..35e45af --- /dev/null +++ b/day5/heroes/src/app/heroes.component.css @@ -0,0 +1,59 @@ +.selected { + background-color: #CFD8DC !important; + color: white; +} +.heroes { + margin: 0 0 2em 0; + list-style-type: none; + padding: 0; + width: 15em; +} +.heroes li { + cursor: pointer; + position: relative; + left: 0; + background-color: #EEE; + margin: .5em; + padding: .3em 0; + height: 1.6em; + border-radius: 4px; +} +.heroes li:hover { + color: #607D8B; + background-color: #DDD; + left: .1em; +} +.heroes li.selected:hover { + background-color: #BBD8DC !important; + color: white; +} +.heroes .text { + position: relative; + top: -3px; +} +.heroes .badge { + display: inline-block; + font-size: small; + color: white; + padding: 0.8em 0.7em 0 0.7em; + background-color: #607D8B; + line-height: 1em; + position: relative; + left: -1px; + top: -4px; + height: 1.8em; + margin-right: .8em; + border-radius: 4px 0 0 4px; +} +button { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; +} +button:hover { + background-color: #cfd8dc; +} diff --git a/day5/heroes/src/app/heroes.component.html b/day5/heroes/src/app/heroes.component.html new file mode 100644 index 0000000..76e0f81 --- /dev/null +++ b/day5/heroes/src/app/heroes.component.html @@ -0,0 +1,14 @@ +

My Heroes

+
    +
  • + {{hero.id}} {{hero.name}} +
  • +
+
+

+ {{selectedHero.name | uppercase}} is my hero +

+ +
diff --git a/day5/heroes/src/app/heroes.component.js b/day5/heroes/src/app/heroes.component.js new file mode 100644 index 0000000..8aa2810 --- /dev/null +++ b/day5/heroes/src/app/heroes.component.js @@ -0,0 +1,45 @@ +"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 router_1 = require("@angular/router"); +var hero_service_1 = require("./hero.service"); +var HeroesComponent = (function () { + function HeroesComponent(router, heroService) { + this.router = router; + this.heroService = heroService; + } + HeroesComponent.prototype.getHeroes = function () { + var _this = this; + this.heroService.getHeroes().then(function (heroes) { return _this.heroes = heroes; }); + }; + HeroesComponent.prototype.ngOnInit = function () { + this.getHeroes(); + }; + HeroesComponent.prototype.onSelect = function (hero) { + this.selectedHero = hero; + }; + HeroesComponent.prototype.gotoDetail = function () { + this.router.navigate(['/detail', this.selectedHero.id]); + }; + return HeroesComponent; +}()); +HeroesComponent = __decorate([ + core_1.Component({ + selector: 'my-heroes', + templateUrl: './heroes.component.html', + styleUrls: ['./heroes.component.css'] + }), + __metadata("design:paramtypes", [router_1.Router, + hero_service_1.HeroService]) +], HeroesComponent); +exports.HeroesComponent = HeroesComponent; +//# sourceMappingURL=heroes.component.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/heroes.component.js.map b/day5/heroes/src/app/heroes.component.js.map new file mode 100644 index 0000000..26df72d --- /dev/null +++ b/day5/heroes/src/app/heroes.component.js.map @@ -0,0 +1 @@ +{"version":3,"file":"heroes.component.js","sourceRoot":"","sources":["heroes.component.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,sCAAkD;AAClD,0CAAyC;AAGzC,+CAA6C;AAO7C,IAAa,eAAe;IAI1B,yBACU,MAAc,EACd,WAAwB;QADxB,WAAM,GAAN,MAAM,CAAQ;QACd,gBAAW,GAAX,WAAW,CAAa;IAAI,CAAC;IAEvC,mCAAS,GAAT;QAAA,iBAEC;QADC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,UAAA,MAAM,IAAI,OAAA,KAAI,CAAC,MAAM,GAAG,MAAM,EAApB,CAAoB,CAAC,CAAC;IACpE,CAAC;IAED,kCAAQ,GAAR;QACE,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED,kCAAQ,GAAR,UAAS,IAAU;QACjB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,oCAAU,GAAV;QACE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IACH,sBAAC;AAAD,CAAC,AAvBD,IAuBC;AAvBY,eAAe;IAL3B,gBAAS,CAAC;QACT,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,yBAAyB;QACtC,SAAS,EAAE,CAAE,wBAAwB,CAAE;KACxC,CAAC;qCAMkB,eAAM;QACD,0BAAW;GANvB,eAAe,CAuB3B;AAvBY,0CAAe"} \ No newline at end of file diff --git a/day5/heroes/src/app/heroes.component.ts b/day5/heroes/src/app/heroes.component.ts new file mode 100644 index 0000000..24fb9eb --- /dev/null +++ b/day5/heroes/src/app/heroes.component.ts @@ -0,0 +1,35 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; + +import { Hero } from './hero'; +import { HeroService } from './hero.service'; + +@Component({ + selector: 'my-heroes', + templateUrl: './heroes.component.html', + styleUrls: [ './heroes.component.css' ] +}) +export class HeroesComponent implements OnInit { + heroes: Hero[]; + selectedHero: Hero; + + constructor( + private router: Router, + private heroService: HeroService) { } + + getHeroes(): void { + this.heroService.getHeroes().then(heroes => this.heroes = heroes); + } + + ngOnInit(): void { + this.getHeroes(); + } + + onSelect(hero: Hero): void { + this.selectedHero = hero; + } + + gotoDetail(): void { + this.router.navigate(['/detail', this.selectedHero.id]); + } +} diff --git a/day5/heroes/src/app/mock-heroes.js b/day5/heroes/src/app/mock-heroes.js new file mode 100644 index 0000000..30d3e51 --- /dev/null +++ b/day5/heroes/src/app/mock-heroes.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.HEROES = [ + { id: 11, name: 'Mr. Nice' }, + { id: 12, name: 'Narco' }, + { id: 13, name: 'Bombasto' }, + { id: 14, name: 'Celeritas' }, + { id: 15, name: 'Magneta' }, + { id: 16, name: 'RubberMan' }, + { id: 17, name: 'Dynama' }, + { id: 18, name: 'Dr IQ' }, + { id: 19, name: 'Magma' }, + { id: 20, name: 'Tornado' } +]; +//# sourceMappingURL=mock-heroes.js.map \ No newline at end of file diff --git a/day5/heroes/src/app/mock-heroes.js.map b/day5/heroes/src/app/mock-heroes.js.map new file mode 100644 index 0000000..9d0f8c7 --- /dev/null +++ b/day5/heroes/src/app/mock-heroes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mock-heroes.js","sourceRoot":"","sources":["mock-heroes.ts"],"names":[],"mappings":";;AAEa,QAAA,MAAM,GAAW;IAC5B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;IAC5B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;IACzB,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;IAC5B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;IAC7B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IAC3B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;IAC7B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC1B,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;IACzB,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;IACzB,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;CAC5B,CAAC"} \ No newline at end of file diff --git a/day5/heroes/src/app/mock-heroes.ts b/day5/heroes/src/app/mock-heroes.ts new file mode 100644 index 0000000..e84c2fd --- /dev/null +++ b/day5/heroes/src/app/mock-heroes.ts @@ -0,0 +1,14 @@ +import { Hero } from './hero'; + +export const HEROES: Hero[] = [ + { id: 11, name: 'Mr. Nice' }, + { id: 12, name: 'Narco' }, + { id: 13, name: 'Bombasto' }, + { id: 14, name: 'Celeritas' }, + { id: 15, name: 'Magneta' }, + { id: 16, name: 'RubberMan' }, + { id: 17, name: 'Dynama' }, + { id: 18, name: 'Dr IQ' }, + { id: 19, name: 'Magma' }, + { id: 20, name: 'Tornado' } +]; diff --git a/day5/heroes/src/index.html b/day5/heroes/src/index.html new file mode 100644 index 0000000..f42755a --- /dev/null +++ b/day5/heroes/src/index.html @@ -0,0 +1,25 @@ + + + + + Angular Tour of Heroes + + + + + + + + + + + + + + + + Loading... + + diff --git a/day5/heroes/src/main.js b/day5/heroes/src/main.js new file mode 100644 index 0000000..5390c92 --- /dev/null +++ b/day5/heroes/src/main.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +// main entry point +var platform_browser_dynamic_1 = require("@angular/platform-browser-dynamic"); +var app_module_1 = require("./app/app.module"); +platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule); +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/day5/heroes/src/main.js.map b/day5/heroes/src/main.js.map new file mode 100644 index 0000000..e856605 --- /dev/null +++ b/day5/heroes/src/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":";;AAAA,mBAAmB;AACnB,8EAA2E;AAC3E,+CAA6C;AAE7C,iDAAsB,EAAE,CAAC,eAAe,CAAC,sBAAS,CAAC,CAAC"} \ No newline at end of file diff --git a/day5/heroes/src/main.ts b/day5/heroes/src/main.ts new file mode 100644 index 0000000..7250217 --- /dev/null +++ b/day5/heroes/src/main.ts @@ -0,0 +1,5 @@ +// main entry point +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/day5/heroes/src/styles.css b/day5/heroes/src/styles.css new file mode 100644 index 0000000..a0496ae --- /dev/null +++ b/day5/heroes/src/styles.css @@ -0,0 +1,65 @@ +/* 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; +} +body, input[text], button { + color: #888; + font-family: Cambria, Georgia; +} +a { + cursor: pointer; + cursor: hand; +} +button { + font-family: Arial; + background-color: #eee; + border: none; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + cursor: hand; +} +button:hover { + background-color: #cfd8dc; +} +button:disabled { + background-color: #eee; + color: #aaa; + cursor: auto; +} + +/* Navigation link styles */ +nav a { + padding: 5px 10px; + text-decoration: none; + margin-right: 10px; + margin-top: 10px; + display: inline-block; + background-color: #eee; + border-radius: 4px; +} +nav a:visited, a:link { + color: #607D8B; +} +nav a:hover { + color: #039be5; + background-color: #CFD8DC; +} +nav a.active { + color: #039be5; +} + +/* everywhere else */ +* { + font-family: Arial, Helvetica, sans-serif; +} diff --git a/day5/heroes/src/systemjs-angular-loader.js b/day5/heroes/src/systemjs-angular-loader.js new file mode 100644 index 0000000..8b10054 --- /dev/null +++ b/day5/heroes/src/systemjs-angular-loader.js @@ -0,0 +1,49 @@ +var templateUrlRegex = /templateUrl\s*:(\s*['"`](.*?)['"`]\s*)/gm; +var stylesRegex = /styleUrls *:(\s*\[[^\]]*?\])/g; +var stringRegex = /(['`"])((?:[^\\]\\\1|.)*?)\1/g; + +module.exports.translate = function(load){ + if (load.source.indexOf('moduleId') != -1) return load; + + var url = document.createElement('a'); + url.href = load.address; + + var basePathParts = url.pathname.split('/'); + + basePathParts.pop(); + var basePath = basePathParts.join('/'); + + var baseHref = document.createElement('a'); + baseHref.href = this.baseURL; + baseHref = baseHref.pathname; + + if (!baseHref.startsWith('/base/')) { // it is not karma + basePath = basePath.replace(baseHref, ''); + } + + load.source = load.source + .replace(templateUrlRegex, function(match, quote, url){ + var resolvedUrl = url; + + if (url.startsWith('.')) { + resolvedUrl = basePath + url.substr(1); + } + + return 'templateUrl: "' + resolvedUrl + '"'; + }) + .replace(stylesRegex, function(match, relativeUrls) { + var urls = []; + + while ((match = stringRegex.exec(relativeUrls)) !== null) { + if (match[2].startsWith('.')) { + urls.push('"' + basePath + match[2].substr(1) + '"'); + } else { + urls.push('"' + match[2] + '"'); + } + } + + return "styleUrls: [" + urls.join(', ') + "]"; + }); + + return load; +}; diff --git a/day5/heroes/src/systemjs.config.js b/day5/heroes/src/systemjs.config.js new file mode 100644 index 0000000..ea7a387 --- /dev/null +++ b/day5/heroes/src/systemjs.config.js @@ -0,0 +1,52 @@ +/** + * System configuration for Angular samples + * Adjust as necessary for your application needs. + */ +(function (global) { + System.config({ + paths: { + // paths serve as alias + 'npm:': 'node_modules/' + }, + // map tells the System loader where to look for things + map: { + // our app is within the app folder + 'app': 'app', + + // angular bundles + '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js', + '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js', + '@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/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.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/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js', + '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', + '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js', + '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js', + + // other libraries + 'rxjs': 'npm:rxjs', + 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js' + }, + // packages tells the System loader how to load when no filename and/or no extension + packages: { + app: { + main: './main.js', + defaultExtension: 'js', + meta: { + './*.js': { + loader: 'systemjs-angular-loader.js' + } + } + }, + rxjs: { + defaultExtension: 'js' + } + } + }); +})(this); diff --git a/day5/heroes/src/tsconfig.json b/day5/heroes/src/tsconfig.json new file mode 100644 index 0000000..1a6e599 --- /dev/null +++ b/day5/heroes/src/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ "es2015", "dom" ], + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true, + "typeRoots": [ + "../node_modules/@types/" + ] + }, + "compileOnSave": true, + "exclude": [ + "node_modules/*", + "**/*-aot.ts" + ] +} diff --git a/day5/heroes/tslint.json b/day5/heroes/tslint.json new file mode 100644 index 0000000..276453f --- /dev/null +++ b/day5/heroes/tslint.json @@ -0,0 +1,93 @@ +{ + "rules": { + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [ + true, + "spaces" + ], + "label-position": true, + "label-undefined": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + "static-before-instance", + "variables-before-functions" + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-unused-variable": true, + "no-unreachable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +}