├── .browserslistrc ├── .editorconfig ├── .gitignore ├── README.md ├── angular.json ├── dist ├── favicon.ico ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff ├── glyphicons-halflings-regular.woff2 ├── index.html ├── main.js ├── main.js.map ├── polyfills.js ├── polyfills.js.map ├── runtime.js ├── runtime.js.map ├── styles.css ├── styles.css.map ├── vendor.js └── vendor.js.map ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── server.js ├── server ├── data │ ├── books.json │ └── readers.json ├── routes │ ├── books.js │ ├── errors.js │ ├── index.js │ └── readers.js └── views │ ├── error.jade │ ├── index.jade │ └── layout.jade ├── src ├── app │ ├── add-book │ │ ├── add-book.component.html │ │ └── add-book.component.ts │ ├── add-reader │ │ ├── add-reader.component.html │ │ └── add-reader.component.ts │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.module.ts │ ├── dashboard │ │ ├── dashboard.component.html │ │ └── dashboard.component.ts │ ├── data.ts │ ├── edit-book │ │ ├── edit-book.component.html │ │ └── edit-book.component.ts │ ├── edit-reader │ │ ├── edit-reader.component.html │ │ └── edit-reader.component.ts │ └── models │ │ ├── book.ts │ │ └── reader.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test.ts └── typings.d.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Services 2 | 3 | This is the official repository for my Pluralsight course titled *Angular Services*. 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 | -------------------------------------------------------------------------------- /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": "src/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 | "src/tsconfig.app.json", 97 | "src/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/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/dist/favicon.ico -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/dist/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/dist/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/dist/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /dist/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/dist/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Book Tracker 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /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_7__ = __webpack_require__(/*! tslib */ 4762); 199 | /* harmony import */ var _angular_platform_browser__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @angular/platform-browser */ 9075); 200 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @angular/core */ 7716); 201 | /* harmony import */ var _angular_forms__WEBPACK_IMPORTED_MODULE_10__ = __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 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | let AppModule = class AppModule { 221 | }; 222 | AppModule = (0,tslib__WEBPACK_IMPORTED_MODULE_7__.__decorate)([ 223 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_8__.NgModule)({ 224 | declarations: [ 225 | _app_component__WEBPACK_IMPORTED_MODULE_2__.AppComponent, 226 | _dashboard_dashboard_component__WEBPACK_IMPORTED_MODULE_4__.DashboardComponent, 227 | _add_book_add_book_component__WEBPACK_IMPORTED_MODULE_0__.AddBookComponent, 228 | _edit_reader_edit_reader_component__WEBPACK_IMPORTED_MODULE_6__.EditReaderComponent, 229 | _edit_book_edit_book_component__WEBPACK_IMPORTED_MODULE_5__.EditBookComponent, 230 | _add_reader_add_reader_component__WEBPACK_IMPORTED_MODULE_1__.AddReaderComponent 231 | ], 232 | imports: [ 233 | _angular_platform_browser__WEBPACK_IMPORTED_MODULE_9__.BrowserModule, 234 | _app_routing_module__WEBPACK_IMPORTED_MODULE_3__.AppRoutingModule, 235 | _angular_forms__WEBPACK_IMPORTED_MODULE_10__.FormsModule 236 | ], 237 | providers: [], 238 | bootstrap: [_app_component__WEBPACK_IMPORTED_MODULE_2__.AppComponent] 239 | }) 240 | ], AppModule); 241 | 242 | 243 | 244 | /***/ }), 245 | 246 | /***/ 7528: 247 | /*!**************************************************!*\ 248 | !*** ./src/app/dashboard/dashboard.component.ts ***! 249 | \**************************************************/ 250 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 251 | 252 | "use strict"; 253 | __webpack_require__.r(__webpack_exports__); 254 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 255 | /* harmony export */ "DashboardComponent": () => (/* binding */ DashboardComponent) 256 | /* harmony export */ }); 257 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ 4762); 258 | /* harmony import */ var _raw_loader_dashboard_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./dashboard.component.html */ 9306); 259 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/core */ 7716); 260 | /* harmony import */ var app_data__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/data */ 8387); 261 | 262 | 263 | 264 | 265 | let DashboardComponent = class DashboardComponent { 266 | constructor() { 267 | this.allBooks = app_data__WEBPACK_IMPORTED_MODULE_1__.allBooks; 268 | this.allReaders = app_data__WEBPACK_IMPORTED_MODULE_1__.allReaders; 269 | this.mostPopularBook = app_data__WEBPACK_IMPORTED_MODULE_1__.allBooks[0]; 270 | } 271 | ngOnInit() { 272 | } 273 | deleteBook(bookID) { 274 | console.warn(`Delete book not yet implemented (bookID: ${bookID}).`); 275 | } 276 | deleteReader(readerID) { 277 | console.warn(`Delete reader not yet implemented (readerID: ${readerID}).`); 278 | } 279 | }; 280 | DashboardComponent.ctorParameters = () => []; 281 | DashboardComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__decorate)([ 282 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_3__.Component)({ 283 | selector: 'app-dashboard', 284 | template: _raw_loader_dashboard_component_html__WEBPACK_IMPORTED_MODULE_0__.default 285 | }) 286 | ], DashboardComponent); 287 | 288 | 289 | 290 | /***/ }), 291 | 292 | /***/ 8387: 293 | /*!*************************!*\ 294 | !*** ./src/app/data.ts ***! 295 | \*************************/ 296 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 297 | 298 | "use strict"; 299 | __webpack_require__.r(__webpack_exports__); 300 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 301 | /* harmony export */ "allReaders": () => (/* binding */ allReaders), 302 | /* harmony export */ "allBooks": () => (/* binding */ allBooks) 303 | /* harmony export */ }); 304 | const allReaders = [ 305 | { readerID: 1, name: 'Marie', weeklyReadingGoal: 400, totalMinutesRead: 5600 }, 306 | { readerID: 2, name: 'Daniel', weeklyReadingGoal: 210, totalMinutesRead: 3000 }, 307 | { readerID: 3, name: 'Lanier', weeklyReadingGoal: 140, totalMinutesRead: 600 } 308 | ]; 309 | const allBooks = [ 310 | { bookID: 1, title: 'Goodnight Moon', author: 'Margaret Wise Brown', publicationYear: 1953 }, 311 | { bookID: 2, title: 'Green Eggs and Ham', author: 'Dr. Seuss', publicationYear: 1960 }, 312 | { bookID: 3, title: 'Where the Wild Things Are', author: 'Maurice Sendak', publicationYear: 1963 }, 313 | { bookID: 4, title: 'The Hobbit', author: 'J. R. R. Tolkien', publicationYear: 1937 }, 314 | { bookID: 5, title: 'Curious George', author: 'H. A. Rey', publicationYear: 1941 }, 315 | { bookID: 6, title: 'Alice\'s Adventures in Wonderland', author: 'Lewis Carroll', publicationYear: 1865 }, 316 | ]; 317 | 318 | 319 | /***/ }), 320 | 321 | /***/ 445: 322 | /*!**************************************************!*\ 323 | !*** ./src/app/edit-book/edit-book.component.ts ***! 324 | \**************************************************/ 325 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 326 | 327 | "use strict"; 328 | __webpack_require__.r(__webpack_exports__); 329 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 330 | /* harmony export */ "EditBookComponent": () => (/* binding */ EditBookComponent) 331 | /* harmony export */ }); 332 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ 4762); 333 | /* harmony import */ var _raw_loader_edit_book_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./edit-book.component.html */ 8367); 334 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 7716); 335 | /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/router */ 9895); 336 | /* harmony import */ var app_data__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/data */ 8387); 337 | 338 | 339 | 340 | 341 | 342 | let EditBookComponent = class EditBookComponent { 343 | constructor(route) { 344 | this.route = route; 345 | } 346 | ngOnInit() { 347 | let bookID = parseInt(this.route.snapshot.params['id']); 348 | this.selectedBook = app_data__WEBPACK_IMPORTED_MODULE_1__.allBooks.find(book => book.bookID === bookID); 349 | } 350 | setMostPopular() { 351 | console.warn('Setting most popular book not yet implemented.'); 352 | } 353 | saveChanges() { 354 | console.warn('Save changes to book not yet implemented.'); 355 | } 356 | }; 357 | EditBookComponent.ctorParameters = () => [ 358 | { type: _angular_router__WEBPACK_IMPORTED_MODULE_2__.ActivatedRoute } 359 | ]; 360 | EditBookComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([ 361 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.Component)({ 362 | selector: 'app-edit-book', 363 | template: _raw_loader_edit_book_component_html__WEBPACK_IMPORTED_MODULE_0__.default 364 | }) 365 | ], EditBookComponent); 366 | 367 | 368 | 369 | /***/ }), 370 | 371 | /***/ 6236: 372 | /*!******************************************************!*\ 373 | !*** ./src/app/edit-reader/edit-reader.component.ts ***! 374 | \******************************************************/ 375 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 376 | 377 | "use strict"; 378 | __webpack_require__.r(__webpack_exports__); 379 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 380 | /* harmony export */ "EditReaderComponent": () => (/* binding */ EditReaderComponent) 381 | /* harmony export */ }); 382 | /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ 4762); 383 | /* harmony import */ var _raw_loader_edit_reader_component_html__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !raw-loader!./edit-reader.component.html */ 4644); 384 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @angular/core */ 7716); 385 | /* harmony import */ var _angular_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/router */ 9895); 386 | /* harmony import */ var app_data__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! app/data */ 8387); 387 | 388 | 389 | 390 | 391 | 392 | let EditReaderComponent = class EditReaderComponent { 393 | constructor(route) { 394 | this.route = route; 395 | } 396 | ngOnInit() { 397 | let readerID = parseInt(this.route.snapshot.params['id']); 398 | this.selectedReader = app_data__WEBPACK_IMPORTED_MODULE_1__.allReaders.find(reader => reader.readerID === readerID); 399 | } 400 | saveChanges() { 401 | console.warn('Save reader not yet implemented.'); 402 | } 403 | }; 404 | EditReaderComponent.ctorParameters = () => [ 405 | { type: _angular_router__WEBPACK_IMPORTED_MODULE_2__.ActivatedRoute } 406 | ]; 407 | EditReaderComponent = (0,tslib__WEBPACK_IMPORTED_MODULE_3__.__decorate)([ 408 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_4__.Component)({ 409 | selector: 'app-edit-reader', 410 | template: _raw_loader_edit_reader_component_html__WEBPACK_IMPORTED_MODULE_0__.default 411 | }) 412 | ], EditReaderComponent); 413 | 414 | 415 | 416 | /***/ }), 417 | 418 | /***/ 2340: 419 | /*!*****************************************!*\ 420 | !*** ./src/environments/environment.ts ***! 421 | \*****************************************/ 422 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 423 | 424 | "use strict"; 425 | __webpack_require__.r(__webpack_exports__); 426 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 427 | /* harmony export */ "environment": () => (/* binding */ environment) 428 | /* harmony export */ }); 429 | // The file contents for the current environment will overwrite these during build. 430 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 431 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 432 | // The list of which env maps to which file can be found in `.angular-cli.json`. 433 | const environment = { 434 | production: false 435 | }; 436 | 437 | 438 | /***/ }), 439 | 440 | /***/ 4431: 441 | /*!*********************!*\ 442 | !*** ./src/main.ts ***! 443 | \*********************/ 444 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 445 | 446 | "use strict"; 447 | __webpack_require__.r(__webpack_exports__); 448 | /* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @angular/core */ 7716); 449 | /* harmony import */ var _angular_platform_browser_dynamic__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @angular/platform-browser-dynamic */ 4608); 450 | /* harmony import */ var _app_app_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./app/app.module */ 6747); 451 | /* harmony import */ var _environments_environment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./environments/environment */ 2340); 452 | 453 | 454 | 455 | 456 | if (_environments_environment__WEBPACK_IMPORTED_MODULE_1__.environment.production) { 457 | (0,_angular_core__WEBPACK_IMPORTED_MODULE_2__.enableProdMode)(); 458 | } 459 | (0,_angular_platform_browser_dynamic__WEBPACK_IMPORTED_MODULE_3__.platformBrowserDynamic)().bootstrapModule(_app_app_module__WEBPACK_IMPORTED_MODULE_0__.AppModule); 460 | 461 | 462 | /***/ }), 463 | 464 | /***/ 1249: 465 | /*!***********************************!*\ 466 | !*** ./src/app/app.component.css ***! 467 | \***********************************/ 468 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 469 | 470 | "use strict"; 471 | __webpack_require__.r(__webpack_exports__); 472 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 473 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 474 | /* harmony export */ }); 475 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhcHAuY29tcG9uZW50LmNzcyJ9 */"); 476 | 477 | /***/ }), 478 | 479 | /***/ 7052: 480 | /*!****************************************************************************************!*\ 481 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/add-book/add-book.component.html ***! 482 | \****************************************************************************************/ 483 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 484 | 485 | "use strict"; 486 | __webpack_require__.r(__webpack_exports__); 487 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 488 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 489 | /* harmony export */ }); 490 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
\r\n
\r\n
\r\n
\r\n Add New Book\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
"); 491 | 492 | /***/ }), 493 | 494 | /***/ 1699: 495 | /*!********************************************************************************************!*\ 496 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/add-reader/add-reader.component.html ***! 497 | \********************************************************************************************/ 498 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 499 | 500 | "use strict"; 501 | __webpack_require__.r(__webpack_exports__); 502 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 503 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 504 | /* harmony export */ }); 505 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
\r\n
\r\n
\r\n
\r\n Add Reader\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
"); 506 | 507 | /***/ }), 508 | 509 | /***/ 1106: 510 | /*!**************************************************************************!*\ 511 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/app.component.html ***! 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 */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 519 | /* harmony export */ }); 520 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\r\n\r\n\r\n"); 521 | 522 | /***/ }), 523 | 524 | /***/ 9306: 525 | /*!******************************************************************************************!*\ 526 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/dashboard/dashboard.component.html ***! 527 | \******************************************************************************************/ 528 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 529 | 530 | "use strict"; 531 | __webpack_require__.r(__webpack_exports__); 532 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 533 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 534 | /* harmony export */ }); 535 | /* 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
    "); 536 | 537 | /***/ }), 538 | 539 | /***/ 8367: 540 | /*!******************************************************************************************!*\ 541 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/edit-book/edit-book.component.html ***! 542 | \******************************************************************************************/ 543 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 544 | 545 | "use strict"; 546 | __webpack_require__.r(__webpack_exports__); 547 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 548 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 549 | /* harmony export */ }); 550 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Edit Book\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 551 | 552 | /***/ }), 553 | 554 | /***/ 4644: 555 | /*!**********************************************************************************************!*\ 556 | !*** ./node_modules/raw-loader/dist/cjs.js!./src/app/edit-reader/edit-reader.component.html ***! 557 | \**********************************************************************************************/ 558 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 559 | 560 | "use strict"; 561 | __webpack_require__.r(__webpack_exports__); 562 | /* harmony export */ __webpack_require__.d(__webpack_exports__, { 563 | /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) 564 | /* harmony export */ }); 565 | /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("
    \r\n
    \r\n
    \r\n
    \r\n Edit Reader\r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    \r\n
    "); 566 | 567 | /***/ }) 568 | 569 | }, 570 | /******/ __webpack_require__ => { // webpackRuntimeModules 571 | /******/ "use strict"; 572 | /******/ 573 | /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) 574 | /******/ __webpack_require__.O(0, ["vendor"], () => (__webpack_exec__(4431))); 575 | /******/ var __webpack_exports__ = __webpack_require__.O(); 576 | /******/ } 577 | ]); 578 | //# sourceMappingURL=main.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/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/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';\r\n\r\n@Component({\r\n selector: 'app-root',\r\n templateUrl: './app.component.html',\r\n styleUrls: ['./app.component.css']\r\n})\r\nexport class AppComponent {\r\n title = 'app';\r\n}\r\n","import { BrowserModule } from '@angular/platform-browser';\r\nimport { 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\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 imports: [\r\n BrowserModule,\r\n AppRoutingModule,\r\n FormsModule\r\n ],\r\n providers: [],\r\n bootstrap: [AppComponent]\r\n})\r\nexport class AppModule { }\r\n","import { Component, OnInit } from '@angular/core';\r\n\r\nimport { Book } from \"app/models/book\";\r\nimport { allBooks, allReaders } from 'app/data';\r\nimport { Reader } from \"app/models/reader\";\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[] = allBooks;\r\n allReaders: Reader[] = allReaders;\r\n mostPopularBook: Book = allBooks[0];\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\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: 'Green Eggs and Ham', author: 'Dr. Seuss', publicationYear: 1960 },\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 { allBooks } from 'app/data';\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\r\n ngOnInit() {\r\n let bookID: number = parseInt(this.route.snapshot.params['id']);\r\n this.selectedBook = allBooks.find(book => book.bookID === bookID);\r\n }\r\n\r\n setMostPopular(): void {\r\n console.warn('Setting most popular book not yet implemented.');\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 { allReaders } from 'app/data';\r\nimport { Reader } from \"app/models/reader\";\r\n\r\n@Component({\r\n selector: 'app-edit-reader',\r\n templateUrl: './edit-reader.component.html',\r\n styles: []\r\n})\r\nexport class EditReaderComponent implements OnInit {\r\n\r\n selectedReader: Reader;\r\n\r\n constructor(private route: ActivatedRoute) { }\r\n\r\n ngOnInit() {\r\n let readerID: number = parseInt(this.route.snapshot.params['id']);\r\n this.selectedReader = allReaders.find(reader => reader.readerID === readerID);\r\n }\r\n\r\n saveChanges() {\r\n console.warn('Save reader not yet implemented.');\r\n }\r\n}\r\n","// The file contents for the current environment will overwrite these during build.\r\n// The build system defaults to the dev environment which uses `environment.ts`, but if you do\r\n// `ng build --env=prod` then `environment.prod.ts` will be used instead.\r\n// The list of which env maps to which file can be found in `.angular-cli.json`.\r\n\r\nexport const environment = {\r\n production: false\r\n};\r\n","import { enableProdMode } from '@angular/core';\r\nimport { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\n\r\nimport { AppModule } from './app/app.module';\r\nimport { environment } from './environments/environment';\r\n\r\nif (environment.production) {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule);\r\n","export default \"\\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJhcHAuY29tcG9uZW50LmNzcyJ9 */\";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Add New Book\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Add Reader\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"\\r\\n\\r\\n\\r\\n\";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n

    All Books

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

    All Readers

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

    Most Popular Book

    \\r\\n
    \\r\\n
    \\r\\n {{mostPopularBook.title}} by {{mostPopularBook.author}}\\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Edit Book\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";","export default \"
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n Edit Reader\\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \\r\\n
    \";"],"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/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:///"} -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.1.1", 16 | "@angular/common": "12.1.1", 17 | "@angular/compiler": "12.1.1", 18 | "@angular/core": "12.1.1", 19 | "@angular/forms": "12.1.1", 20 | "@angular/platform-browser": "12.1.1", 21 | "@angular/platform-browser-dynamic": "12.1.1", 22 | "@angular/router": "12.1.1", 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.1.1", 36 | "@angular/cli": "12.1.1", 37 | "@angular/compiler-cli": "12.1.1", 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.3.5", 52 | "concurrently": "5.3.0" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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; -------------------------------------------------------------------------------- /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": "Green Eggs and Ham", 11 | "author": "Dr. Seuss", 12 | "publicationYear": "1960" 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 | ] -------------------------------------------------------------------------------- /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 | ] -------------------------------------------------------------------------------- /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/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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /server/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /server/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /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/add-book/add-book.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Add New Book 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | 27 |
    28 |
    29 |
    30 |
    31 |
    32 |
    -------------------------------------------------------------------------------- /src/app/add-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.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Add Reader 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | 27 |
    28 |
    29 |
    30 |
    31 |
    32 |
    -------------------------------------------------------------------------------- /src/app/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/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/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { 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 | 13 | @NgModule({ 14 | declarations: [ 15 | AppComponent, 16 | DashboardComponent, 17 | AddBookComponent, 18 | EditReaderComponent, 19 | EditBookComponent, 20 | AddReaderComponent 21 | ], 22 | imports: [ 23 | BrowserModule, 24 | AppRoutingModule, 25 | FormsModule 26 | ], 27 | providers: [], 28 | bootstrap: [AppComponent] 29 | }) 30 | export class AppModule { } 31 | -------------------------------------------------------------------------------- /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/dashboard/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | import { Book } from "app/models/book"; 4 | import { allBooks, allReaders } from 'app/data'; 5 | import { Reader } from "app/models/reader"; 6 | 7 | @Component({ 8 | selector: 'app-dashboard', 9 | templateUrl: './dashboard.component.html', 10 | styles: [] 11 | }) 12 | export class DashboardComponent implements OnInit { 13 | 14 | allBooks: Book[] = allBooks; 15 | allReaders: Reader[] = allReaders; 16 | mostPopularBook: Book = allBooks[0]; 17 | 18 | constructor() { } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | deleteBook(bookID: number): void { 24 | console.warn(`Delete book not yet implemented (bookID: ${bookID}).`); 25 | } 26 | 27 | deleteReader(readerID: number): void { 28 | console.warn(`Delete reader not yet implemented (readerID: ${readerID}).`); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /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: 'Green Eggs and Ham', author: 'Dr. Seuss', publicationYear: 1960 }, 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 | ]; -------------------------------------------------------------------------------- /src/app/edit-book/edit-book.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Edit Book 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | 27 | 28 |
    29 |
    30 |
    31 |
    32 |
    33 |
    -------------------------------------------------------------------------------- /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 { allBooks } from 'app/data'; 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 | 18 | ngOnInit() { 19 | let bookID: number = parseInt(this.route.snapshot.params['id']); 20 | this.selectedBook = allBooks.find(book => book.bookID === bookID); 21 | } 22 | 23 | setMostPopular(): void { 24 | console.warn('Setting most popular book not yet implemented.'); 25 | } 26 | 27 | saveChanges(): void { 28 | console.warn('Save changes to book not yet implemented.'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/edit-reader/edit-reader.component.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 | Edit Reader 6 |
    7 | 8 |
    9 | 10 |
    11 |
    12 |
    13 | 14 |
    15 | 16 |
    17 |
    18 |
    19 | 20 |
    21 | 22 |
    23 |
    24 |
    25 |
    26 | 27 |
    28 |
    29 |
    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 { allReaders } from 'app/data'; 5 | import { Reader } from "app/models/reader"; 6 | 7 | @Component({ 8 | selector: 'app-edit-reader', 9 | templateUrl: './edit-reader.component.html', 10 | styles: [] 11 | }) 12 | export class EditReaderComponent implements OnInit { 13 | 14 | selectedReader: Reader; 15 | 16 | constructor(private route: ActivatedRoute) { } 17 | 18 | ngOnInit() { 19 | let readerID: number = parseInt(this.route.snapshot.params['id']); 20 | this.selectedReader = allReaders.find(reader => reader.readerID === readerID); 21 | } 22 | 23 | saveChanges() { 24 | console.warn('Save reader not yet implemented.'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/models/book.ts: -------------------------------------------------------------------------------- 1 | export class Book { 2 | bookID: number; 3 | title: string; 4 | author: string; 5 | publicationYear: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/app/models/reader.ts: -------------------------------------------------------------------------------- 1 | export class Reader { 2 | readerID: number; 3 | name: string; 4 | weeklyReadingGoal: number; 5 | totalMinutesRead: number; 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/src/favicon.ico -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bricewilson/angular-services/8567805366718b5ebc4ed9554f4b649a0401533b/src/styles.css -------------------------------------------------------------------------------- /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/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "eofline": true, 15 | "forin": true, 16 | "import-blacklist": [ 17 | true 18 | ], 19 | "import-spacing": true, 20 | "indent": [ 21 | true, 22 | "spaces" 23 | ], 24 | "interface-over-type-literal": true, 25 | "label-position": true, 26 | "max-line-length": [ 27 | true, 28 | 140 29 | ], 30 | "member-access": false, 31 | "member-ordering": [ 32 | true, 33 | "static-before-instance", 34 | "variables-before-functions" 35 | ], 36 | "no-arg": true, 37 | "no-bitwise": true, 38 | "no-console": [ 39 | true, 40 | "debug", 41 | "info", 42 | "time", 43 | "timeEnd", 44 | "trace" 45 | ], 46 | "no-construct": true, 47 | "no-debugger": true, 48 | "no-duplicate-super": true, 49 | "no-empty": false, 50 | "no-empty-interface": true, 51 | "no-eval": true, 52 | "no-inferrable-types": [ 53 | true, 54 | "ignore-params" 55 | ], 56 | "no-misused-new": true, 57 | "no-non-null-assertion": true, 58 | "no-shadowed-variable": true, 59 | "no-string-literal": false, 60 | "no-string-throw": true, 61 | "no-switch-case-fall-through": true, 62 | "no-trailing-whitespace": true, 63 | "no-unnecessary-initializer": true, 64 | "no-unused-expression": true, 65 | "no-use-before-declare": true, 66 | "no-var-keyword": true, 67 | "object-literal-sort-keys": false, 68 | "one-line": [ 69 | true, 70 | "check-open-brace", 71 | "check-catch", 72 | "check-else", 73 | "check-whitespace" 74 | ], 75 | "prefer-const": true, 76 | "quotemark": [ 77 | true, 78 | "single" 79 | ], 80 | "radix": true, 81 | "semicolon": [ 82 | "always" 83 | ], 84 | "triple-equals": [ 85 | true, 86 | "allow-null-check" 87 | ], 88 | "typedef-whitespace": [ 89 | true, 90 | { 91 | "call-signature": "nospace", 92 | "index-signature": "nospace", 93 | "parameter": "nospace", 94 | "property-declaration": "nospace", 95 | "variable-declaration": "nospace" 96 | } 97 | ], 98 | "typeof-compare": true, 99 | "unified-signatures": true, 100 | "variable-name": false, 101 | "whitespace": [ 102 | true, 103 | "check-branch", 104 | "check-decl", 105 | "check-operator", 106 | "check-separator", 107 | "check-type" 108 | ], 109 | "directive-selector": [ 110 | true, 111 | "attribute", 112 | "app", 113 | "camelCase" 114 | ], 115 | "component-selector": [ 116 | true, 117 | "element", 118 | "app", 119 | "kebab-case" 120 | ], 121 | "use-input-property-decorator": true, 122 | "use-output-property-decorator": true, 123 | "use-host-property-decorator": true, 124 | "no-input-rename": true, 125 | "no-output-rename": true, 126 | "use-life-cycle-interface": true, 127 | "use-pipe-transform-interface": true, 128 | "component-class-suffix": true, 129 | "directive-class-suffix": true, 130 | "no-access-missing-member": true, 131 | "templates-use-public": true, 132 | "invoke-injectable": true 133 | } 134 | } 135 | --------------------------------------------------------------------------------