├── 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 |
--------------------------------------------------------------------------------
/src/app/add-reader/add-reader.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 \"\";","export default \"\";","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 \"\";","export default \"\";"],"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__ = ("");
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__ = ("");
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__ = ("");
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__ = ("");
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
--------------------------------------------------------------------------------