├── src ├── styles.css ├── assets │ └── .gitkeep ├── app │ ├── app.component.css │ ├── models │ │ ├── bookTrackerError.ts │ │ ├── book.ts │ │ └── reader.ts │ ├── app.component.ts │ ├── core │ │ ├── logger.service.ts │ │ ├── plain-logger.service.ts │ │ ├── badge.service.ts │ │ ├── book-tracker-error-handler.service.ts │ │ └── data.service.ts │ ├── add-book │ │ ├── add-book.component.ts │ │ └── add-book.component.html │ ├── add-reader │ │ ├── add-reader.component.ts │ │ └── add-reader.component.html │ ├── edit-book │ │ ├── edit-book.component.ts │ │ └── edit-book.component.html │ ├── app-routing.module.ts │ ├── data.ts │ ├── edit-reader │ │ ├── edit-reader.component.ts │ │ └── edit-reader.component.html │ ├── app.module.ts │ ├── app.component.html │ └── dashboard │ │ ├── dashboard.component.ts │ │ └── dashboard.component.html ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── typings.d.ts ├── index.html ├── main.ts ├── test.ts └── polyfills.ts ├── dist ├── favicon.ico ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff ├── glyphicons-halflings-regular.woff2 ├── index.html ├── runtime.js.map ├── runtime.js ├── main.js.map └── main.js ├── server ├── views │ ├── index.jade │ ├── error.jade │ └── layout.jade ├── routes │ ├── index.js │ ├── errors.js │ ├── books.js │ └── readers.js └── data │ ├── readers.json │ └── books.json ├── e2e ├── app.po.ts ├── tsconfig.e2e.json └── app.e2e-spec.ts ├── .editorconfig ├── tsconfig.app.json ├── tsconfig.spec.json ├── README.md ├── .gitignore ├── .browserslistrc ├── protractor.conf.js ├── tsconfig.json ├── karma.conf.js ├── package.json ├── server.js ├── tslint.json └── angular.json /src/styles.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/dist/favicon.ico -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /server/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /server/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/dist/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/dist/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/dist/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-http-communication/HEAD/dist/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/app/models/bookTrackerError.ts: -------------------------------------------------------------------------------- 1 | export class BookTrackerError { 2 | errorNumber: number; 3 | message: string; 4 | friendlyMessage: string; 5 | } -------------------------------------------------------------------------------- /src/app/models/book.ts: -------------------------------------------------------------------------------- 1 | export class Book { 2 | bookID: number; 3 | title: string; 4 | author: string; 5 | publicationYear: number; 6 | } 7 | -------------------------------------------------------------------------------- /server/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content -------------------------------------------------------------------------------- /src/app/models/reader.ts: -------------------------------------------------------------------------------- 1 | export class Reader { 2 | readerID: number; 3 | name: string; 4 | weeklyReadingGoal: number; 5 | totalMinutesRead: number; 6 | } 7 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'app'; 10 | } 11 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class BooktrackerPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Tracker 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { BooktrackerPage } from './app.po'; 2 | 3 | describe('booktracker App', () => { 4 | let page: BooktrackerPage; 5 | 6 | beforeEach(() => { 7 | page = new BooktrackerPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to app!!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/app/core/logger.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class LoggerService { 7 | log(message: string): void { 8 | const timeString: String = new Date().toLocaleTimeString(); 9 | console.log(`${message} (${timeString})`); 10 | } 11 | 12 | error(message: string): void { 13 | console.error(`ERROR: ${message}`); 14 | } 15 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/app/core/plain-logger.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | import { LoggerService } from './logger.service'; 4 | 5 | @Injectable() 6 | export class PlainLoggerService implements LoggerService { 7 | 8 | log(message: string): void { 9 | console.log(message); 10 | } 11 | 12 | error(message: string): void { 13 | console.log(message); 14 | } 15 | 16 | constructor() { } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular HTTP Communication 2 | 3 | This is the official repository for my Pluralsight course titled *Angular HTTP Communication*. 4 | There are separate branches named after the modules in the course that contain the code as it 5 | exists at the end of that module. 6 | 7 | I will update this repo below with any problems or small issues reported between updates to the actual course. 8 | 9 | Thanks for watching and good luck on your Angular projects! 10 | -------------------------------------------------------------------------------- /server/routes/errors.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var fs = require('fs'); 3 | var router = express.Router(); 4 | 5 | /* GET all books and POST new readers */ 6 | router.route('/500') 7 | .get(function(req, res) { 8 | res.status(500).send('Book Tracker server error.'); 9 | }); 10 | 11 | router.route('/401') 12 | .get(function(req, res) { 13 | res.status(401).send('Book Tracker unauthorized.'); 14 | }); 15 | 16 | module.exports = router; -------------------------------------------------------------------------------- /server/data/readers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "readerID": 1, 4 | "name": "Marie", 5 | "weeklyReadingGoal": 350, 6 | "totalMinutesRead": 5600 7 | }, 8 | { 9 | "readerID": 2, 10 | "name": "Daniel", 11 | "weeklyReadingGoal": 210, 12 | "totalMinutesRead": 3000 13 | }, 14 | { 15 | "readerID": 3, 16 | "name": "Lanier", 17 | "weeklyReadingGoal": 140, 18 | "totalMinutesRead": 600 19 | } 20 | ] -------------------------------------------------------------------------------- /src/app/core/badge.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class BadgeService { 7 | 8 | constructor() { } 9 | 10 | getReaderBadge(minutesRead: number): string { 11 | 12 | if (minutesRead > 5000) { 13 | return 'Book Worm'; 14 | } 15 | else if (minutesRead > 2500) { 16 | return 'Page Turner'; 17 | } 18 | else { 19 | return 'Getting Started'; 20 | } 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Tracker 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | node_modules/ 4 | .vscode/ 5 | 6 | # compiled output 7 | /tmp 8 | /out-tsc 9 | 10 | # dependencies 11 | 12 | # IDEs and editors 13 | /.idea 14 | .project 15 | .classpath 16 | .c9/ 17 | *.launch 18 | .settings/ 19 | *.sublime-workspace 20 | 21 | # IDE - VSCode 22 | 23 | # misc 24 | /.sass-cache 25 | /connect.lock 26 | /coverage 27 | /libpeerconnection.log 28 | npm-debug.log 29 | testem.log 30 | /typings 31 | 32 | # e2e 33 | /e2e/*.js 34 | /e2e/*.map 35 | 36 | # System Files 37 | .DS_Store 38 | Thumbs.db 39 | -------------------------------------------------------------------------------- /src/app/add-book/add-book.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { Book } from "app/models/book"; 4 | 5 | @Component({ 6 | selector: 'app-add-book', 7 | templateUrl: './add-book.component.html', 8 | styles: [] 9 | }) 10 | export class AddBookComponent implements OnInit { 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { } 15 | 16 | saveBook(formValues: any): void { 17 | let newBook: Book = formValues; 18 | newBook.bookID = 0; 19 | console.log(newBook); 20 | console.warn('Save new book not yet implemented.'); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/add-reader/add-reader.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { Reader } from "app/models/reader"; 4 | 5 | @Component({ 6 | selector: 'app-add-reader', 7 | templateUrl: './add-reader.component.html', 8 | styles: [] 9 | }) 10 | export class AddReaderComponent implements OnInit { 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { } 15 | 16 | saveReader(formValues: any): void { 17 | let newReader: Reader = formValues; 18 | newReader.readerID = 0; 19 | console.log(newReader); 20 | console.warn('Save new reader not yet implemented.'); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/core/book-tracker-error-handler.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, ErrorHandler } from '@angular/core'; 2 | import { BookTrackerError } from 'app/models/bookTrackerError'; 3 | 4 | @Injectable() 5 | export class BookTrackerErrorHandlerService implements ErrorHandler { 6 | 7 | handleError(error: any): void { 8 | let customError: BookTrackerError = new BookTrackerError(); 9 | customError.errorNumber = 200; 10 | customError.message = (error).message; 11 | customError.friendlyMessage = 'An error occurred. Please try again.'; 12 | 13 | console.log(customError); 14 | } 15 | 16 | constructor() { } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /src/app/core/data.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | import { allBooks, allReaders } from 'app/data'; 4 | import { Reader } from "app/models/reader"; 5 | import { Book } from "app/models/book"; 6 | import { BookTrackerError } from 'app/models/bookTrackerError'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class DataService { 12 | 13 | constructor() { } 14 | 15 | mostPopularBook: Book = allBooks[0]; 16 | 17 | setMostPopularBook(popularBook: Book): void { 18 | this.mostPopularBook = popularBook; 19 | } 20 | 21 | getAllReaders(): Reader[] { 22 | return allReaders; 23 | } 24 | 25 | getReaderById(id: number): Reader { 26 | return allReaders.find(reader => reader.readerID === id); 27 | } 28 | 29 | getAllBooks(): Book[] { 30 | return allBooks; 31 | } 32 | 33 | getBookById(id: number): Book { 34 | return allBooks.find(book => book.bookID === id); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./src/", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "strictPropertyInitialization": false, 10 | "strictNullChecks": false, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2015", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "strictInjectionParameters": true, 28 | "strictInputAccessModifiers": true, 29 | "strictTemplates": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/edit-book/edit-book.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | 4 | import { Book } from 'app/models/book'; 5 | import { DataService } from 'app/core/data.service'; 6 | 7 | @Component({ 8 | selector: 'app-edit-book', 9 | templateUrl: './edit-book.component.html', 10 | styles: [] 11 | }) 12 | export class EditBookComponent implements OnInit { 13 | 14 | selectedBook: Book; 15 | 16 | constructor(private route: ActivatedRoute, 17 | private dataService: DataService) { } 18 | 19 | ngOnInit() { 20 | let bookID: number = parseInt(this.route.snapshot.params['id']); 21 | this.selectedBook = this.dataService.getBookById(bookID); 22 | } 23 | 24 | setMostPopular(): void { 25 | this.dataService.setMostPopularBook(this.selectedBook); 26 | } 27 | 28 | saveChanges(): void { 29 | console.warn('Save changes to book not yet implemented.'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /server/data/books.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "bookID": 1, 4 | "title": "Goodnight Moon", 5 | "author": "Margaret Wise Brown", 6 | "publicationYear": "1953" 7 | }, 8 | { 9 | "bookID": 2, 10 | "title": "Winnie-the-Pooh", 11 | "author": "A. A. Milne", 12 | "publicationYear": "1926" 13 | }, 14 | { 15 | "bookID": 3, 16 | "title": "Where the Wild Things Are", 17 | "author": "Maurice Sendak", 18 | "publicationYear": "1963" 19 | }, 20 | { 21 | "bookID": 4, 22 | "title": "The Hobbit", 23 | "author": "J. R. R. Tolkien", 24 | "publicationYear": "1937" 25 | }, 26 | { 27 | "bookID": 5, 28 | "title": "Curious George", 29 | "author": "H. A. Rey", 30 | "publicationYear": "1941" 31 | }, 32 | { 33 | "bookID": 6, 34 | "title": "Alice's Adventures in Wonderland", 35 | "author": "Lewis Carroll", 36 | "publicationYear": "1865" 37 | } 38 | ] -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | import { AddBookComponent } from "app/add-book/add-book.component"; 5 | import { AddReaderComponent } from "app/add-reader/add-reader.component"; 6 | import { DashboardComponent } from "app/dashboard/dashboard.component"; 7 | import { EditBookComponent } from "app/edit-book/edit-book.component"; 8 | import { EditReaderComponent } from "app/edit-reader/edit-reader.component"; 9 | 10 | const routes: Routes = [ 11 | { path: 'dashboard', component: DashboardComponent }, 12 | { path: 'addbook', component: AddBookComponent }, 13 | { path: 'addreader', component: AddReaderComponent }, 14 | { path: 'editreader/:id', component: EditReaderComponent }, 15 | { path: 'editbook/:id', component: EditBookComponent }, 16 | { path: '', redirectTo: 'dashboard', pathMatch: 'full' } 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forRoot(routes)], 21 | exports: [RouterModule] 22 | }) 23 | export class AppRoutingModule { } 24 | -------------------------------------------------------------------------------- /src/app/data.ts: -------------------------------------------------------------------------------- 1 | import { Book } from "app/models/book"; 2 | import { Reader } from "app/models/reader"; 3 | 4 | export const allReaders: Reader[] = [ 5 | { readerID: 1, name: 'Marie', weeklyReadingGoal: 400, totalMinutesRead: 5600 }, 6 | { readerID: 2, name: 'Daniel', weeklyReadingGoal: 210, totalMinutesRead: 3000 }, 7 | { readerID: 3, name: 'Lanier', weeklyReadingGoal: 140, totalMinutesRead: 600 } 8 | ]; 9 | 10 | export const allBooks: Book[] = [ 11 | { bookID: 1, title: 'Goodnight Moon', author: 'Margaret Wise Brown', publicationYear: 1953 }, 12 | { bookID: 2, title: 'Winnie-the-Pooh', author: 'A. A. Milne', publicationYear: 1926 }, 13 | { bookID: 3, title: 'Where the Wild Things Are', author: 'Maurice Sendak', publicationYear: 1963 }, 14 | { bookID: 4, title: 'The Hobbit', author: 'J. R. R. Tolkien', publicationYear: 1937 }, 15 | { bookID: 5, title: 'Curious George', author: 'H. A. Rey', publicationYear: 1941 }, 16 | { bookID: 6, title: 'Alice\'s Adventures in Wonderland', author: 'Lewis Carroll', publicationYear: 1865 }, 17 | ]; -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /src/app/edit-reader/edit-reader.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | 4 | import { Reader } from "app/models/reader"; 5 | import { DataService } from 'app/core/data.service'; 6 | import { BadgeService } from 'app/core/badge.service'; 7 | 8 | @Component({ 9 | selector: 'app-edit-reader', 10 | templateUrl: './edit-reader.component.html', 11 | styles: [], 12 | providers: [BadgeService] 13 | }) 14 | export class EditReaderComponent implements OnInit { 15 | 16 | selectedReader: Reader; 17 | currentBadge: string; 18 | 19 | constructor(private route: ActivatedRoute, 20 | private dataService: DataService, 21 | private badgeService: BadgeService) { } 22 | 23 | ngOnInit() { 24 | let readerID: number = parseInt(this.route.snapshot.params['id']); 25 | this.selectedReader = this.dataService.getReaderById(readerID); 26 | this.currentBadge = this.badgeService.getReaderBadge(this.selectedReader.totalMinutesRead); 27 | } 28 | 29 | saveChanges() { 30 | console.warn('Save reader not yet implemented.'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { ErrorHandler, NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | 5 | import { AddBookComponent } from './add-book/add-book.component'; 6 | import { AddReaderComponent } from './add-reader/add-reader.component'; 7 | import { AppComponent } from './app.component'; 8 | import { AppRoutingModule } from './app-routing.module'; 9 | import { DashboardComponent } from './dashboard/dashboard.component'; 10 | import { EditBookComponent } from './edit-book/edit-book.component'; 11 | import { EditReaderComponent } from './edit-reader/edit-reader.component'; 12 | import { BookTrackerErrorHandlerService } from './core/book-tracker-error-handler.service'; 13 | 14 | @NgModule({ 15 | declarations: [ 16 | AppComponent, 17 | DashboardComponent, 18 | AddBookComponent, 19 | EditReaderComponent, 20 | EditBookComponent, 21 | AddReaderComponent 22 | ], 23 | providers: [ 24 | { provide: ErrorHandler, useClass: BookTrackerErrorHandlerService } 25 | ], 26 | imports: [ 27 | BrowserModule, 28 | AppRoutingModule, 29 | FormsModule 30 | ], 31 | bootstrap: [AppComponent] 32 | }) 33 | export class AppModule { } 34 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Observable } from 'rxjs'; 3 | import { Title } from '@angular/platform-browser'; 4 | 5 | import { Book } from "app/models/book"; 6 | import { Reader } from "app/models/reader"; 7 | import { DataService } from 'app/core/data.service'; 8 | 9 | @Component({ 10 | selector: 'app-dashboard', 11 | templateUrl: './dashboard.component.html', 12 | styles: [] 13 | }) 14 | export class DashboardComponent implements OnInit { 15 | 16 | allBooks: Book[]; 17 | allReaders: Reader[]; 18 | mostPopularBook: Book; 19 | 20 | constructor(private dataService: DataService, 21 | private title: Title) { } 22 | 23 | ngOnInit() { 24 | this.allBooks = this.dataService.getAllBooks(); 25 | this.allReaders = this.dataService.getAllReaders(); 26 | this.mostPopularBook = this.dataService.mostPopularBook; 27 | 28 | this.title.setTitle(`Book Tracker`); 29 | } 30 | 31 | deleteBook(bookID: number): void { 32 | console.warn(`Delete book not yet implemented (bookID: ${bookID}).`); 33 | } 34 | 35 | deleteReader(readerID: number): void { 36 | console.warn(`Delete reader not yet implemented (readerID: ${readerID}).`); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/app/add-book/add-book.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | Add New Book 6 |
7 | 8 |
9 | 10 |
11 |
12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 |
-------------------------------------------------------------------------------- /src/app/add-reader/add-reader.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | Add Reader 6 |
7 | 8 |
9 | 10 |
11 |
12 |
13 | 14 |
15 | 16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 |
-------------------------------------------------------------------------------- /src/app/dashboard/dashboard.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

All Books

7 |
8 |
9 |
  • 10 | {{book.title}} 11 | Edit 12 | Delete 13 |
  • 14 |
    15 |
    16 |
    17 |
    18 |
    19 |
    20 |
    21 |
    22 |

    All Readers

    23 |
    24 |
    25 |
  • 26 | {{reader.name}} 27 | Edit 28 | Delete 29 |
  • 30 |
    31 |
    32 |
    33 |
    34 |
    35 |
    36 |
    37 |
    38 |

    Most Popular Book

    39 |
    40 |
    41 | {{mostPopularBook.title}} by {{mostPopularBook.author}} 42 |
    43 |
    44 |
    45 |
    46 |
    -------------------------------------------------------------------------------- /src/app/edit-book/edit-book.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Edit Book 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | 27 | 28 |
    29 |
    30 |
    31 |
    32 |
    33 |
    -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "booktracker", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "concurrently --kill-others \"ng build --watch --no-delete-output-path\" \"node server.js\"", 8 | "build": "ng build && node server.js", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "12.0.5", 16 | "@angular/common": "12.0.5", 17 | "@angular/compiler": "12.0.5", 18 | "@angular/core": "12.0.5", 19 | "@angular/forms": "12.0.5", 20 | "@angular/platform-browser": "12.0.5", 21 | "@angular/platform-browser-dynamic": "12.0.5", 22 | "@angular/router": "12.0.5", 23 | "rxjs": "6.6.0", 24 | "tslib": "2.0.0", 25 | "zone.js": "~0.11.4", 26 | "body-parser": "1.19.0", 27 | "bootstrap": "3.4.1", 28 | "cookie-parser": "1.4.5", 29 | "debug": "4.3.1", 30 | "express": "4.17.1", 31 | "morgan": "1.10.0", 32 | "serve-favicon": "2.5.0" 33 | }, 34 | "devDependencies": { 35 | "@angular-devkit/build-angular": "12.0.5", 36 | "@angular/cli": "12.0.5", 37 | "@angular/compiler-cli": "12.0.5", 38 | "@types/jasmine": "3.6.0", 39 | "@types/node": "12.11.1", 40 | "codelyzer": "6.0.0", 41 | "jasmine-core": "3.6.0", 42 | "jasmine-spec-reporter": "5.0.0", 43 | "karma": "6.3.4", 44 | "karma-chrome-launcher": "3.1.0", 45 | "karma-coverage": "2.0.3", 46 | "karma-jasmine": "4.0.0", 47 | "karma-jasmine-html-reporter": "1.5.0", 48 | "protractor": "7.0.0", 49 | "ts-node": "8.3.0", 50 | "tslint": "6.1.0", 51 | "typescript": "4.2.4", 52 | "concurrently": "5.3.0" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/edit-reader/edit-reader.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Edit Reader 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 | 25 |
    26 | 27 |
    28 | {{ currentBadge }} 29 |
    30 |
    31 | 32 | 33 |
    34 |
    35 | 36 |
    37 |
    38 |
    39 |
    40 |
    41 |
    -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var routes = require('./server/routes/index'); 9 | var readers = require('./server/routes/readers'); 10 | var books = require('./server/routes/books'); 11 | var errors = require('./server/routes/errors'); 12 | 13 | var app = express(); 14 | 15 | // view engine setup 16 | app.set('views', path.join(__dirname, '/server/views')); 17 | app.set('view engine', 'jade'); 18 | 19 | app.use(favicon(path.join(__dirname, 'dist/favicon.ico'))); 20 | app.use(logger('dev')); 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded({ extended: false })); 23 | app.use(cookieParser()); 24 | app.use(express.static(path.join(__dirname, 'dist'))); 25 | 26 | // app.use('/', routes); 27 | app.use('/api/readers', readers); 28 | app.use('/api/books', books); 29 | app.use('/api/errors', errors); 30 | app.get('*', function(req, res) { 31 | res.sendFile(path.join(__dirname, 'dist/index.html')); 32 | }); 33 | 34 | // catch 404 and forward to error handler 35 | app.use(function(req, res, next) { 36 | var err = new Error('Not Found'); 37 | err.status = 404; 38 | next(err); 39 | }); 40 | 41 | // error handlers 42 | 43 | // development error handler 44 | // will print stacktrace 45 | if (app.get('env') === 'development') { 46 | app.use(function(err, req, res, next) { 47 | res.status(err.status || 500); 48 | res.render('error', { 49 | message: err.message, 50 | error: err 51 | }); 52 | }); 53 | } 54 | 55 | // production error handler 56 | // no stacktraces leaked to user 57 | app.use(function(err, req, res, next) { 58 | res.status(err.status || 500); 59 | res.render('error', { 60 | message: err.message, 61 | error: {} 62 | }); 63 | }); 64 | 65 | var debug = require('debug')('server'); 66 | 67 | app.set('port', process.env.PORT || 3000); 68 | 69 | app.listen(app.get('port')); 70 | 71 | console.log('Listening on port: ' + app.get('port')); 72 | 73 | module.exports = app; 74 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js'; // Included with Angular CLI. 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | -------------------------------------------------------------------------------- /server/routes/books.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var fs = require('fs'); 3 | var datafile = 'server/data/books.json'; 4 | var router = express.Router(); 5 | 6 | /* GET all books and POST new books */ 7 | router.route('/') 8 | .get(function(req, res) { 9 | var data = getBookData(); 10 | res.send(data); 11 | }) 12 | 13 | .post(function(req, res) { 14 | 15 | var data = getBookData(); 16 | var nextID = getNextAvailableID(data); 17 | 18 | var newBook = { 19 | bookID: nextID, 20 | title: req.body.title, 21 | author: req.body.author, 22 | publicationYear: req.body.publicationYear 23 | }; 24 | 25 | data.push(newBook); 26 | 27 | saveBookData(data); 28 | 29 | // res.set('Content-Type', 'application/json'); 30 | res.status(201).send(newBook); 31 | }); 32 | 33 | 34 | /* GET, PUT and DELETE individual books */ 35 | router.route('/:id') 36 | 37 | .get(function(req, res) { 38 | 39 | //console.log('Retrieving book id: ' + req.params.id); 40 | 41 | var data = getBookData(); 42 | 43 | var matchingBooks = data.filter(function(item) { 44 | return item.bookID == req.params.id; 45 | }); 46 | 47 | if(matchingBooks.length === 0) { 48 | res.sendStatus(404); 49 | } else { 50 | res.send(matchingBooks[0]); 51 | } 52 | }) 53 | 54 | .delete(function(req, res) { 55 | 56 | var data = getBookData(); 57 | 58 | var pos = data.map(function(e) { 59 | return e.bookID; 60 | }).indexOf(parseInt(req.params.id, 10)); 61 | 62 | if (pos > -1) { 63 | data.splice(pos, 1); 64 | } else { 65 | res.sendStatus(404); 66 | } 67 | 68 | saveBookData(data); 69 | res.sendStatus(204); 70 | 71 | }) 72 | 73 | .put(function(req, res) { 74 | 75 | var data = getBookData(); 76 | 77 | var matchingBooks = data.filter(function(item) { 78 | return item.bookID == req.params.id; 79 | }); 80 | 81 | if(matchingBooks.length === 0) { 82 | res.sendStatus(404); 83 | } else { 84 | 85 | var bookToUpdate = matchingBooks[0]; 86 | bookToUpdate.title = req.body.title; 87 | bookToUpdate.author = req.body.author; 88 | bookToUpdate.publicationYear = req.body.publicationYear; 89 | 90 | saveBookData(data); 91 | res.sendStatus(204); 92 | 93 | } 94 | }); 95 | 96 | function getNextAvailableID(allBooks) { 97 | 98 | var maxID = 0; 99 | 100 | allBooks.forEach(function(element, index, array) { 101 | 102 | if(element.bookID > maxID) { 103 | maxID = element.bookID; 104 | } 105 | 106 | }); 107 | 108 | return ++maxID; 109 | 110 | } 111 | 112 | function getBookData() { 113 | var data = fs.readFileSync(datafile, 'utf8'); 114 | return JSON.parse(data); 115 | } 116 | 117 | function saveBookData(data) { 118 | fs.writeFile(datafile, JSON.stringify(data, null, 4), function (err) { 119 | if (err) { 120 | console.log(err); 121 | } 122 | }); 123 | } 124 | 125 | module.exports = router; 126 | -------------------------------------------------------------------------------- /server/routes/readers.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var fs = require('fs'); 3 | var datafile = 'server/data/readers.json'; 4 | var router = express.Router(); 5 | 6 | /* GET all books and POST new readers */ 7 | router.route('/') 8 | .get(function(req, res) { 9 | var data = getReaderData(); 10 | res.send(data); 11 | }) 12 | 13 | .post(function(req, res) { 14 | 15 | var data = getReaderData(); 16 | var nextID = getNextAvailableID(data); 17 | 18 | var newReader = { 19 | readerID: nextID, 20 | name: req.body.name, 21 | weeklyReadingGoal: req.body.weeklyReadingGoal, 22 | totalMinutesRead: req.body.totalMinutesRead 23 | }; 24 | 25 | data.push(newReader); 26 | 27 | saveReaderData(data); 28 | 29 | // res.set('Content-Type', 'application/json'); 30 | res.status(201).send(newReader); 31 | }); 32 | 33 | 34 | /* GET, PUT and DELETE individual readers */ 35 | router.route('/:id') 36 | 37 | .get(function(req, res) { 38 | 39 | //console.log('Retrieving reader id: ' + req.params.id); 40 | 41 | var data = getReaderData(); 42 | 43 | var matchingReaders = data.filter(function(item) { 44 | return item.readerID == req.params.id; 45 | }); 46 | 47 | if(matchingReaders.length === 0) { 48 | res.sendStatus(404); 49 | } else { 50 | res.send(matchingReaders[0]); 51 | } 52 | }) 53 | 54 | .delete(function(req, res) { 55 | 56 | var data = getReaderData(); 57 | 58 | var pos = data.map(function(e) { 59 | return e.readerID; 60 | }).indexOf(parseInt(req.params.id, 10)); 61 | 62 | if (pos > -1) { 63 | data.splice(pos, 1); 64 | } else { 65 | res.sendStatus(404); 66 | } 67 | 68 | saveReaderData(data); 69 | res.sendStatus(204); 70 | 71 | }) 72 | 73 | .put(function(req, res) { 74 | 75 | var data = getReaderData(); 76 | 77 | var matchingReaders = data.filter(function(item) { 78 | return item.readerID == req.params.id; 79 | }); 80 | 81 | if(matchingReaders.length === 0) { 82 | res.sendStatus(404); 83 | } else { 84 | 85 | var readerToUpdate = matchingReaders[0]; 86 | readerToUpdate.name = req.body.name; 87 | readerToUpdate.weeklyReadingGoal = req.body.weeklyReadingGoal; 88 | readerToUpdate.totalMinutesRead = req.body.totalMinutesRead; 89 | 90 | saveReaderData(data); 91 | res.sendStatus(204); 92 | 93 | } 94 | }); 95 | 96 | function getNextAvailableID(allReaders) { 97 | 98 | var maxID = 0; 99 | 100 | allReaders.forEach(function(element, index, array) { 101 | 102 | if(element.readerID > maxID) { 103 | maxID = element.readerID; 104 | } 105 | 106 | }); 107 | 108 | return ++maxID; 109 | 110 | } 111 | 112 | function getReaderData() { 113 | var data = fs.readFileSync(datafile, 'utf8'); 114 | return JSON.parse(data); 115 | } 116 | 117 | function saveReaderData(data) { 118 | fs.writeFile(datafile, JSON.stringify(data, null, 4), function (err) { 119 | if (err) { 120 | console.log(err); 121 | } 122 | }); 123 | } 124 | 125 | module.exports = router; 126 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-return-shorthand": true, 15 | "curly": true, 16 | "deprecation": { 17 | "severity": "warning" 18 | }, 19 | "eofline": true, 20 | "import-blacklist": [ 21 | true, 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": { 26 | "options": [ 27 | "spaces" 28 | ] 29 | }, 30 | "max-classes-per-file": false, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-empty": false, 55 | "no-inferrable-types": [ 56 | true, 57 | "ignore-params" 58 | ], 59 | "no-non-null-assertion": true, 60 | "no-redundant-jsdoc": true, 61 | "no-switch-case-fall-through": true, 62 | "no-var-requires": false, 63 | "object-literal-key-quotes": [ 64 | true, 65 | "as-needed" 66 | ], 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "semicolon": { 72 | "options": [ 73 | "always" 74 | ] 75 | }, 76 | "space-before-function-paren": { 77 | "options": { 78 | "anonymous": "never", 79 | "asyncArrow": "always", 80 | "constructor": "never", 81 | "method": "never", 82 | "named": "never" 83 | } 84 | }, 85 | "typedef": [ 86 | true, 87 | "call-signature" 88 | ], 89 | "typedef-whitespace": { 90 | "options": [ 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | }, 98 | { 99 | "call-signature": "onespace", 100 | "index-signature": "onespace", 101 | "parameter": "onespace", 102 | "property-declaration": "onespace", 103 | "variable-declaration": "onespace" 104 | } 105 | ] 106 | }, 107 | "variable-name": { 108 | "options": [ 109 | "ban-keywords", 110 | "check-format", 111 | "allow-pascal-case" 112 | ] 113 | }, 114 | "whitespace": { 115 | "options": [ 116 | "check-branch", 117 | "check-decl", 118 | "check-operator", 119 | "check-separator", 120 | "check-type", 121 | "check-typecast" 122 | ] 123 | }, 124 | "component-class-suffix": true, 125 | "contextual-lifecycle": true, 126 | "directive-class-suffix": true, 127 | "no-conflicting-lifecycle": true, 128 | "no-host-metadata-property": true, 129 | "no-input-rename": true, 130 | "no-inputs-metadata-property": true, 131 | "no-output-native": true, 132 | "no-output-on-prefix": true, 133 | "no-output-rename": true, 134 | "no-outputs-metadata-property": true, 135 | "template-banana-in-box": true, 136 | "template-no-negated-async": true, 137 | "use-lifecycle-interface": true, 138 | "use-pipe-transform-interface": true, 139 | "directive-selector": [ 140 | true, 141 | "attribute", 142 | "app", 143 | "camelCase" 144 | ], 145 | "component-selector": [ 146 | true, 147 | "element", 148 | "app", 149 | "kebab-case" 150 | ] 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "booktracker": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "architect": { 11 | "build": { 12 | "builder": "@angular-devkit/build-angular:browser", 13 | "options": { 14 | "outputPath": "dist", 15 | "index": "src/index.html", 16 | "main": "src/main.ts", 17 | "tsConfig": "tsconfig.app.json", 18 | "polyfills": "src/polyfills.ts", 19 | "assets": [ 20 | "src/assets", 21 | "src/favicon.ico" 22 | ], 23 | "styles": [ 24 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 25 | "src/styles.css" 26 | ], 27 | "scripts": [], 28 | "aot": false, 29 | "vendorChunk": true, 30 | "extractLicenses": false, 31 | "buildOptimizer": false, 32 | "sourceMap": true, 33 | "optimization": false, 34 | "namedChunks": true 35 | }, 36 | "configurations": { 37 | "production": { 38 | "optimization": true, 39 | "outputHashing": "all", 40 | "sourceMap": false, 41 | "extractCss": true, 42 | "namedChunks": false, 43 | "aot": true, 44 | "extractLicenses": true, 45 | "vendorChunk": false, 46 | "buildOptimizer": true, 47 | "fileReplacements": [ 48 | { 49 | "replace": "src/environments/environment.ts", 50 | "with": "src/environments/environment.prod.ts" 51 | } 52 | ] 53 | } 54 | }, 55 | "defaultConfiguration": "" 56 | }, 57 | "serve": { 58 | "builder": "@angular-devkit/build-angular:dev-server", 59 | "options": { 60 | "browserTarget": "booktracker:build" 61 | }, 62 | "configurations": { 63 | "production": { 64 | "browserTarget": "booktracker:build:production" 65 | } 66 | } 67 | }, 68 | "extract-i18n": { 69 | "builder": "@angular-devkit/build-angular:extract-i18n", 70 | "options": { 71 | "browserTarget": "booktracker:build" 72 | } 73 | }, 74 | "test": { 75 | "builder": "@angular-devkit/build-angular:karma", 76 | "options": { 77 | "main": "src/test.ts", 78 | "karmaConfig": "./karma.conf.js", 79 | "polyfills": "src/polyfills.ts", 80 | "tsConfig": "tsconfig.spec.json", 81 | "scripts": [], 82 | "styles": [ 83 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 84 | "src/styles.css" 85 | ], 86 | "assets": [ 87 | "src/assets", 88 | "src/favicon.ico" 89 | ] 90 | } 91 | }, 92 | "lint": { 93 | "builder": "@angular-devkit/build-angular:tslint", 94 | "options": { 95 | "tsConfig": [ 96 | "tsconfig.app.json", 97 | "tsconfig.spec.json" 98 | ], 99 | "exclude": [] 100 | } 101 | } 102 | } 103 | }, 104 | "booktracker-e2e": { 105 | "root": "e2e", 106 | "sourceRoot": "e2e", 107 | "projectType": "application", 108 | "architect": { 109 | "e2e": { 110 | "builder": "@angular-devkit/build-angular:protractor", 111 | "options": { 112 | "protractorConfig": "./protractor.conf.js", 113 | "devServerTarget": "booktracker:serve" 114 | } 115 | }, 116 | "lint": { 117 | "builder": "@angular-devkit/build-angular:tslint", 118 | "options": { 119 | "tsConfig": [ 120 | "e2e/tsconfig.e2e.json" 121 | ], 122 | "exclude": [] 123 | } 124 | } 125 | } 126 | } 127 | }, 128 | "defaultProject": "booktracker", 129 | "schematics": { 130 | "@schematics/angular:component": { 131 | "prefix": "app", 132 | "styleext": "css" 133 | }, 134 | "@schematics/angular:directive": { 135 | "prefix": "app" 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /dist/runtime.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack/bootstrap","webpack/runtime/chunk loaded","webpack/runtime/compat get default export","webpack/runtime/define property getters","webpack/runtime/hasOwnProperty shorthand","webpack/runtime/make namespace object","webpack/runtime/jsonp chunk loading"],"names":[],"mappings":";;;;UAAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WCzBA;WACA;WACA;WACA;WACA,8BAA8B,wCAAwC;WACtE;WACA;WACA;WACA;WACA,gBAAgB,qBAAqB;WACrC;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,IAAI;WACJ;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC1BA;WACA;WACA;WACA;WACA;WACA,gCAAgC,YAAY;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,wCAAwC,yCAAyC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,sDAAsD,kBAAkB;WACxE;WACA,+CAA+C,cAAc;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,oBAAoB;WAC1B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G","file":"runtime.js","sourcesContent":["// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tresult = fn();\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"runtime\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tfor(moduleId in moreModules) {\n\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t}\n\t}\n\tif(runtime) var result = runtime(__webpack_require__);\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkIds[i]] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkbooktracker\"] = self[\"webpackChunkbooktracker\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));"],"sourceRoot":"webpack:///"} -------------------------------------------------------------------------------- /dist/runtime.js: -------------------------------------------------------------------------------- 1 | /******/ (() => { // webpackBootstrap 2 | /******/ "use strict"; 3 | /******/ var __webpack_modules__ = ({}); 4 | /************************************************************************/ 5 | /******/ // The module cache 6 | /******/ var __webpack_module_cache__ = {}; 7 | /******/ 8 | /******/ // The require function 9 | /******/ function __webpack_require__(moduleId) { 10 | /******/ // Check if module is in cache 11 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 12 | /******/ if (cachedModule !== undefined) { 13 | /******/ return cachedModule.exports; 14 | /******/ } 15 | /******/ // Create a new module (and put it into the cache) 16 | /******/ var module = __webpack_module_cache__[moduleId] = { 17 | /******/ // no module.id needed 18 | /******/ // no module.loaded needed 19 | /******/ exports: {} 20 | /******/ }; 21 | /******/ 22 | /******/ // Execute the module function 23 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ // expose the modules object (__webpack_modules__) 30 | /******/ __webpack_require__.m = __webpack_modules__; 31 | /******/ 32 | /************************************************************************/ 33 | /******/ /* webpack/runtime/chunk loaded */ 34 | /******/ (() => { 35 | /******/ var deferred = []; 36 | /******/ __webpack_require__.O = (result, chunkIds, fn, priority) => { 37 | /******/ if(chunkIds) { 38 | /******/ priority = priority || 0; 39 | /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1]; 40 | /******/ deferred[i] = [chunkIds, fn, priority]; 41 | /******/ return; 42 | /******/ } 43 | /******/ var notFulfilled = Infinity; 44 | /******/ for (var i = 0; i < deferred.length; i++) { 45 | /******/ var [chunkIds, fn, priority] = deferred[i]; 46 | /******/ var fulfilled = true; 47 | /******/ for (var j = 0; j < chunkIds.length; j++) { 48 | /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) { 49 | /******/ chunkIds.splice(j--, 1); 50 | /******/ } else { 51 | /******/ fulfilled = false; 52 | /******/ if(priority < notFulfilled) notFulfilled = priority; 53 | /******/ } 54 | /******/ } 55 | /******/ if(fulfilled) { 56 | /******/ deferred.splice(i--, 1) 57 | /******/ result = fn(); 58 | /******/ } 59 | /******/ } 60 | /******/ return result; 61 | /******/ }; 62 | /******/ })(); 63 | /******/ 64 | /******/ /* webpack/runtime/compat get default export */ 65 | /******/ (() => { 66 | /******/ // getDefaultExport function for compatibility with non-harmony modules 67 | /******/ __webpack_require__.n = (module) => { 68 | /******/ var getter = module && module.__esModule ? 69 | /******/ () => (module['default']) : 70 | /******/ () => (module); 71 | /******/ __webpack_require__.d(getter, { a: getter }); 72 | /******/ return getter; 73 | /******/ }; 74 | /******/ })(); 75 | /******/ 76 | /******/ /* webpack/runtime/define property getters */ 77 | /******/ (() => { 78 | /******/ // define getter functions for harmony exports 79 | /******/ __webpack_require__.d = (exports, definition) => { 80 | /******/ for(var key in definition) { 81 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 82 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 83 | /******/ } 84 | /******/ } 85 | /******/ }; 86 | /******/ })(); 87 | /******/ 88 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 89 | /******/ (() => { 90 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 91 | /******/ })(); 92 | /******/ 93 | /******/ /* webpack/runtime/make namespace object */ 94 | /******/ (() => { 95 | /******/ // define __esModule on exports 96 | /******/ __webpack_require__.r = (exports) => { 97 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 98 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 99 | /******/ } 100 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 101 | /******/ }; 102 | /******/ })(); 103 | /******/ 104 | /******/ /* webpack/runtime/jsonp chunk loading */ 105 | /******/ (() => { 106 | /******/ // no baseURI 107 | /******/ 108 | /******/ // object to store loaded and loading chunks 109 | /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched 110 | /******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded 111 | /******/ var installedChunks = { 112 | /******/ "runtime": 0 113 | /******/ }; 114 | /******/ 115 | /******/ // no chunk on demand loading 116 | /******/ 117 | /******/ // no prefetching 118 | /******/ 119 | /******/ // no preloaded 120 | /******/ 121 | /******/ // no HMR 122 | /******/ 123 | /******/ // no HMR manifest 124 | /******/ 125 | /******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0); 126 | /******/ 127 | /******/ // install a JSONP callback for chunk loading 128 | /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 129 | /******/ var [chunkIds, moreModules, runtime] = data; 130 | /******/ // add "moreModules" to the modules object, 131 | /******/ // then flag all "chunkIds" as loaded and fire callback 132 | /******/ var moduleId, chunkId, i = 0; 133 | /******/ for(moduleId in moreModules) { 134 | /******/ if(__webpack_require__.o(moreModules, moduleId)) { 135 | /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 136 | /******/ } 137 | /******/ } 138 | /******/ if(runtime) var result = runtime(__webpack_require__); 139 | /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 140 | /******/ for(;i < chunkIds.length; i++) { 141 | /******/ chunkId = chunkIds[i]; 142 | /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 143 | /******/ installedChunks[chunkId][0](); 144 | /******/ } 145 | /******/ installedChunks[chunkIds[i]] = 0; 146 | /******/ } 147 | /******/ return __webpack_require__.O(result); 148 | /******/ } 149 | /******/ 150 | /******/ var chunkLoadingGlobal = self["webpackChunkbooktracker"] = self["webpackChunkbooktracker"] || []; 151 | /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 152 | /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 153 | /******/ })(); 154 | /******/ 155 | /************************************************************************/ 156 | /******/ 157 | /******/ 158 | /******/ })() 159 | ; 160 | //# sourceMappingURL=runtime.js.map -------------------------------------------------------------------------------- /dist/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["./$_lazy_route_resources|lazy|groupOptions: {}|namespace object","./src/app/add-book/add-book.component.ts","./src/app/add-reader/add-reader.component.ts","./src/app/app-routing.module.ts","./src/app/app.component.ts","./src/app/app.module.ts","./src/app/core/badge.service.ts","./src/app/core/book-tracker-error-handler.service.ts","./src/app/core/data.service.ts","./src/app/dashboard/dashboard.component.ts","./src/app/data.ts","./src/app/edit-book/edit-book.component.ts","./src/app/edit-reader/edit-reader.component.ts","./src/app/models/bookTrackerError.ts","./src/environments/environment.ts","./src/main.ts","./src/app/app.component.css","./src/app/add-book/add-book.component.html","./src/app/add-reader/add-reader.component.html","./src/app/app.component.html","./src/app/dashboard/dashboard.component.html","./src/app/edit-book/edit-book.component.html","./src/app/edit-reader/edit-reader.component.html"],"names":[],"mappings":"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","file":"main.js","sourcesContent":["function webpackEmptyAsyncContext(req) {\n\t// Here Promise.resolve().then() is used instead of new Promise() to prevent\n\t// uncaught exception popping up in devtools\n\treturn Promise.resolve().then(() => {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t});\n}\nwebpackEmptyAsyncContext.keys = () => ([]);\nwebpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;\nwebpackEmptyAsyncContext.id = 8255;\nmodule.exports = webpackEmptyAsyncContext;","import { Component, OnInit } from '@angular/core';\r\n\r\nimport { Book } from \"app/models/book\";\r\n\r\n@Component({\r\n selector: 'app-add-book',\r\n templateUrl: './add-book.component.html',\r\n styles: []\r\n})\r\nexport class AddBookComponent implements OnInit {\r\n\r\n constructor() { }\r\n\r\n ngOnInit() { }\r\n\r\n saveBook(formValues: any): void {\r\n let newBook: Book = formValues;\r\n newBook.bookID = 0;\r\n console.log(newBook);\r\n console.warn('Save new book not yet implemented.');\r\n }\r\n\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\n\r\nimport { Reader } from \"app/models/reader\";\r\n\r\n@Component({\r\n selector: 'app-add-reader',\r\n templateUrl: './add-reader.component.html',\r\n styles: []\r\n})\r\nexport class AddReaderComponent implements OnInit {\r\n\r\n constructor() { }\r\n\r\n ngOnInit() { }\r\n\r\n saveReader(formValues: any): void {\r\n let newReader: Reader = formValues;\r\n newReader.readerID = 0;\r\n console.log(newReader);\r\n console.warn('Save new reader not yet implemented.');\r\n }\r\n\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { RouterModule, Routes } from '@angular/router';\r\n\r\nimport { AddBookComponent } from \"app/add-book/add-book.component\";\r\nimport { AddReaderComponent } from \"app/add-reader/add-reader.component\";\r\nimport { DashboardComponent } from \"app/dashboard/dashboard.component\";\r\nimport { EditBookComponent } from \"app/edit-book/edit-book.component\";\r\nimport { EditReaderComponent } from \"app/edit-reader/edit-reader.component\";\r\n\r\nconst routes: Routes = [\r\n { path: 'dashboard', component: DashboardComponent },\r\n { path: 'addbook', component: AddBookComponent },\r\n { path: 'addreader', component: AddReaderComponent },\r\n { path: 'editreader/:id', component: EditReaderComponent },\r\n { path: 'editbook/:id', component: EditBookComponent },\r\n { path: '', redirectTo: 'dashboard', pathMatch: 'full' }\r\n];\r\n\r\n@NgModule({\r\n imports: [RouterModule.forRoot(routes)],\r\n exports: [RouterModule]\r\n})\r\nexport class AppRoutingModule { }\r\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'app-root',\n templateUrl: './app.component.html',\n styleUrls: ['./app.component.css']\n})\nexport class AppComponent {\n title = 'app';\n}\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { ErrorHandler, NgModule } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\n\r\nimport { AddBookComponent } from './add-book/add-book.component';\r\nimport { AddReaderComponent } from './add-reader/add-reader.component';\r\nimport { AppComponent } from './app.component';\r\nimport { AppRoutingModule } from './app-routing.module';\r\nimport { DashboardComponent } from './dashboard/dashboard.component';\r\nimport { EditBookComponent } from './edit-book/edit-book.component';\r\nimport { EditReaderComponent } from './edit-reader/edit-reader.component';\r\nimport { BookTrackerErrorHandlerService } from './core/book-tracker-error-handler.service';\r\n\r\n@NgModule({\r\n declarations: [\r\n AppComponent,\r\n DashboardComponent,\r\n AddBookComponent,\r\n EditReaderComponent,\r\n EditBookComponent,\r\n AddReaderComponent\r\n ],\r\n providers: [\r\n { provide: ErrorHandler, useClass: BookTrackerErrorHandlerService }\r\n ],\r\n imports: [\r\n BrowserModule,\r\n AppRoutingModule,\r\n FormsModule\r\n ],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class BadgeService {\r\n\r\n constructor() { }\r\n\r\n getReaderBadge(minutesRead: number): string {\r\n\r\n if (minutesRead > 5000) {\r\n return 'Book Worm';\r\n }\r\n else if (minutesRead > 2500) {\r\n return 'Page Turner';\r\n }\r\n else {\r\n return 'Getting Started';\r\n }\r\n \r\n }\r\n\r\n}\r\n","import { Injectable, ErrorHandler } from '@angular/core';\r\nimport { BookTrackerError } from 'app/models/bookTrackerError';\r\n\r\n@Injectable()\r\nexport class BookTrackerErrorHandlerService implements ErrorHandler {\r\n\r\n handleError(error: any): void {\r\n let customError: BookTrackerError = new BookTrackerError();\r\n customError.errorNumber = 200;\r\n customError.message = (error).message;\r\n customError.friendlyMessage = 'An error occurred. Please try again.';\r\n\r\n console.log(customError);\r\n }\r\n\r\n constructor() { }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\nimport { allBooks, allReaders } from 'app/data';\r\nimport { Reader } from \"app/models/reader\";\r\nimport { Book } from \"app/models/book\";\r\nimport { BookTrackerError } from 'app/models/bookTrackerError';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class DataService {\r\n\r\n constructor() { }\r\n\r\n mostPopularBook: Book = allBooks[0];\r\n\r\n setMostPopularBook(popularBook: Book): void {\r\n this.mostPopularBook = popularBook;\r\n }\r\n\r\n getAllReaders(): Reader[] {\r\n return allReaders;\r\n }\r\n\r\n getReaderById(id: number): Reader {\r\n return allReaders.find(reader => reader.readerID === id);\r\n }\r\n\r\n getAllBooks(): Book[] {\r\n return allBooks;\r\n }\r\n\r\n getBookById(id: number): Book {\r\n return allBooks.find(book => book.bookID === id);\r\n } \r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { Title } from '@angular/platform-browser';\r\n\r\nimport { Book } from \"app/models/book\";\r\nimport { Reader } from \"app/models/reader\";\r\nimport { DataService } from 'app/core/data.service';\r\n\r\n@Component({\r\n selector: 'app-dashboard',\r\n templateUrl: './dashboard.component.html',\r\n styles: []\r\n})\r\nexport class DashboardComponent implements OnInit {\r\n\r\n allBooks: Book[];\r\n allReaders: Reader[];\r\n mostPopularBook: Book;\r\n\r\n constructor(private dataService: DataService,\r\n private title: Title) { }\r\n \r\n ngOnInit() {\r\n this.allBooks = this.dataService.getAllBooks();\r\n this.allReaders = this.dataService.getAllReaders();\r\n this.mostPopularBook = this.dataService.mostPopularBook;\r\n\r\n this.title.setTitle(`Book Tracker`);\r\n }\r\n\r\n deleteBook(bookID: number): void {\r\n console.warn(`Delete book not yet implemented (bookID: ${bookID}).`);\r\n }\r\n\r\n deleteReader(readerID: number): void {\r\n console.warn(`Delete reader not yet implemented (readerID: ${readerID}).`);\r\n }\r\n\r\n}\r\n","import { Book } from \"app/models/book\";\r\nimport { Reader } from \"app/models/reader\";\r\n\r\nexport const allReaders: Reader[] = [\r\n { readerID: 1, name: 'Marie', weeklyReadingGoal: 400, totalMinutesRead: 5600 },\r\n { readerID: 2, name: 'Daniel', weeklyReadingGoal: 210, totalMinutesRead: 3000 },\r\n { readerID: 3, name: 'Lanier', weeklyReadingGoal: 140, totalMinutesRead: 600 }\r\n ];\r\n\r\nexport const allBooks: Book[] = [\r\n { bookID: 1, title: 'Goodnight Moon', author: 'Margaret Wise Brown', publicationYear: 1953 },\r\n { bookID: 2, title: 'Winnie-the-Pooh', author: 'A. A. Milne', publicationYear: 1926 },\r\n { bookID: 3, title: 'Where the Wild Things Are', author: 'Maurice Sendak', publicationYear: 1963 },\r\n { bookID: 4, title: 'The Hobbit', author: 'J. R. R. Tolkien', publicationYear: 1937 },\r\n { bookID: 5, title: 'Curious George', author: 'H. A. Rey', publicationYear: 1941 },\r\n { bookID: 6, title: 'Alice\\'s Adventures in Wonderland', author: 'Lewis Carroll', publicationYear: 1865 },\r\n];","import { Component, OnInit } from '@angular/core';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\nimport { Book } from 'app/models/book';\r\nimport { DataService } from 'app/core/data.service';\r\n\r\n@Component({\r\n selector: 'app-edit-book',\r\n templateUrl: './edit-book.component.html',\r\n styles: []\r\n})\r\nexport class EditBookComponent implements OnInit {\r\n\r\n selectedBook: Book;\r\n\r\n constructor(private route: ActivatedRoute,\r\n private dataService: DataService) { }\r\n\r\n ngOnInit() {\r\n let bookID: number = parseInt(this.route.snapshot.params['id']);\r\n this.selectedBook = this.dataService.getBookById(bookID);\r\n }\r\n\r\n setMostPopular(): void {\r\n this.dataService.setMostPopularBook(this.selectedBook);\r\n }\r\n\r\n saveChanges(): void {\r\n console.warn('Save changes to book not yet implemented.');\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { ActivatedRoute } from '@angular/router';\r\n\r\nimport { Reader } from \"app/models/reader\";\r\nimport { DataService } from 'app/core/data.service';\r\nimport { BadgeService } from 'app/core/badge.service';\r\n\r\n@Component({\r\n selector: 'app-edit-reader',\r\n templateUrl: './edit-reader.component.html',\r\n styles: [],\r\n providers: [BadgeService]\r\n})\r\nexport class EditReaderComponent implements OnInit {\r\n\r\n selectedReader: Reader;\r\n currentBadge: string;\r\n\r\n constructor(private route: ActivatedRoute,\r\n private dataService: DataService,\r\n private badgeService: BadgeService) { }\r\n\r\n ngOnInit() {\r\n let readerID: number = parseInt(this.route.snapshot.params['id']);\r\n this.selectedReader = this.dataService.getReaderById(readerID);\r\n this.currentBadge = this.badgeService.getReaderBadge(this.selectedReader.totalMinutesRead);\r\n }\r\n\r\n saveChanges() {\r\n console.warn('Save reader not yet implemented.');\r\n }\r\n}\r\n","export class BookTrackerError {\r\n errorNumber: number;\r\n message: string;\r\n friendlyMessage: string;\r\n}","// This file can be replaced during build by using the `fileReplacements` array.\r\n// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.\r\n// The list of file replacements can be found in `angular.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n\r\n/*\r\n * For easier debugging in development mode, you can import the following file\r\n * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.\r\n *\r\n * This import should be commented out in production mode because it will have a negative impact\r\n * on performance if an error is thrown.\r\n */\r\n// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.\r\n","import { enableProdMode } from '@angular/core';\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\n\nimport { AppModule } from './app/app.module';\nimport { environment } from './environments/environment';\n\nif (environment.production) {\n enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule);\n","export default \"\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhcHAuY29tcG9uZW50LmNzcyJ9 */\";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Add New Book\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Add Reader\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"\\r\\n\\r\\n\\r\\n\";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    All Books

    \\r\\n
    \\r\\n
    \\r\\n
  • \\r\\n {{book.title}}\\r\\n Edit \\r\\n Delete\\r\\n
  • \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    All Readers

    \\r\\n
    \\r\\n
    \\r\\n
  • \\r\\n {{reader.name}}\\r\\n Edit\\r\\n Delete \\r\\n
  • \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    Most Popular Book

    \\r\\n
    \\r\\n
    \\r\\n {{mostPopularBook.title}} by {{mostPopularBook.author}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Edit Book\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Edit Reader\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n\\r\\n
    \\r\\n \\r\\n
    \\r\\n {{ currentBadge }}\\r\\n
    \\r\\n
    \\r\\n\\r\\n\\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";"],"sourceRoot":"webpack:///"} -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | (self["webpackChunkbooktracker"] = self["webpackChunkbooktracker"] || []).push([["main"],{ 2 | 3 | /***/ 8255: 4 | /*!*******************************************************!*\ 5 | !*** ./$_lazy_route_resources/ lazy namespace object ***! 6 | \*******************************************************/ 7 | /***/ ((module) => { 8 | 9 | function webpackEmptyAsyncContext(req) { 10 | // Here Promise.resolve().then() is used instead of new Promise() to prevent 11 | // uncaught exception popping up in devtools 12 | return Promise.resolve().then(() => { 13 | var e = new Error("Cannot find module '" + req + "'"); 14 | e.code = 'MODULE_NOT_FOUND'; 15 | throw e; 16 | }); 17 | } 18 | webpackEmptyAsyncContext.keys = () => ([]); 19 | webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; 20 | webpackEmptyAsyncContext.id = 8255; 21 | module.exports = webpackEmptyAsyncContext; 22 | 23 | /***/ }), 24 | 25 | /***/ 9884: 26 | /*!************************************************!*\ 27 | !*** ./src/app/add-book/add-book.component.ts ***! 28 | \************************************************/ 29 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 30 | 31 | "use strict"; 32 | __webpack_require__.r(__webpack_exports__); 33 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 34 | /* harmony export */ "AddBookComponent": () => (/* binding */ AddBookComponent) 35 | /* harmony export */ }); 36 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ 4762); 37 | /* harmony import */ var _raw_loader_add_book_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./add-book.component.html */ 7052); 38 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 39 | 40 | 41 | 42 | let AddBookComponent = class AddBookComponent { 43 | constructor() { } 44 | ngOnInit() { } 45 | saveBook(formValues) { 46 | let newBook = formValues; 47 | newBook.bookID = 0; 48 | console.log(newBook); 49 | console.warn('Save new book not yet implemented.'); 50 | } 51 | }; 52 | AddBookComponent.ctorParameters = () => []; 53 | AddBookComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([ 54 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.Component)({ 55 | selector: 'app-add-book', 56 | template: _raw_loader_add_book_component_html__WEBPACK_IMPORTED_MODULE_0__.default 57 | }) 58 | ], AddBookComponent); 59 | 60 | 61 | 62 | /***/ }), 63 | 64 | /***/ 4808: 65 | /*!****************************************************!*\ 66 | !*** ./src/app/add-reader/add-reader.component.ts ***! 67 | \****************************************************/ 68 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 69 | 70 | "use strict"; 71 | __webpack_require__.r(__webpack_exports__); 72 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 73 | /* harmony export */ "AddReaderComponent": () => (/* binding */ AddReaderComponent) 74 | /* harmony export */ }); 75 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ 4762); 76 | /* harmony import */ var _raw_loader_add_reader_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./add-reader.component.html */ 1699); 77 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 78 | 79 | 80 | 81 | let AddReaderComponent = class AddReaderComponent { 82 | constructor() { } 83 | ngOnInit() { } 84 | saveReader(formValues) { 85 | let newReader = formValues; 86 | newReader.readerID = 0; 87 | console.log(newReader); 88 | console.warn('Save new reader not yet implemented.'); 89 | } 90 | }; 91 | AddReaderComponent.ctorParameters = () => []; 92 | AddReaderComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([ 93 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.Component)({ 94 | selector: 'app-add-reader', 95 | template: _raw_loader_add_reader_component_html__WEBPACK_IMPORTED_MODULE_0__.default 96 | }) 97 | ], AddReaderComponent); 98 | 99 | 100 | 101 | /***/ }), 102 | 103 | /***/ 158: 104 | /*!***************************************!*\ 105 | !*** ./src/app/app-routing.module.ts ***! 106 | \***************************************/ 107 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 108 | 109 | "use strict"; 110 | __webpack_require__.r(__webpack_exports__); 111 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 112 | /* harmony export */ "AppRoutingModule": () => (/* binding */ AppRoutingModule) 113 | /* harmony export */ }); 114 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! tslib */ 4762); 115 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @angular/core */ 7716); 116 | /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @angular/router */ 9895); 117 | /* harmony import */ var app_add_book_add_book_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! app/add-book/add-book.component */ 9884); 118 | /* harmony import */ var app_add_reader_add_reader_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/add-reader/add-reader.component */ 4808); 119 | /* harmony import */ var app_dashboard_dashboard_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! app/dashboard/dashboard.component */ 7528); 120 | /* harmony import */ var app_edit_book_edit_book_component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! app/edit-book/edit-book.component */ 445); 121 | /* harmony import */ var app_edit_reader_edit_reader_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! app/edit-reader/edit-reader.component */ 6236); 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | const routes = [ 131 | { path: 'dashboard', component: app_dashboard_dashboard_component__WEBPACK_IMPORTED_MODULE_2__.DashboardComponent }, 132 | { path: 'addbook', component: app_add_book_add_book_component__WEBPACK_IMPORTED_MODULE_0__.AddBookComponent }, 133 | { path: 'addreader', component: app_add_reader_add_reader_component__WEBPACK_IMPORTED_MODULE_1__.AddReaderComponent }, 134 | { path: 'editreader/:id', component: app_edit_reader_edit_reader_component__WEBPACK_IMPORTED_MODULE_4__.EditReaderComponent }, 135 | { path: 'editbook/:id', component: app_edit_book_edit_book_component__WEBPACK_IMPORTED_MODULE_3__.EditBookComponent }, 136 | { path: '', redirectTo: 'dashboard', pathMatch: 'full' } 137 | ]; 138 | let AppRoutingModule = class AppRoutingModule { 139 | }; 140 | AppRoutingModule = (0,tslib__WEBPACK_IMPORTED_MODULE_5__.__decorate)([ 141 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_6__.NgModule)({ 142 | imports: [_angular_router__WEBPACK_IMPORTED_MODULE_7__.RouterModule.forRoot(routes)], 143 | exports: [_angular_router__WEBPACK_IMPORTED_MODULE_7__.RouterModule] 144 | }) 145 | ], AppRoutingModule); 146 | 147 | 148 | 149 | /***/ }), 150 | 151 | /***/ 5041: 152 | /*!**********************************!*\ 153 | !*** ./src/app/app.component.ts ***! 154 | \**********************************/ 155 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 156 | 157 | "use strict"; 158 | __webpack_require__.r(__webpack_exports__); 159 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 160 | /* harmony export */ "AppComponent": () => (/* binding */ AppComponent) 161 | /* harmony export */ }); 162 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ 4762); 163 | /* harmony import */ var _raw_loader_app_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./app.component.html */ 1106); 164 | /* harmony import */ var _app_component_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./app.component.css */ 1249); 165 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 7716); 166 | 167 | 168 | 169 | 170 | let AppComponent = class AppComponent { 171 | constructor() { 172 | this.title = 'app'; 173 | } 174 | }; 175 | AppComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__decorate)([ 176 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.Component)({ 177 | selector: 'app-root', 178 | template: _raw_loader_app_component_html__WEBPACK_IMPORTED_MODULE_0__.default, 179 | styles: [_app_component_css__WEBPACK_IMPORTED_MODULE_1__.default] 180 | }) 181 | ], AppComponent); 182 | 183 | 184 | 185 | /***/ }), 186 | 187 | /***/ 6747: 188 | /*!*******************************!*\ 189 | !*** ./src/app/app.module.ts ***! 190 | \*******************************/ 191 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 192 | 193 | "use strict"; 194 | __webpack_require__.r(__webpack_exports__); 195 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 196 | /* harmony export */ "AppModule": () => (/* binding */ AppModule) 197 | /* harmony export */ }); 198 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! tslib */ 4762); 199 | /* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @angular/platform-browser */ 9075); 200 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/core */ 7716); 201 | /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @angular/forms */ 3679); 202 | /* harmony import */ var _add_book_add_book_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add-book/add-book.component */ 9884); 203 | /* harmony import */ var _add_reader_add_reader_component__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./add-reader/add-reader.component */ 4808); 204 | /* harmony import */ var _app_component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./app.component */ 5041); 205 | /* harmony import */ var _app_routing_module__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./app-routing.module */ 158); 206 | /* harmony import */ var _dashboard_dashboard_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./dashboard/dashboard.component */ 7528); 207 | /* harmony import */ var _edit_book_edit_book_component__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./edit-book/edit-book.component */ 445); 208 | /* harmony import */ var _edit_reader_edit_reader_component__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./edit-reader/edit-reader.component */ 6236); 209 | /* harmony import */ var _core_book_tracker_error_handler_service__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./core/book-tracker-error-handler.service */ 9772); 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | let AppModule = class AppModule { 223 | }; 224 | AppModule = (0,tslib__WEBPACK_IMPORTED_MODULE_8__.__decorate)([ 225 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_9__.NgModule)({ 226 | declarations: [ 227 | _app_component__WEBPACK_IMPORTED_MODULE_2__.AppComponent, 228 | _dashboard_dashboard_component__WEBPACK_IMPORTED_MODULE_4__.DashboardComponent, 229 | _add_book_add_book_component__WEBPACK_IMPORTED_MODULE_0__.AddBookComponent, 230 | _edit_reader_edit_reader_component__WEBPACK_IMPORTED_MODULE_6__.EditReaderComponent, 231 | _edit_book_edit_book_component__WEBPACK_IMPORTED_MODULE_5__.EditBookComponent, 232 | _add_reader_add_reader_component__WEBPACK_IMPORTED_MODULE_1__.AddReaderComponent 233 | ], 234 | providers: [ 235 | { provide: _angular_core__WEBPACK_IMPORTED_MODULE_9__.ErrorHandler, useClass: _core_book_tracker_error_handler_service__WEBPACK_IMPORTED_MODULE_7__.BookTrackerErrorHandlerService } 236 | ], 237 | imports: [ 238 | _angular_platform_browser__WEBPACK_IMPORTED_MODULE_10__.BrowserModule, 239 | _app_routing_module__WEBPACK_IMPORTED_MODULE_3__.AppRoutingModule, 240 | _angular_forms__WEBPACK_IMPORTED_MODULE_11__.FormsModule 241 | ], 242 | bootstrap: [_app_component__WEBPACK_IMPORTED_MODULE_2__.AppComponent] 243 | }) 244 | ], AppModule); 245 | 246 | 247 | 248 | /***/ }), 249 | 250 | /***/ 8856: 251 | /*!***************************************!*\ 252 | !*** ./src/app/core/badge.service.ts ***! 253 | \***************************************/ 254 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 255 | 256 | "use strict"; 257 | __webpack_require__.r(__webpack_exports__); 258 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 259 | /* harmony export */ "BadgeService": () => (/* binding */ BadgeService) 260 | /* harmony export */ }); 261 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ 4762); 262 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @angular/core */ 7716); 263 | 264 | 265 | let BadgeService = class BadgeService { 266 | constructor() { } 267 | getReaderBadge(minutesRead) { 268 | if (minutesRead > 5000) { 269 | return 'Book Worm'; 270 | } 271 | else if (minutesRead > 2500) { 272 | return 'Page Turner'; 273 | } 274 | else { 275 | return 'Getting Started'; 276 | } 277 | } 278 | }; 279 | BadgeService.ctorParameters = () => []; 280 | BadgeService = (0,tslib__WEBPACK_IMPORTED_MODULE_0__.__decorate)([ 281 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_1__.Injectable)({ 282 | providedIn: 'root' 283 | }) 284 | ], BadgeService); 285 | 286 | 287 | 288 | /***/ }), 289 | 290 | /***/ 9772: 291 | /*!************************************************************!*\ 292 | !*** ./src/app/core/book-tracker-error-handler.service.ts ***! 293 | \************************************************************/ 294 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 295 | 296 | "use strict"; 297 | __webpack_require__.r(__webpack_exports__); 298 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 299 | /* harmony export */ "BookTrackerErrorHandlerService": () => (/* binding */ BookTrackerErrorHandlerService) 300 | /* harmony export */ }); 301 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ 4762); 302 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 303 | /* harmony import */ var app_models_bookTrackerError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! app/models/bookTrackerError */ 5582); 304 | 305 | 306 | 307 | let BookTrackerErrorHandlerService = class BookTrackerErrorHandlerService { 308 | constructor() { } 309 | handleError(error) { 310 | let customError = new app_models_bookTrackerError__WEBPACK_IMPORTED_MODULE_0__.BookTrackerError(); 311 | customError.errorNumber = 200; 312 | customError.message = error.message; 313 | customError.friendlyMessage = 'An error occurred. Please try again.'; 314 | console.log(customError); 315 | } 316 | }; 317 | BookTrackerErrorHandlerService.ctorParameters = () => []; 318 | BookTrackerErrorHandlerService = (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([ 319 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.Injectable)() 320 | ], BookTrackerErrorHandlerService); 321 | 322 | 323 | 324 | /***/ }), 325 | 326 | /***/ 3943: 327 | /*!**************************************!*\ 328 | !*** ./src/app/core/data.service.ts ***! 329 | \**************************************/ 330 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 331 | 332 | "use strict"; 333 | __webpack_require__.r(__webpack_exports__); 334 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 335 | /* harmony export */ "DataService": () => (/* binding */ DataService) 336 | /* harmony export */ }); 337 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ 4762); 338 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 339 | /* harmony import */ var app_data__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! app/data */ 8387); 340 | 341 | 342 | 343 | let DataService = class DataService { 344 | constructor() { 345 | this.mostPopularBook = app_data__WEBPACK_IMPORTED_MODULE_0__.allBooks[0]; 346 | } 347 | setMostPopularBook(popularBook) { 348 | this.mostPopularBook = popularBook; 349 | } 350 | getAllReaders() { 351 | return app_data__WEBPACK_IMPORTED_MODULE_0__.allReaders; 352 | } 353 | getReaderById(id) { 354 | return app_data__WEBPACK_IMPORTED_MODULE_0__.allReaders.find(reader => reader.readerID === id); 355 | } 356 | getAllBooks() { 357 | return app_data__WEBPACK_IMPORTED_MODULE_0__.allBooks; 358 | } 359 | getBookById(id) { 360 | return app_data__WEBPACK_IMPORTED_MODULE_0__.allBooks.find(book => book.bookID === id); 361 | } 362 | }; 363 | DataService.ctorParameters = () => []; 364 | DataService = (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__decorate)([ 365 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.Injectable)({ 366 | providedIn: 'root' 367 | }) 368 | ], DataService); 369 | 370 | 371 | 372 | /***/ }), 373 | 374 | /***/ 7528: 375 | /*!**************************************************!*\ 376 | !*** ./src/app/dashboard/dashboard.component.ts ***! 377 | \**************************************************/ 378 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 379 | 380 | "use strict"; 381 | __webpack_require__.r(__webpack_exports__); 382 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 383 | /* harmony export */ "DashboardComponent": () => (/* binding */ DashboardComponent) 384 | /* harmony export */ }); 385 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ 4762); 386 | /* harmony import */ var _raw_loader_dashboard_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./dashboard.component.html */ 9306); 387 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 7716); 388 | /* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/platform-browser */ 9075); 389 | /* harmony import */ var app_core_data_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/core/data.service */ 3943); 390 | 391 | 392 | 393 | 394 | 395 | let DashboardComponent = class DashboardComponent { 396 | constructor(dataService, title) { 397 | this.dataService = dataService; 398 | this.title = title; 399 | } 400 | ngOnInit() { 401 | this.allBooks = this.dataService.getAllBooks(); 402 | this.allReaders = this.dataService.getAllReaders(); 403 | this.mostPopularBook = this.dataService.mostPopularBook; 404 | this.title.setTitle(`Book Tracker`); 405 | } 406 | deleteBook(bookID) { 407 | console.warn(`Delete book not yet implemented (bookID: ${bookID}).`); 408 | } 409 | deleteReader(readerID) { 410 | console.warn(`Delete reader not yet implemented (readerID: ${readerID}).`); 411 | } 412 | }; 413 | DashboardComponent.ctorParameters = () => [ 414 | { type: app_core_data_service__WEBPACK_IMPORTED_MODULE_1__.DataService }, 415 | { type: _angular_platform_browser__WEBPACK_IMPORTED_MODULE_2__.Title } 416 | ]; 417 | DashboardComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([ 418 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.Component)({ 419 | selector: 'app-dashboard', 420 | template: _raw_loader_dashboard_component_html__WEBPACK_IMPORTED_MODULE_0__.default 421 | }) 422 | ], DashboardComponent); 423 | 424 | 425 | 426 | /***/ }), 427 | 428 | /***/ 8387: 429 | /*!*************************!*\ 430 | !*** ./src/app/data.ts ***! 431 | \*************************/ 432 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 433 | 434 | "use strict"; 435 | __webpack_require__.r(__webpack_exports__); 436 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 437 | /* harmony export */ "allReaders": () => (/* binding */ allReaders), 438 | /* harmony export */ "allBooks": () => (/* binding */ allBooks) 439 | /* harmony export */ }); 440 | const allReaders = [ 441 | { readerID: 1, name: 'Marie', weeklyReadingGoal: 400, totalMinutesRead: 5600 }, 442 | { readerID: 2, name: 'Daniel', weeklyReadingGoal: 210, totalMinutesRead: 3000 }, 443 | { readerID: 3, name: 'Lanier', weeklyReadingGoal: 140, totalMinutesRead: 600 } 444 | ]; 445 | const allBooks = [ 446 | { bookID: 1, title: 'Goodnight Moon', author: 'Margaret Wise Brown', publicationYear: 1953 }, 447 | { bookID: 2, title: 'Winnie-the-Pooh', author: 'A. A. Milne', publicationYear: 1926 }, 448 | { bookID: 3, title: 'Where the Wild Things Are', author: 'Maurice Sendak', publicationYear: 1963 }, 449 | { bookID: 4, title: 'The Hobbit', author: 'J. R. R. Tolkien', publicationYear: 1937 }, 450 | { bookID: 5, title: 'Curious George', author: 'H. A. Rey', publicationYear: 1941 }, 451 | { bookID: 6, title: 'Alice\'s Adventures in Wonderland', author: 'Lewis Carroll', publicationYear: 1865 }, 452 | ]; 453 | 454 | 455 | /***/ }), 456 | 457 | /***/ 445: 458 | /*!**************************************************!*\ 459 | !*** ./src/app/edit-book/edit-book.component.ts ***! 460 | \**************************************************/ 461 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 462 | 463 | "use strict"; 464 | __webpack_require__.r(__webpack_exports__); 465 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 466 | /* harmony export */ "EditBookComponent": () => (/* binding */ EditBookComponent) 467 | /* harmony export */ }); 468 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ 4762); 469 | /* harmony import */ var _raw_loader_edit_book_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./edit-book.component.html */ 8367); 470 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 7716); 471 | /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/router */ 9895); 472 | /* harmony import */ var app_core_data_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/core/data.service */ 3943); 473 | 474 | 475 | 476 | 477 | 478 | let EditBookComponent = class EditBookComponent { 479 | constructor(route, dataService) { 480 | this.route = route; 481 | this.dataService = dataService; 482 | } 483 | ngOnInit() { 484 | let bookID = parseInt(this.route.snapshot.params['id']); 485 | this.selectedBook = this.dataService.getBookById(bookID); 486 | } 487 | setMostPopular() { 488 | this.dataService.setMostPopularBook(this.selectedBook); 489 | } 490 | saveChanges() { 491 | console.warn('Save changes to book not yet implemented.'); 492 | } 493 | }; 494 | EditBookComponent.ctorParameters = () => [ 495 | { type: _angular_router__WEBPACK_IMPORTED_MODULE_2__.ActivatedRoute }, 496 | { type: app_core_data_service__WEBPACK_IMPORTED_MODULE_1__.DataService } 497 | ]; 498 | EditBookComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([ 499 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.Component)({ 500 | selector: 'app-edit-book', 501 | template: _raw_loader_edit_book_component_html__WEBPACK_IMPORTED_MODULE_0__.default 502 | }) 503 | ], EditBookComponent); 504 | 505 | 506 | 507 | /***/ }), 508 | 509 | /***/ 6236: 510 | /*!******************************************************!*\ 511 | !*** ./src/app/edit-reader/edit-reader.component.ts ***! 512 | \******************************************************/ 513 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 514 | 515 | "use strict"; 516 | __webpack_require__.r(__webpack_exports__); 517 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 518 | /* harmony export */ "EditReaderComponent": () => (/* binding */ EditReaderComponent) 519 | /* harmony export */ }); 520 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! tslib */ 4762); 521 | /* harmony import */ var _raw_loader_edit_reader_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./edit-reader.component.html */ 4644); 522 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @angular/core */ 7716); 523 | /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/router */ 9895); 524 | /* harmony import */ var app_core_data_service__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/core/data.service */ 3943); 525 | /* harmony import */ var app_core_badge_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! app/core/badge.service */ 8856); 526 | 527 | 528 | 529 | 530 | 531 | 532 | let EditReaderComponent = class EditReaderComponent { 533 | constructor(route, dataService, badgeService) { 534 | this.route = route; 535 | this.dataService = dataService; 536 | this.badgeService = badgeService; 537 | } 538 | ngOnInit() { 539 | let readerID = parseInt(this.route.snapshot.params['id']); 540 | this.selectedReader = this.dataService.getReaderById(readerID); 541 | this.currentBadge = this.badgeService.getReaderBadge(this.selectedReader.totalMinutesRead); 542 | } 543 | saveChanges() { 544 | console.warn('Save reader not yet implemented.'); 545 | } 546 | }; 547 | EditReaderComponent.ctorParameters = () => [ 548 | { type: _angular_router__WEBPACK_IMPORTED_MODULE_3__.ActivatedRoute }, 549 | { type: app_core_data_service__WEBPACK_IMPORTED_MODULE_1__.DataService }, 550 | { type: app_core_badge_service__WEBPACK_IMPORTED_MODULE_2__.BadgeService } 551 | ]; 552 | EditReaderComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_4__.__decorate)([ 553 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_5__.Component)({ 554 | selector: 'app-edit-reader', 555 | template: _raw_loader_edit_reader_component_html__WEBPACK_IMPORTED_MODULE_0__.default, 556 | providers: [app_core_badge_service__WEBPACK_IMPORTED_MODULE_2__.BadgeService] 557 | }) 558 | ], EditReaderComponent); 559 | 560 | 561 | 562 | /***/ }), 563 | 564 | /***/ 5582: 565 | /*!********************************************!*\ 566 | !*** ./src/app/models/bookTrackerError.ts ***! 567 | \********************************************/ 568 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 569 | 570 | "use strict"; 571 | __webpack_require__.r(__webpack_exports__); 572 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 573 | /* harmony export */ "BookTrackerError": () => (/* binding */ BookTrackerError) 574 | /* harmony export */ }); 575 | class BookTrackerError { 576 | } 577 | 578 | 579 | /***/ }), 580 | 581 | /***/ 2340: 582 | /*!*****************************************!*\ 583 | !*** ./src/environments/environment.ts ***! 584 | \*****************************************/ 585 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 586 | 587 | "use strict"; 588 | __webpack_require__.r(__webpack_exports__); 589 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 590 | /* harmony export */ "environment": () => (/* binding */ environment) 591 | /* harmony export */ }); 592 | // This file can be replaced during build by using the `fileReplacements` array. 593 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 594 | // The list of file replacements can be found in `angular.json`. 595 | const environment = { 596 | production: false 597 | }; 598 | /* 599 | * For easier debugging in development mode, you can import the following file 600 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 601 | * 602 | * This import should be commented out in production mode because it will have a negative impact 603 | * on performance if an error is thrown. 604 | */ 605 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 606 | 607 | 608 | /***/ }), 609 | 610 | /***/ 4431: 611 | /*!*********************!*\ 612 | !*** ./src/main.ts ***! 613 | \*********************/ 614 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 615 | 616 | "use strict"; 617 | __webpack_require__.r(__webpack_exports__); 618 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 619 | /* harmony import */ var _angular_platform_browser_dynamic__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/platform-browser-dynamic */ 4608); 620 | /* harmony import */ var _app_app_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./app/app.module */ 6747); 621 | /* harmony import */ var _environments_environment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./environments/environment */ 2340); 622 | 623 | 624 | 625 | 626 | if (_environments_environment__WEBPACK_IMPORTED_MODULE_1__.environment.production) { 627 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.enableProdMode)(); 628 | } 629 | (0,_angular_platform_browser_dynamic__WEBPACK_IMPORTED_MODULE_3__.platformBrowserDynamic)().bootstrapModule(_app_app_module__WEBPACK_IMPORTED_MODULE_0__.AppModule); 630 | 631 | 632 | /***/ }), 633 | 634 | /***/ 1249: 635 | /*!***********************************!*\ 636 | !*** ./src/app/app.component.css ***! 637 | \***********************************/ 638 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 639 | 640 | "use strict"; 641 | __webpack_require__.r(__webpack_exports__); 642 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 643 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 644 | /* harmony export */ }); 645 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhcHAuY29tcG9uZW50LmNzcyJ9 */"); 646 | 647 | /***/ }), 648 | 649 | /***/ 7052: 650 | /*!****************************************************************************************!*\ 651 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/add-book/add-book.component.html ***! 652 | \****************************************************************************************/ 653 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 654 | 655 | "use strict"; 656 | __webpack_require__.r(__webpack_exports__); 657 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 658 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 659 | /* harmony export */ }); 660 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Add New Book\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 661 | 662 | /***/ }), 663 | 664 | /***/ 1699: 665 | /*!********************************************************************************************!*\ 666 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/add-reader/add-reader.component.html ***! 667 | \********************************************************************************************/ 668 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 669 | 670 | "use strict"; 671 | __webpack_require__.r(__webpack_exports__); 672 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 673 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 674 | /* harmony export */ }); 675 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Add Reader\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 676 | 677 | /***/ }), 678 | 679 | /***/ 1106: 680 | /*!**************************************************************************!*\ 681 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/app.component.html ***! 682 | \**************************************************************************/ 683 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 684 | 685 | "use strict"; 686 | __webpack_require__.r(__webpack_exports__); 687 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 688 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 689 | /* harmony export */ }); 690 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\r\n\r\n\r\n"); 691 | 692 | /***/ }), 693 | 694 | /***/ 9306: 695 | /*!******************************************************************************************!*\ 696 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/dashboard/dashboard.component.html ***! 697 | \******************************************************************************************/ 698 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 699 | 700 | "use strict"; 701 | __webpack_require__.r(__webpack_exports__); 702 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 703 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 704 | /* harmony export */ }); 705 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n

    All Books

    \r\n
    \r\n
    \r\n
  • \r\n {{book.title}}\r\n Edit \r\n Delete\r\n
  • \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n

    All Readers

    \r\n
    \r\n
    \r\n
  • \r\n {{reader.name}}\r\n Edit\r\n Delete \r\n
  • \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n

    Most Popular Book

    \r\n
    \r\n
    \r\n {{mostPopularBook.title}} by {{mostPopularBook.author}}\r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 706 | 707 | /***/ }), 708 | 709 | /***/ 8367: 710 | /*!******************************************************************************************!*\ 711 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/edit-book/edit-book.component.html ***! 712 | \******************************************************************************************/ 713 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 714 | 715 | "use strict"; 716 | __webpack_require__.r(__webpack_exports__); 717 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 718 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 719 | /* harmony export */ }); 720 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Edit Book\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 721 | 722 | /***/ }), 723 | 724 | /***/ 4644: 725 | /*!**********************************************************************************************!*\ 726 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/edit-reader/edit-reader.component.html ***! 727 | \**********************************************************************************************/ 728 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 729 | 730 | "use strict"; 731 | __webpack_require__.r(__webpack_exports__); 732 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 733 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 734 | /* harmony export */ }); 735 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Edit Reader\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n\r\n
    \r\n \r\n
    \r\n {{ currentBadge }}\r\n
    \r\n
    \r\n\r\n\r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 736 | 737 | /***/ }) 738 | 739 | }, 740 | /******/ __webpack_require__ => { // webpackRuntimeModules 741 | /******/ "use strict"; 742 | /******/ 743 | /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) 744 | /******/ __webpack_require__.O(0, ["vendor"], () => (__webpack_exec__(4431))); 745 | /******/ var __webpack_exports__ = __webpack_require__.O(); 746 | /******/ } 747 | ]); 748 | //# sourceMappingURL=main.js.map --------------------------------------------------------------------------------