├── .dockerignore ├── .gitignore ├── app ├── typings.d.ts ├── booking.js ├── booking.js.map ├── bookings-doc.ts ├── bookings-doc.js.map ├── bookings-doc.js ├── main.js.map ├── booking.ts ├── main.js ├── booking-status.pipe.ts ├── main.ts ├── booking-status.pipe.js.map ├── vendor.ts ├── flightsearch.component.css ├── polyfills.ts ├── app.module.ts ├── booking-status.pipe.js ├── flightsearch.component.html ├── booking.service.js.map ├── service-worker │ └── service-worker.ts ├── booking.service.ts ├── flightsearch.component.js.map ├── flightsearch.component.ts ├── booking.service.js └── flightsearch.component.js ├── dist ├── app │ ├── booking.js │ ├── booking.js.map │ ├── bookings-doc.js.map │ ├── bookings-doc.js │ ├── main.js.map │ ├── vendor.js.map │ ├── booking-status.pipe.js.map │ ├── vendor.js │ ├── main.js │ ├── polyfills.js.map │ ├── app.module.js.map │ ├── polyfills.js │ ├── booking-status.pipe.js │ ├── service-worker │ │ ├── service-worker.js.map │ │ └── service-worker.js │ ├── app.module.js │ ├── booking.service.js.map │ ├── flightsearch.component.js.map │ ├── booking.service.js │ └── flightsearch.component.js ├── sw-boot.js └── sw-boot.js.map ├── favicon.ico ├── img ├── qr.png └── notfound.png ├── images ├── hamburger.svg └── touch │ ├── icon-128x128.png │ ├── apple-touch-icon.png │ ├── chrome-touch-icon-192x192.png │ └── ms-touch-icon-144x144-precomposed.png ├── declarations.d.ts ├── webpack.config.js ├── .idea ├── jsLibraryMappings.xml ├── modules.xml ├── typescript-compiler.xml ├── src-webpack.iml └── workspace.xml ├── .vscode └── tasks.json ├── typings.json ├── sw-boot.js ├── .editorconfig ├── tsconfig.json ├── styles.css ├── manifest.json ├── webpack.sw.config.js ├── webpack.app.config.js ├── index.html ├── readme.md ├── package.json └── data └── buchungen.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | typings -------------------------------------------------------------------------------- /app/typings.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare var PouchDB: any -------------------------------------------------------------------------------- /app/booking.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //# sourceMappingURL=booking.js.map -------------------------------------------------------------------------------- /dist/app/booking.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //# sourceMappingURL=booking.js.map -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/favicon.ico -------------------------------------------------------------------------------- /img/qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/img/qr.png -------------------------------------------------------------------------------- /app/booking.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking.js","sourceRoot":"","sources":["booking.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /img/notfound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/img/notfound.png -------------------------------------------------------------------------------- /dist/app/booking.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking.js","sourceRoot":"","sources":["../../app/booking.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /images/hamburger.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/touch/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/images/touch/icon-128x128.png -------------------------------------------------------------------------------- /declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare var toolbox: any; 2 | declare var caches: any; 3 | declare var System: any; 4 | declare var Headers: any; 5 | declare var fetch: any; -------------------------------------------------------------------------------- /images/touch/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/images/touch/apple-touch-icon.png -------------------------------------------------------------------------------- /images/touch/chrome-touch-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/images/touch/chrome-touch-icon-192x192.png -------------------------------------------------------------------------------- /images/touch/ms-touch-icon-144x144-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manfredsteyer/progresive-web-apps-with-angular-2-demo/HEAD/images/touch/ms-touch-icon-144x144-precomposed.png -------------------------------------------------------------------------------- /app/bookings-doc.ts: -------------------------------------------------------------------------------- 1 | import {Booking} from './booking'; 2 | 3 | export class BookingsDoc { 4 | _id: string; 5 | _rev: string; 6 | 7 | bookings: Array; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /app/bookings-doc.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bookings-doc.js","sourceRoot":"","sources":["bookings-doc.ts"],"names":[],"mappings":";AAEA;IAAA;IAKA,CAAC;IAAD,kBAAC;AAAD,CAAC,AALD,IAKC;AALY,mBAAW,cAKvB,CAAA"} -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpackAppConfig = require("./webpack.app.config"); 2 | var webpackSwConfig = require("./webpack.sw.config"); 3 | 4 | module.exports = [ 5 | webpackAppConfig, 6 | webpackSwConfig 7 | ]; 8 | -------------------------------------------------------------------------------- /dist/app/bookings-doc.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bookings-doc.js","sourceRoot":"","sources":["../../app/bookings-doc.ts"],"names":[],"mappings":";AAEA;IAAA;IAKA,CAAC;IAAD,kBAAC;AAAD,CAAC,AALD,IAKC;AALY,mBAAW,cAKvB,CAAA"} -------------------------------------------------------------------------------- /app/bookings-doc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var BookingsDoc = (function () { 3 | function BookingsDoc() { 4 | } 5 | return BookingsDoc; 6 | }()); 7 | exports.BookingsDoc = BookingsDoc; 8 | //# sourceMappingURL=bookings-doc.js.map -------------------------------------------------------------------------------- /dist/app/bookings-doc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var BookingsDoc = (function () { 3 | function BookingsDoc() { 4 | } 5 | return BookingsDoc; 6 | }()); 7 | exports.BookingsDoc = BookingsDoc; 8 | //# sourceMappingURL=bookings-doc.js.map -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/typescript-compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /dist/app/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sourceRoot":"","sources":["../../app/main.ts"],"names":[],"mappings":";AAAA,yCAAqC,mCAAmC,CAAC,CAAA;AACzE,2BAAwB,cAAc,CAAC,CAAA;AACvC;;;;;;;;EAQE;AAEF,iDAAsB,EAAE,CAAC,eAAe,CAAC,sBAAS,CAAC;KAChD,KAAK,CAAC,UAAA,GAAG,IAAI,OAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAlB,CAAkB,CAAC,CAAC"} -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "tsc", 6 | "isShellCommand": true, 7 | "args": ["-p", "."], 8 | "showOutput": "silent", 9 | "problemMatcher": "$tsc" 10 | } -------------------------------------------------------------------------------- /app/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sourceRoot":"","sources":["main.ts"],"names":[],"mappings":";AAAA,yCAA2B,mCAAmC,CAAC,CAAA;AAC/D,qBAA6B,eAAe,CAAC,CAAA;AAC7C,uCAAoC,0BAA0B,CAAC,CAAA;AAC/D,QAAO,uBAAuB,CAAC,CAAA;AAC/B,QAAO,6BAA6B,CAAC,CAAA;AAGrC,IAAI,OAAO,GAAG;IACV,qBAAc;CACjB,CAAC;AAEF,oCAAS,CAAC,8CAAqB,EAAE,OAAO,CAAC,CAAC"} -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-seed", 3 | "version": false, 4 | "dependencies": {}, 5 | "globalDependencies": { 6 | "core-js": "registry:dt/core-js#0.0.0+20160602141332", 7 | "hammerjs": "registry:dt/hammerjs#2.0.8+20160724063812", 8 | "node": "registry:dt/node#6.0.0+20160621231320" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/booking.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface Booking { 3 | 4 | flugId: number; 5 | passagierId: number; 6 | buchungsStatus: number; 7 | flug: Flight; 8 | 9 | isDirty: boolean; 10 | 11 | } 12 | 13 | export interface Flight { 14 | id: number; 15 | abflugsort: string; 16 | zielort: string; 17 | datum: string; 18 | } -------------------------------------------------------------------------------- /dist/sw-boot.js: -------------------------------------------------------------------------------- 1 | //import "./app/service-worker/service-worker"; 2 | var context = self; 3 | context.addEventListener('install', function (event) { event.waitUntil(context.skipWaiting()); }); 4 | context.addEventListener('activate', function (event) { event.waitUntil(context.clients.claim()); }); 5 | //importScripts("dist/vendor.js"); 6 | importScripts("dist/sw.js"); 7 | // v7 8 | //# sourceMappingURL=sw-boot.js.map -------------------------------------------------------------------------------- /sw-boot.js: -------------------------------------------------------------------------------- 1 | //import "./app/service-worker/service-worker"; 2 | 3 | if(typeof window != "object") self.window = self; 4 | 5 | var context = self; 6 | context.addEventListener('install', function(event) { event.waitUntil(context.skipWaiting()) }); 7 | context.addEventListener('activate', function(event) { event.waitUntil(context.clients.claim())}); 8 | 9 | importScripts("dist/sw.js"); 10 | 11 | // v8 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | 13 | [*.md] 14 | max_line_length = 0 15 | trim_trailing_whitespace = false 16 | 17 | # Indentation override 18 | #[lib/**.js] 19 | #[{package.json,.travis.yml}] 20 | #[**/**.js] 21 | -------------------------------------------------------------------------------- /dist/app/vendor.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"vendor.js","sourceRoot":"","sources":["../../app/vendor.ts"],"names":[],"mappings":"AAAA,UAAU;;AAEV,YAAY;AACZ,QAAO,mCAAmC,CAAC,CAAA;AAC3C,QAAO,2BAA2B,CAAC,CAAA;AACnC,QAAO,eAAe,CAAC,CAAA;AACvB,QAAO,eAAe,CAAC,CAAA;AACvB,QAAO,iBAAiB,CAAC,CAAA;AAGzB,SAAS;AACT,oBAAoB;AACpB,QAAO,uBAAuB,CAAC,CAAA;AAC/B,QAAO,6BAA6B,CAAC,CAAA;AAErC,oBAAoB;AACpB,QAAO,SAAS,CAAC,CAAA;AAEjB,wEAAwE;AACxE,iGAAiG"} -------------------------------------------------------------------------------- /dist/sw-boot.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"sw-boot.js","sourceRoot":"","sources":["../sw-boot.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAE/C,IAAI,OAAO,GAAQ,IAAI,CAAC;AACxB,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,UAAS,KAAU,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA,CAAC,CAAC,CAAC,CAAC;AACrG,OAAO,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAS,KAAU,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA,CAAA,CAAC,CAAC,CAAC;AAEvG,kCAAkC;AAClC,aAAa,CAAC,YAAY,CAAC,CAAC;AAI5B,KAAK"} -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var platform_browser_dynamic_1 = require('@angular/platform-browser-dynamic'); 3 | var http_1 = require('@angular/http'); 4 | var flightsearch_component_1 = require('./flightsearch.component'); 5 | require('rxjs/add/operator/map'); 6 | require('rxjs/add/operator/toPromise'); 7 | var service = [ 8 | http_1.HTTP_PROVIDERS 9 | ]; 10 | platform_browser_dynamic_1.bootstrap(flightsearch_component_1.FlightSearchComponent, service); 11 | //# sourceMappingURL=main.js.map -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "outDir": "dist", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "moduleResolution": "node" 10 | }, 11 | "exclude": [ 12 | "typings/main.d.ts", 13 | "typings/main", 14 | "node_modules" 15 | ], 16 | "compileOnSave": false, 17 | "buildOnSave": false, 18 | "atom": { "rewriteTsconfig": false } 19 | } 20 | -------------------------------------------------------------------------------- /app/booking-status.pipe.ts: -------------------------------------------------------------------------------- 1 | 2 | import {Pipe, PipeTransform } from '@angular/core'; 3 | 4 | @Pipe({ 5 | name: 'bookingStatus', 6 | pure: true 7 | }) 8 | export class BookingStatusPipe implements PipeTransform { 9 | 10 | transform(value: any, ...args: any[]): any { 11 | 12 | switch(value) { 13 | case 0: return "Booked (not checked in)"; 14 | case 1: return "Checked in"; 15 | case 2: return "Boarded"; 16 | } 17 | 18 | } 19 | } -------------------------------------------------------------------------------- /.idea/src-webpack.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/main.ts: -------------------------------------------------------------------------------- 1 | import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; 2 | import {AppModule} from "./app.module"; 3 | /* 4 | let runtime = require('serviceworker-webpack-plugin/lib/runtime'); 5 | 6 | if ('serviceWorker' in navigator) { 7 | console.debug('registering service-worker'); 8 | runtime.register().then(() => console.debug('ok')).catch((err) => console.error('error service worker start', err)); 9 | 10 | } 11 | */ 12 | 13 | platformBrowserDynamic().bootstrapModule(AppModule) 14 | .catch(err => console.error(err)); 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/booking-status.pipe.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking-status.pipe.js","sourceRoot":"","sources":["booking-status.pipe.ts"],"names":[],"mappings":";;;;;;;;;;AACA,qBAAmC,eAAe,CAAC,CAAA;AAMnD;IAAA;IAWA,CAAC;IATG,qCAAS,GAAT,UAAU,KAAU;QAAE,cAAc;aAAd,WAAc,CAAd,sBAAc,CAAd,IAAc;YAAd,6BAAc;;QAEhC,MAAM,CAAA,CAAC,KAAK,CAAC,CAAC,CAAC;YACX,KAAK,CAAC,EAAE,MAAM,CAAC,yBAAyB,CAAC;YACzC,KAAK,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC;YAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;QAC7B,CAAC;IAEL,CAAC;IAdL;QAAC,WAAI,CAAC;YACF,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,IAAI;SACb,CAAC;;yBAAA;IAYF,wBAAC;AAAD,CAAC,AAXD,IAWC;AAXY,yBAAiB,oBAW7B,CAAA"} -------------------------------------------------------------------------------- /app/vendor.ts: -------------------------------------------------------------------------------- 1 | // Vendors 2 | 3 | // Angular 2 4 | import '@angular/platform-browser-dynamic'; 5 | import '@angular/platform-browser'; 6 | import '@angular/core'; 7 | import '@angular/http'; 8 | import '@angular/router'; 9 | 10 | 11 | // RxJS 5 12 | // import 'rxjs/Rx'; 13 | import 'rxjs/add/operator/map'; 14 | import 'rxjs/add/operator/toPromise'; 15 | 16 | //import 'hammerjs'; 17 | import 'pouchdb'; 18 | 19 | // For vendors for example jQuery, Lodash, angular2-jwt import them here 20 | // Also see src/typings.d.ts as you also need to run `typings install x` where `x` is your module 21 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Master Styles */ 2 | h1 { 3 | color: #369; 4 | font-family: Arial, Helvetica, sans-serif; 5 | font-size: 250%; 6 | } 7 | h2, h3 { 8 | color: #444; 9 | font-family: Arial, Helvetica, sans-serif; 10 | font-weight: lighter; 11 | } 12 | body { 13 | margin: 2em; 14 | } 15 | body, input[text], button { 16 | color: #888; 17 | font-family: Cambria, Georgia; 18 | } 19 | 20 | /* 21 | * See https://github.com/angular/angular.io/blob/master/public/docs/_examples/styles.css 22 | * for the full set of master styles used by the documentation samples 23 | */ 24 | -------------------------------------------------------------------------------- /dist/app/booking-status.pipe.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking-status.pipe.js","sourceRoot":"","sources":["../../app/booking-status.pipe.ts"],"names":[],"mappings":";;;;;;;;;;AACA,qBAAmC,eAAe,CAAC,CAAA;AAMnD;IAAA;IAWA,CAAC;IATG,qCAAS,GAAT,UAAU,KAAU;QAAE,cAAc;aAAd,WAAc,CAAd,sBAAc,CAAd,IAAc;YAAd,6BAAc;;QAEhC,MAAM,CAAA,CAAC,KAAK,CAAC,CAAC,CAAC;YACX,KAAK,CAAC,EAAE,MAAM,CAAC,yBAAyB,CAAC;YACzC,KAAK,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC;YAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;QAC7B,CAAC;IAEL,CAAC;IAdL;QAAC,WAAI,CAAC;YACF,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,IAAI;SACb,CAAC;;yBAAA;IAYF,wBAAC;AAAD,CAAC,AAXD,IAWC;AAXY,yBAAiB,oBAW7B,CAAA"} -------------------------------------------------------------------------------- /dist/app/vendor.js: -------------------------------------------------------------------------------- 1 | // Vendors 2 | "use strict"; 3 | // Angular 2 4 | require('@angular/platform-browser-dynamic'); 5 | require('@angular/platform-browser'); 6 | require('@angular/core'); 7 | require('@angular/http'); 8 | require('@angular/router'); 9 | // RxJS 5 10 | // import 'rxjs/Rx'; 11 | require('rxjs/add/operator/map'); 12 | require('rxjs/add/operator/toPromise'); 13 | //import 'hammerjs'; 14 | require('pouchdb'); 15 | // For vendors for example jQuery, Lodash, angular2-jwt import them here 16 | // Also see src/typings.d.ts as you also need to run `typings install x` where `x` is your module 17 | //# sourceMappingURL=vendor.js.map -------------------------------------------------------------------------------- /dist/app/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var platform_browser_dynamic_1 = require('@angular/platform-browser-dynamic'); 3 | var app_module_1 = require("./app.module"); 4 | /* 5 | let runtime = require('serviceworker-webpack-plugin/lib/runtime'); 6 | 7 | if ('serviceWorker' in navigator) { 8 | console.debug('registering service-worker'); 9 | runtime.register().then(() => console.debug('ok')).catch((err) => console.error('error service worker start', err)); 10 | 11 | } 12 | */ 13 | platform_browser_dynamic_1.platformBrowserDynamic().bootstrapModule(app_module_1.AppModule) 14 | .catch(function (err) { return console.error(err); }); 15 | //# sourceMappingURL=main.js.map -------------------------------------------------------------------------------- /dist/app/polyfills.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"polyfills.js","sourceRoot":"","sources":["../../app/polyfills.ts"],"names":[],"mappings":"AAAA,YAAY;;AAEZ,QAAO,SAAS,CAAC,CAAA,CAAC,8BAA8B;AAEhD,wBAAwB;AACxB,gGAAgG;AAChG,QAAO,oBAAoB,CAAC,CAAA;AAC5B,QAAO,oBAAoB,CAAC,CAAA;AAC5B,QAAO,sBAAsB,CAAC,CAAA;AAC9B,QAAO,uBAAuB,CAAC,CAAA;AAC/B,QAAO,yBAAyB,CAAC,CAAA;AACjC,QAAO,oBAAoB,CAAC,CAAA;AAC5B,QAAO,kBAAkB,CAAC,CAAA;AAC1B,QAAO,oBAAoB,CAAC,CAAA;AAC5B,QAAO,kBAAkB,CAAC,CAAA;AAC1B,QAAO,mBAAmB,CAAC,CAAA;AAC3B,QAAO,oBAAoB,CAAC,CAAA;AAC5B,QAAO,iBAAiB,CAAC,CAAA;AACzB,QAAO,iBAAiB,CAAC,CAAA;AACzB,QAAO,sBAAsB,CAAC,CAAA;AAC9B,QAAO,sBAAsB,CAAC,CAAA;AAC9B,QAAO,mBAAmB,CAAC,CAAA;AAC3B,QAAO,qBAAqB,CAAC,CAAA;AAC7B,gFAAgF;AAChF,gCAAgC;AAEhC,QAAO,qBAAqB,CAAC,CAAA;AAC7B,QAAO,mBAAmB,CAAC,CAAA;AAC3B,QAAO,oCAAoC,CAAC,CAAA"} -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PWA-Demo Flight", 3 | "short_name": "PWA Flight", 4 | "gcm_sender_id": "1004270452653", 5 | "permissions": [ 6 | "gcm" 7 | ], 8 | "icons": [{ 9 | "src": "images/touch/icon-128x128.png", 10 | "sizes": "128x128", 11 | "type": "image/png" 12 | }, { 13 | "src": "images/touch/apple-touch-icon.png", 14 | "sizes": "152x152", 15 | "type": "image/png" 16 | }, { 17 | "src": "images/touch/ms-touch-icon-144x144-precomposed.png", 18 | "sizes": "144x144", 19 | "type": "image/png" 20 | }, { 21 | "src": "images/touch/chrome-touch-icon-192x192.png", 22 | "sizes": "192x192", 23 | "type": "image/png" 24 | }], 25 | "start_url": "/index.html?homescreen=1", 26 | "display": "standalone", 27 | "background_color": "#3E4EB8", 28 | "theme_color": "#2F3BA2" 29 | } 30 | -------------------------------------------------------------------------------- /dist/app/app.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../../app/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,qBAAuB,eAAe,CAAC,CAAA;AACvC,iCAA4B,2BAA2B,CAAC,CAAA;AACxD,qBAAyB,eAAe,CAAC,CAAA;AACzC,sBAA0B,gBAAgB,CAAC,CAAA;AAC3C,oCAAgC,uBAAuB,CAAC,CAAA;AACxD,uCAAoC,0BAA0B,CAAC,CAAA;AAC/D,qBAA2B,yBAAyB,CAAC,CAAA;AACrD,uBAA6B,2BAA2B,CAAC,CAAA;AACzD,qBAA2B,yBAAyB,CAAC,CAAA;AACrD,wBAA8B,4BAA4B,CAAC,CAAA;AAC3D,wBAA8B,4BAA4B,CAAC,CAAA;AAC3D,qBAA2B,yBAAyB,CAAC,CAAA;AAuBrD;IAAA;IACA,CAAC;IAtBD;QAAC,eAAQ,CAAC;YACN,OAAO,EAAE;gBACL,gCAAa;gBACb,iBAAU;gBACV,mBAAW;gBACX,uBAAc,CAAC,OAAO,EAAE;gBACxB,mBAAY,CAAC,OAAO,EAAE;gBACtB,mBAAY,CAAC,OAAO,EAAE;gBACtB,mBAAY,CAAC,OAAO,EAAE;gBACtB,yBAAe,CAAC,OAAO,EAAE;gBACzB,yBAAe,CAAC,OAAO,EAAE;aAC5B;YACD,YAAY,EAAE;gBACV,uCAAiB,EAAE,8CAAqB;aAC3C;YACD,SAAS,EAAE,EACV;YACD,SAAS,EAAE;gBACT,8CAAqB;aACtB;SACJ,CAAC;;iBAAA;IAEF,gBAAC;AAAD,CAAC,AADD,IACC;AADY,iBAAS,YACrB,CAAA"} -------------------------------------------------------------------------------- /app/flightsearch.component.css: -------------------------------------------------------------------------------- 1 | 2 | .card { 3 | background-color: #FFFF99; 4 | border-color:#FFCC00; 5 | border-width: 2px; 6 | border-style: solid; 7 | padding:10px; 8 | margin-bottom: 40px; 9 | } 10 | 11 | 12 | * { 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | .secondary { 18 | color: rgba(0,0,0,0.54); 19 | } 20 | 21 | [md-fab] { 22 | position: absolute; 23 | right: 3%; 24 | top: 34px; 25 | z-index: 1; 26 | } 27 | 28 | md-sidenav-layout { 29 | background: rgba(0,0,0,0.03); 30 | } 31 | 32 | md-input { 33 | margin: 8px 0; 34 | width: 100%; 35 | } 36 | 37 | md-radio-button, md-checkbox { 38 | margin: 16px 8px; 39 | } 40 | 41 | .form { 42 | display: flex; 43 | } 44 | 45 | .form md-card { 46 | flex-grow: 1; 47 | } 48 | 49 | md-card { 50 | width: 400px; 51 | box-sizing: border-box; 52 | margin: 16px; 53 | } 54 | 55 | .card-container { 56 | display: flex; 57 | flex-flow: row wrap; 58 | } -------------------------------------------------------------------------------- /app/polyfills.ts: -------------------------------------------------------------------------------- 1 | // Polyfills 2 | 3 | import 'ie-shim'; // Internet Explorer 9 support 4 | 5 | // import 'core-js/es6'; 6 | // Added parts of es6 which are necessary for your project or your browser support requirements. 7 | import 'core-js/es6/symbol'; 8 | import 'core-js/es6/object'; 9 | import 'core-js/es6/function'; 10 | import 'core-js/es6/parse-int'; 11 | import 'core-js/es6/parse-float'; 12 | import 'core-js/es6/number'; 13 | import 'core-js/es6/math'; 14 | import 'core-js/es6/string'; 15 | import 'core-js/es6/date'; 16 | import 'core-js/es6/array'; 17 | import 'core-js/es6/regexp'; 18 | import 'core-js/es6/map'; 19 | import 'core-js/es6/set'; 20 | import 'core-js/es6/weak-map'; 21 | import 'core-js/es6/weak-set'; 22 | import 'core-js/es6/typed'; 23 | import 'core-js/es6/reflect'; 24 | // see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709 25 | // import 'core-js/es6/promise'; 26 | 27 | import 'core-js/es7/reflect'; 28 | import 'zone.js/dist/zone'; 29 | import 'zone.js/dist/long-stack-trace-zone'; 30 | -------------------------------------------------------------------------------- /dist/app/polyfills.js: -------------------------------------------------------------------------------- 1 | // Polyfills 2 | "use strict"; 3 | require('ie-shim'); // Internet Explorer 9 support 4 | // import 'core-js/es6'; 5 | // Added parts of es6 which are necessary for your project or your browser support requirements. 6 | require('core-js/es6/symbol'); 7 | require('core-js/es6/object'); 8 | require('core-js/es6/function'); 9 | require('core-js/es6/parse-int'); 10 | require('core-js/es6/parse-float'); 11 | require('core-js/es6/number'); 12 | require('core-js/es6/math'); 13 | require('core-js/es6/string'); 14 | require('core-js/es6/date'); 15 | require('core-js/es6/array'); 16 | require('core-js/es6/regexp'); 17 | require('core-js/es6/map'); 18 | require('core-js/es6/set'); 19 | require('core-js/es6/weak-map'); 20 | require('core-js/es6/weak-set'); 21 | require('core-js/es6/typed'); 22 | require('core-js/es6/reflect'); 23 | // see issue https://github.com/AngularClass/angular2-webpack-starter/issues/709 24 | // import 'core-js/es6/promise'; 25 | require('core-js/es7/reflect'); 26 | require('zone.js/dist/zone'); 27 | require('zone.js/dist/long-stack-trace-zone'); 28 | //# sourceMappingURL=polyfills.js.map -------------------------------------------------------------------------------- /app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from "@angular/core"; 2 | import {BrowserModule} from "@angular/platform-browser"; 3 | import {HttpModule} from "@angular/http"; 4 | import {FormsModule} from "@angular/forms"; 5 | import {BookingStatusPipe} from "./booking-status.pipe"; 6 | import {FlightSearchComponent} from "./flightsearch.component"; 7 | import {MdCardModule} from "@angular2-material/card"; 8 | import {MdButtonModule} from "@angular2-material/button"; 9 | import {MdIconModule} from "@angular2-material/icon"; 10 | import {MdToolbarModule} from "@angular2-material/toolbar"; 11 | import {MdSidenavModule} from "@angular2-material/sidenav"; 12 | import {MdListModule} from "@angular2-material/list"; 13 | 14 | @NgModule({ 15 | imports: [ 16 | BrowserModule, 17 | HttpModule, 18 | FormsModule, 19 | MdButtonModule.forRoot(), 20 | MdCardModule.forRoot(), 21 | MdIconModule.forRoot(), 22 | MdListModule.forRoot(), 23 | MdSidenavModule.forRoot(), 24 | MdToolbarModule.forRoot() 25 | ], 26 | declarations: [ 27 | BookingStatusPipe, FlightSearchComponent 28 | ], 29 | providers: [ 30 | ], 31 | bootstrap: [ 32 | FlightSearchComponent 33 | ] 34 | }) 35 | export class AppModule { 36 | } 37 | 38 | -------------------------------------------------------------------------------- /webpack.sw.config.js: -------------------------------------------------------------------------------- 1 | var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin'); 2 | 3 | var webpack = require('webpack'); 4 | var path = require("path"); 5 | 6 | var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; 7 | 8 | module.exports = { 9 | debug: true, 10 | devtool: 'source-map', 11 | entry: { 12 | 'sw': './app/service-worker/service-worker' 13 | }, 14 | output: { 15 | path: __dirname + "/dist", 16 | filename: "[name].js", 17 | publicPath: "dist/" 18 | }, 19 | resolve: { 20 | extensions: ['', '.ts', '.js', '.jpg', '.jpeg', '.gif', '.png', '.css'] 21 | }, 22 | module: { 23 | loaders: [ 24 | { test: /\.(jpg|jpeg|gif|png)$/, loader:'file-loader?name=img/[path][name].[ext]' }, 25 | { test: /\.css$/, loader:'raw-loader' }, 26 | { test: /\.html$/, loaders: ['html-loader'] }, 27 | { test: /\.ts$/, loaders: ['awesome-typescript-loader'], exclude: /node_modules/} 28 | ] 29 | }, 30 | plugins: [ 31 | ], 32 | node: { 33 | __filename: true 34 | }, 35 | devServer: { 36 | inline:true, 37 | port: 8085, 38 | // historyApiFallback: true, 39 | watchOptions: { 40 | aggregateTimeout: 300, 41 | poll: 1000 42 | } 43 | } 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /webpack.app.config.js: -------------------------------------------------------------------------------- 1 | var ServiceWorkerWebpackPlugin = require('serviceworker-webpack-plugin'); 2 | 3 | var webpack = require('webpack'); 4 | var path = require("path"); 5 | 6 | var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; 7 | 8 | module.exports = { 9 | debug: true, 10 | devtool: 'source-map', 11 | entry: { 12 | 'vendor': ['./app/polyfills', './app/vendor'], 13 | 'app': './app/main', 14 | //'sw': './app/service-worker/service-worker' 15 | }, 16 | output: { 17 | path: __dirname + "/dist", 18 | filename: "[name].js", 19 | publicPath: "dist/" 20 | }, 21 | resolve: { 22 | extensions: ['', '.ts', '.js', '.jpg', '.jpeg', '.gif', '.png', '.css'] 23 | }, 24 | module: { 25 | loaders: [ 26 | { test: /\.(jpg|jpeg|gif|png)$/, loader:'file-loader?name=img/[path][name].[ext]' }, 27 | { test: /\.css$/, loader:'raw-loader' }, 28 | { test: /\.html$/, loaders: ['html-loader'] }, 29 | { test: /\.ts$/, loaders: ['awesome-typescript-loader'], exclude: /node_modules/} 30 | ] 31 | }, 32 | modulesDirectories: ['node_modules'], 33 | plugins: [ 34 | 35 | new ServiceWorkerWebpackPlugin({ 36 | entry: path.join(__dirname, 'sw-boot.js'), 37 | }), 38 | new CommonsChunkPlugin({ name: 'vendor' }) 39 | ], 40 | node: { 41 | __filename: true 42 | }, 43 | devServer: { 44 | inline:true, 45 | port: 8085, 46 | // historyApiFallback: true, 47 | watchOptions: { 48 | aggregateTimeout: 300, 49 | poll: 1000 50 | } 51 | } 52 | 53 | }; 54 | -------------------------------------------------------------------------------- /app/booking-status.pipe.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var BookingStatusPipe = (function () { 13 | function BookingStatusPipe() { 14 | } 15 | BookingStatusPipe.prototype.transform = function (value) { 16 | var args = []; 17 | for (var _i = 1; _i < arguments.length; _i++) { 18 | args[_i - 1] = arguments[_i]; 19 | } 20 | switch (value) { 21 | case 0: return "Booked (not checked in)"; 22 | case 1: return "Checked in"; 23 | case 2: return "Boarded"; 24 | } 25 | }; 26 | BookingStatusPipe = __decorate([ 27 | core_1.Pipe({ 28 | name: 'bookingStatus', 29 | pure: true 30 | }), 31 | __metadata('design:paramtypes', []) 32 | ], BookingStatusPipe); 33 | return BookingStatusPipe; 34 | }()); 35 | exports.BookingStatusPipe = BookingStatusPipe; 36 | //# sourceMappingURL=booking-status.pipe.js.map -------------------------------------------------------------------------------- /dist/app/booking-status.pipe.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var BookingStatusPipe = (function () { 13 | function BookingStatusPipe() { 14 | } 15 | BookingStatusPipe.prototype.transform = function (value) { 16 | var args = []; 17 | for (var _i = 1; _i < arguments.length; _i++) { 18 | args[_i - 1] = arguments[_i]; 19 | } 20 | switch (value) { 21 | case 0: return "Booked (not checked in)"; 22 | case 1: return "Checked in"; 23 | case 2: return "Boarded"; 24 | } 25 | }; 26 | BookingStatusPipe = __decorate([ 27 | core_1.Pipe({ 28 | name: 'bookingStatus', 29 | pure: true 30 | }), 31 | __metadata('design:paramtypes', []) 32 | ], BookingStatusPipe); 33 | return BookingStatusPipe; 34 | }()); 35 | exports.BookingStatusPipe = BookingStatusPipe; 36 | //# sourceMappingURL=booking-status.pipe.js.map -------------------------------------------------------------------------------- /app/flightsearch.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | refresh 6 | Aktualisieren 7 | Daten mit dem Server abgleichen 8 | 9 | 10 | 11 | 12 | 13 | menu 14 | 15 | Your Flights 16 | 17 | 18 | 19 | 20 | {{b.flug.abflugort}} - {{b.flug.zielort}} 21 | 22 | Flight-No.: {{b.flug.id}} 23 | {{b.flug.datum.substr(0,10)}} 24 | {{b.buchungsStatus | bookingStatus}} 25 | 26 | 27 | Check in 28 | Check out 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 61 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Progressive Web App Demo 4 | 5 | 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 | 34 | 35 | 40 | 41 | 42 | 43 | 44 | 45 | Loading... 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /dist/app/service-worker/service-worker.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"service-worker.js","sourceRoot":"","sources":["../../../app/service-worker/service-worker.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #Progressive Web Apps (PWA) with Angular 2 Show Case 2 | 3 | This sample shows: 4 | 5 | - PWA with Angular 2 6 | - Bundling Service Worker and App with webpack 7 | - Caching with Service Worker and the Service Worker Toolbox 8 | - Storing data with PouchDB (which uses IndexedDb, WebDb or LocalStorage) 9 | - AppShell Pattern with Caching to quickly provide value to the user 10 | - Web App Manifest and a Fallback using Meta-Tags to install the App to the Home Screen 11 | - Background Synchronisation with Service Workers 12 | - Push Notifications with Service Worksers 13 | 14 | ## Prerequisites 15 | 16 | - NodeJS (nodejs.org) 17 | 18 | ## Installation 19 | 20 | ``` 21 | npm install 22 | ``` 23 | 24 | ## Bundling 25 | 26 | ``` 27 | npm run webpack 28 | ``` 29 | 30 | ## Starting 31 | 32 | After Bundling run: 33 | 34 | ``` 35 | npm run http-server 36 | ``` 37 | 38 | This starts a http-server at localhost:8080 39 | 40 | ## Trying out Sample 41 | 42 | 1. Go to http://localhost:8080 43 | 2. Stop http-server and refresh browser 44 | 3. Web-Site should still load due to its service-worker based offline capabilities 45 | 4. Disconnect from the web 46 | 5. Alter the state of some bookings in the browser (check in/ check out). 47 | 6. Open F12-Dev-Tools 48 | 7. Reconnect to the web 49 | 8. Some time after reconnecting, you should see that the app is syncing the booking states with the server 50 | 9. Start http-server again (``npm run http-server``) 51 | 10. In chrome, go to F12-Dev-Tools (F12) | Application | Service Worker 52 | 11. Press 'Push' to simulate a push-message 53 | 12. You should see a push-message 54 | 55 | ## Sending push messages via HTTP 56 | 57 | 1. Start app and go to F12-Dev-Tools 58 | 2. The console should display a "push endpoint" 59 | 3. Send the following HTTP message to this push-endpoint to notify chrome. The auth key can be created within the google api console. See [this post](https://developers.google.com/web/updates/2015/03/push-notifications-on-the-open-web) for [further infos](https://developers.google.com/web/updates/2015/03/push-notifications-on-the-open-web). 60 | 61 | ``` 62 | POST https://android.googleapis.com/gcm/send/dt1JdJT[...] 63 | Content-Length: 0 64 | Authorization: key=AIzaSyDGFJo7_qMFJRa5tVjHAfyPWjFEQBOe47o 65 | TTL: 10 66 | ``` 67 | 68 | *Note:* To notify firefox, you don't need an auth key. The rest of the message is the same. 69 | 70 | ## Credits 71 | 72 | - Google Web Starter Sit, https://github.com/google/web-starter-kit 73 | - sw-toolbox, https://github.com/GoogleChrome/sw-toolbox 74 | - PouchDB, https://pouchdb.com/ 75 | -------------------------------------------------------------------------------- /dist/app/app.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require("@angular/core"); 12 | var platform_browser_1 = require("@angular/platform-browser"); 13 | var http_1 = require("@angular/http"); 14 | var forms_1 = require("@angular/forms"); 15 | var booking_status_pipe_1 = require("./booking-status.pipe"); 16 | var flightsearch_component_1 = require("./flightsearch.component"); 17 | var card_1 = require("@angular2-material/card"); 18 | var button_1 = require("@angular2-material/button"); 19 | var icon_1 = require("@angular2-material/icon"); 20 | var toolbar_1 = require("@angular2-material/toolbar"); 21 | var sidenav_1 = require("@angular2-material/sidenav"); 22 | var list_1 = require("@angular2-material/list"); 23 | var AppModule = (function () { 24 | function AppModule() { 25 | } 26 | AppModule = __decorate([ 27 | core_1.NgModule({ 28 | imports: [ 29 | platform_browser_1.BrowserModule, 30 | http_1.HttpModule, 31 | forms_1.FormsModule, 32 | button_1.MdButtonModule.forRoot(), 33 | card_1.MdCardModule.forRoot(), 34 | icon_1.MdIconModule.forRoot(), 35 | list_1.MdListModule.forRoot(), 36 | sidenav_1.MdSidenavModule.forRoot(), 37 | toolbar_1.MdToolbarModule.forRoot() 38 | ], 39 | declarations: [ 40 | booking_status_pipe_1.BookingStatusPipe, flightsearch_component_1.FlightSearchComponent 41 | ], 42 | providers: [], 43 | bootstrap: [ 44 | flightsearch_component_1.FlightSearchComponent 45 | ] 46 | }), 47 | __metadata('design:paramtypes', []) 48 | ], AppModule); 49 | return AppModule; 50 | }()); 51 | exports.AppModule = AppModule; 52 | //# sourceMappingURL=app.module.js.map -------------------------------------------------------------------------------- /app/booking.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking.service.js","sourceRoot":"","sources":["booking.service.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/app/booking.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"booking.service.js","sourceRoot":"","sources":["../../app/booking.service.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/app/flightsearch.component.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"flightsearch.component.js","sourceRoot":"","sources":["../../app/flightsearch.component.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/app/service-worker/service-worker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //import { ReflectiveInjector } from '@angular/core'; 3 | // Polyfills for Service-Worker 4 | require('core-js/es6/reflect'); 5 | require('core-js/es7/reflect'); 6 | // Imports 7 | var booking_service_1 = require('../booking.service'); 8 | var toolbox = require('sw-toolbox'); 9 | console.debug("starting service-worker"); 10 | /* 11 | const PROVIDERS = [ 12 | BookingService 13 | ]; 14 | 15 | let injector = ReflectiveInjector.resolveAndCreate(PROVIDERS); 16 | let bs:BookingService = injector.get(BookingService); 17 | */ 18 | var bs = new booking_service_1.BookingService(); 19 | var context = self; 20 | context.addEventListener('sync', function (event) { 21 | console.debug("Service Worker: sync, tag=" + event.tag); 22 | if (event.tag == 'upload') { 23 | event.waitUntil(bs.upload().then(function (_) { return console.debug('background-upload finished'); })); 24 | } 25 | }); 26 | context.addEventListener('push', function (event) { 27 | console.log('Push message', event); 28 | var title = 'Your flight is delayed'; 29 | /* 30 | event.waitUntil(bs.sync().then(p => context.registration.showNotification(title, { 31 | body: 'Your flight is delayed', 32 | icon: '/images/touch/icon-128x128.png', 33 | tag: 'my-tag' 34 | }))); 35 | */ 36 | event.waitUntil(context.registration.showNotification(title, { 37 | body: 'Your flight is delayed', 38 | icon: '/images/touch/icon-128x128.png', 39 | tag: 'my-tag' 40 | })); 41 | }); 42 | self.addEventListener('notificationclick', function (event) { 43 | console.log('Notification click: tag ', event.notification.tag); 44 | event.notification.close(); 45 | var url = 'http://127.0.0.1:8080'; 46 | event.waitUntil(clients.matchAll({ 47 | type: 'window' 48 | }) 49 | .then(function (windowClients) { 50 | console.debug("win-count: " + windowClients.length); 51 | for (var i = 0; i < windowClients.length; i++) { 52 | var client = windowClients[i]; 53 | console.debug(" > client-url: " + client.url + ", url: " + url); 54 | var clientUrl = client.url; 55 | if (clientUrl.startsWith(url) && 'focus' in client) { 56 | return client.focus(); 57 | } 58 | } 59 | if (clients.openWindow) { 60 | return clients.openWindow(url); 61 | } 62 | })); 63 | }); 64 | var context = self; 65 | toolbox.options.debug = true; 66 | toolbox.precache([ 67 | '/', 68 | '/index.html', 69 | '/dist/app.js', 70 | '/dist/vendor.js', 71 | '/dist/sw.js' 72 | ]); 73 | toolbox.router.get('/(.*)', toolbox.networkOnly, { origin: 'http://www.angular.at' }); 74 | toolbox.router.default = toolbox.cacheFirst; 75 | //# sourceMappingURL=service-worker.js.map -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-seed", 3 | "version": "1.0.0", 4 | "description": "A simple starter Angular2 project", 5 | "scripts": { 6 | "typings-install": "typings install", 7 | "postinstall": "npm run typings-install", 8 | "build": "webpack --inline --colors --progress --display-error-details --display-cached", 9 | "webpack": "webpack", 10 | "watch": "npm run build -- --watch", 11 | "server": "webpack-dev-server", 12 | "start": "npm run server", 13 | "tsc": "tsc", 14 | "http-server": "http-server" 15 | }, 16 | "contributors": [ 17 | "Rob Wormald ", 18 | "PatrickJS " 19 | ], 20 | "license": "MIT", 21 | "devDependencies": { 22 | "angular2-template-loader": "^0.4.0", 23 | "awesome-typescript-loader": "^1.1.1", 24 | "css-loader": "^0.23.1", 25 | "html-loader": "^0.4.4", 26 | "http-server": "^0.9.0", 27 | "raw-loader": "^0.5.1", 28 | "serviceworker-loader": "^0.1.0", 29 | "serviceworker-webpack-plugin": "^0.1.5", 30 | "to-string-loader": "^1.1.4", 31 | "typescript": "^2.0.2", 32 | "typings": "~1.0.3", 33 | "webpack": "^1.12.9", 34 | "webpack-dev-server": "^1.14.0", 35 | "webpack-merge": "^0.8.4" 36 | }, 37 | "dependencies": { 38 | "@angular/common": "2.0.0", 39 | "@angular/compiler": "2.0.0", 40 | "@angular/core": "2.0.0", 41 | "@angular/forms": "2.0.0", 42 | "@angular/http": "2.0.0", 43 | "@angular/platform-browser": "2.0.0", 44 | "@angular/platform-browser-dynamic": "2.0.0", 45 | "@angular/router": "3.0.0", 46 | "@angular/upgrade": "2.0.0", 47 | "@angular2-material/button": "^2.0.0-alpha.8-2", 48 | "@angular2-material/card": "^2.0.0-alpha.8-2", 49 | "@angular2-material/core": "^2.0.0-alpha.8-2", 50 | "@angular2-material/icon": "^2.0.0-alpha.8-2", 51 | "@angular2-material/list": "^2.0.0-alpha.8-2", 52 | "@angular2-material/sidenav": "^2.0.0-alpha.8-2", 53 | "@angular2-material/toolbar": "^2.0.0-alpha.8-2", 54 | "angular2-in-memory-web-api": "0.0.20", 55 | "bootstrap": "^3.3.6", 56 | "core-js": "^2.4.1", 57 | "hammerjs": "^2.0.8", 58 | "ie-shim": "^0.1.0", 59 | "moment": "^2.15.1", 60 | "pouchdb": "^5.3.2", 61 | "reflect-metadata": "^0.1.3", 62 | "rxjs": "5.0.0-beta.12", 63 | "sw-toolbox": "^3.2.1", 64 | "systemjs": "0.19.27", 65 | "zone.js": "^0.6.23" 66 | }, 67 | "keywords": [ 68 | "Angular2", 69 | "angular2-seed", 70 | "official angular 2 seed", 71 | "official angular2 seed" 72 | ], 73 | "repository": { 74 | "type": "git", 75 | "url": "git+https://github.com/angular/angular2-seed.git" 76 | }, 77 | "bugs": { 78 | "url": "https://github.com/angular/angular2-seed/issues" 79 | }, 80 | "homepage": "https://github.com/angular/angular2-seed#readme" 81 | } 82 | -------------------------------------------------------------------------------- /app/service-worker/service-worker.ts: -------------------------------------------------------------------------------- 1 | //import { ReflectiveInjector } from '@angular/core'; 2 | // Polyfills for Service-Worker 3 | import 'core-js/es6/reflect'; 4 | import 'core-js/es7/reflect'; 5 | 6 | // Imports 7 | import { BookingService } from '../booking.service'; 8 | var toolbox = require('sw-toolbox'); 9 | 10 | console.debug("starting service-worker"); 11 | 12 | /* 13 | const PROVIDERS = [ 14 | BookingService 15 | ]; 16 | 17 | let injector = ReflectiveInjector.resolveAndCreate(PROVIDERS); 18 | let bs:BookingService = injector.get(BookingService); 19 | */ 20 | 21 | let bs = new BookingService(); 22 | 23 | var context:any = self; 24 | 25 | context.addEventListener('sync', function(event) { 26 | console.debug("Service Worker: sync, tag=" + event.tag); 27 | if (event.tag == 'upload') { 28 | event.waitUntil(bs.upload().then(_ => console.debug('background-upload finished'))); 29 | } 30 | }); 31 | 32 | context.addEventListener('push', function(event: any) { 33 | console.log('Push message', event); 34 | var title = 'Your flight is delayed'; 35 | /* 36 | event.waitUntil(bs.sync().then(p => context.registration.showNotification(title, { 37 | body: 'Your flight is delayed', 38 | icon: '/images/touch/icon-128x128.png', 39 | tag: 'my-tag' 40 | }))); 41 | */ 42 | event.waitUntil(context.registration.showNotification(title, { 43 | body: 'Your flight is delayed', 44 | icon: '/images/touch/icon-128x128.png', 45 | tag: 'my-tag' 46 | })); 47 | 48 | }); 49 | 50 | declare var clients: any; 51 | 52 | self.addEventListener('notificationclick', function(event: any) { 53 | console.log('Notification click: tag ', event.notification.tag); 54 | event.notification.close(); 55 | var url = 'http://127.0.0.1:8080'; 56 | event.waitUntil( 57 | clients.matchAll({ 58 | type: 'window' 59 | }) 60 | .then(function(windowClients) { 61 | console.debug("win-count: " + windowClients.length); 62 | for (var i = 0; i < windowClients.length; i++) { 63 | var client = windowClients[i]; 64 | console.debug(" > client-url: " + client.url + ", url: " + url); 65 | let clientUrl: string = client.url; 66 | if ( clientUrl.startsWith(url) && 'focus' in client) { 67 | return client.focus(); 68 | } 69 | } 70 | if (clients.openWindow) { 71 | return clients.openWindow(url); 72 | } 73 | }) 74 | ); 75 | }); 76 | 77 | 78 | var context: any = self; 79 | 80 | toolbox.options.debug = true; 81 | 82 | toolbox.precache([ 83 | '/', 84 | '/index.html', 85 | '/dist/app.js', 86 | '/dist/vendor.js', 87 | '/dist/sw.js' 88 | ]); 89 | 90 | toolbox.router.get('/(.*)', toolbox.networkOnly, {origin: 'http://www.angular.at'}); 91 | toolbox.router.default = toolbox.cacheFirst; 92 | -------------------------------------------------------------------------------- /app/booking.service.ts: -------------------------------------------------------------------------------- 1 | import {Booking} from './booking'; 2 | import {BookingsDoc} from './bookings-doc'; 3 | import {Injectable } from '@angular/core'; 4 | 5 | 6 | var PouchDB = require("pouchdb"); 7 | 8 | 9 | const PASSAGIER_ID = "3"; 10 | const URL = "http://www.angular.at/api/buchung"; 11 | 12 | const db = new PouchDB("bookingsDb"); 13 | 14 | 15 | @Injectable() 16 | export class BookingService { 17 | 18 | 19 | public sync(): Promise { 20 | var that = this; 21 | return this.upload().then(() => { 22 | return that.download(); 23 | }); 24 | } 25 | 26 | public download(): Promise { 27 | 28 | return this.fetchOnline() 29 | .then(bookings => { 30 | return this.save(bookings).then(() => bookings); 31 | }); 32 | } 33 | 34 | public upload(): Promise { 35 | 36 | let promises = []; 37 | 38 | return this.fetchLocal().then( (bookings) => { 39 | 40 | if (!bookings) return Promise.resolve(null); 41 | 42 | let method = "PUT"; 43 | let mode = "CORS"; 44 | let headers = new Headers(); 45 | headers.set('Content-Type', 'text/json'); 46 | console.debug('bookings', bookings); 47 | var promises = bookings.bookings.filter(b => b.isDirty) 48 | .map(b => fetch(URL, {method, headers, /*mode,*/ body: JSON.stringify(b)})); 49 | 50 | if (!promises) return Promise.resolve(null); 51 | 52 | return Promise.all(promises); 53 | 54 | }); 55 | 56 | } 57 | 58 | public fetchOnline(): Promise { 59 | 60 | // let search = new URLSearchParams(); 61 | // search.set('passagierId', PASSAGIER_ID); 62 | 63 | // let headers = new Headers(); 64 | // headers.set('Accept', 'text/json'); 65 | 66 | let url = URL + "?passagierId=" + encodeURIComponent(PASSAGIER_ID); 67 | 68 | let headers = new Headers(); 69 | headers.set('Accept', 'text/json'); 70 | 71 | let method = "GET"; 72 | let mode = "CORS"; 73 | 74 | return fetch(url, {method, headers/*, mode*/ }) 75 | .then(r => r.json()); 76 | 77 | } 78 | 79 | public fetchLocal(): Promise { 80 | 81 | return db.get('bookings').catch(err => { 82 | if (err.status == 404) return null; 83 | return Promise.reject(err); 84 | }); 85 | } 86 | 87 | public save(bookings: Array): Promise { 88 | 89 | 90 | return this.fetchLocal().then( (entity: BookingsDoc) => { 91 | 92 | if (entity) { 93 | entity.bookings = bookings; 94 | } 95 | else { 96 | entity = { 97 | _id: "bookings", 98 | _rev: null, 99 | bookings: bookings 100 | } 101 | } 102 | return db.put(entity); 103 | }); 104 | 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/flightsearch.component.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"flightsearch.component.js","sourceRoot":"","sources":["flightsearch.component.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /app/flightsearch.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; 2 | import { Http, URLSearchParams, Headers} from '@angular/http'; 3 | import { Booking} from './booking'; 4 | import { BookingsDoc} from './bookings-doc'; 5 | import { BookingService} from './booking.service'; 6 | import { BookingStatusPipe} from './booking-status.pipe'; 7 | 8 | // 'node_modules/bootstrap/dist/css/bootstrap.css' 9 | 10 | @Component({ 11 | selector: 'flight-search', // 12 | template: require('./flightsearch.component.html'), 13 | styles: [require('./flightsearch.component.css')], 14 | providers: [BookingService] 15 | 16 | }) 17 | export class FlightSearchComponent implements OnInit { 18 | 19 | public bookings: Array = []; 20 | 21 | constructor( 22 | private changeDetectionRef: ChangeDetectorRef, 23 | private bookingervice: BookingService) { 24 | } 25 | 26 | ngOnInit() { 27 | this.setupPushNotifications(); 28 | this.syncData(); 29 | } 30 | 31 | syncData() { 32 | let hasPendingRequest = true; 33 | let that = this; 34 | 35 | this.bookingervice.sync().then((b: Booking[]) => { 36 | hasPendingRequest = false; 37 | that.bookings = b; 38 | that.changeDetectionRef.detectChanges(); 39 | }); 40 | 41 | this.bookingervice.fetchLocal().then((b: BookingsDoc) => { 42 | if (!hasPendingRequest) return; 43 | if (!b) return; 44 | that.bookings = b.bookings; 45 | that.changeDetectionRef.detectChanges(); 46 | }); 47 | 48 | } 49 | 50 | requestUpload() { 51 | 52 | let nav:any = navigator; 53 | 54 | if ('serviceWorker' in nav && 'SyncManager' in window) { 55 | nav.serviceWorker 56 | .ready 57 | .then(reg => { 58 | return reg.sync.register('upload'); 59 | }) 60 | .catch(_ => { 61 | return this.bookingervice.upload(); 62 | }); 63 | } 64 | else { 65 | this.bookingervice.upload(); 66 | } 67 | 68 | } 69 | 70 | setupPushNotifications() { 71 | 72 | let nav:any = navigator; 73 | 74 | if ('serviceWorker' in navigator) { 75 | console.log('Service Worker is supported'); 76 | 77 | nav.serviceWorker.ready.then(function(reg) { 78 | 79 | reg.pushManager.subscribe({ 80 | userVisibleOnly: true 81 | }).then(function(sub) { 82 | console.log('push endpoint:', sub.endpoint); 83 | }).catch(function(err) { 84 | console.error(err); 85 | }); 86 | }).catch(function(error) { 87 | console.log('Error:', error); 88 | }); 89 | } 90 | 91 | } 92 | 93 | checkin(b: Booking) { 94 | b.buchungsStatus = 1; 95 | b.isDirty = true; 96 | this.bookingervice.save(this.bookings); 97 | this.requestUpload(); 98 | } 99 | 100 | boarding(b: Booking) { 101 | b.buchungsStatus = 2; 102 | b.isDirty = true; 103 | this.bookingervice.save(this.bookings); 104 | this.requestUpload(); 105 | } 106 | 107 | booked(b: Booking) { 108 | b.buchungsStatus = 0; 109 | b.isDirty = true; 110 | this.bookingervice.save(this.bookings); 111 | this.requestUpload(); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /app/booking.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var PASSAGIER_ID = "3"; 13 | //const URL = "/data/bookings.json"; 14 | var URL = "http://www.angular.at/api/buchung"; 15 | var db = new PouchDB("bookingsDb"); 16 | var BookingService = (function () { 17 | function BookingService() { 18 | } 19 | BookingService.prototype.sync = function () { 20 | var that = this; 21 | return this.upload().then(function () { 22 | return that.download(); 23 | }); 24 | }; 25 | BookingService.prototype.download = function () { 26 | var _this = this; 27 | return this.fetchOnline() 28 | .then(function (bookings) { 29 | return _this.save(bookings).then(function () { return bookings; }); 30 | }); 31 | }; 32 | BookingService.prototype.upload = function () { 33 | var promises = []; 34 | return this.fetchLocal().then(function (bookings) { 35 | if (!bookings) 36 | return Promise.resolve(null); 37 | var method = "PUT"; 38 | var mode = "CORS"; 39 | var headers = new Headers(); 40 | headers.set('Content-Type', 'text/json'); 41 | console.debug('bookings', bookings); 42 | var promises = bookings.bookings.filter(function (b) { return b.isDirty; }) 43 | .map(function (b) { return fetch(URL, { method: method, headers: headers, body: JSON.stringify(b) }); }); 44 | if (!promises) 45 | return Promise.resolve(null); 46 | return Promise.all(promises); 47 | }); 48 | }; 49 | BookingService.prototype.fetchOnline = function () { 50 | // let search = new URLSearchParams(); 51 | // search.set('passagierId', PASSAGIER_ID); 52 | // let headers = new Headers(); 53 | // headers.set('Accept', 'text/json'); 54 | var url = URL + "?passagierId=" + encodeURIComponent(PASSAGIER_ID); 55 | var headers = new Headers(); 56 | headers.set('Accept', 'text/json'); 57 | var method = "GET"; 58 | var mode = "CORS"; 59 | return fetch(url, { method: method, headers: headers /*, mode*/ }) 60 | .then(function (r) { return r.json(); }); 61 | }; 62 | BookingService.prototype.fetchLocal = function () { 63 | return db.get('bookings').catch(function (err) { 64 | if (err.status == 404) 65 | return null; 66 | return Promise.reject(err); 67 | }); 68 | }; 69 | BookingService.prototype.save = function (bookings) { 70 | return this.fetchLocal().then(function (entity) { 71 | if (entity) { 72 | entity.bookings = bookings; 73 | } 74 | else { 75 | entity = { 76 | _id: "bookings", 77 | _rev: null, 78 | bookings: bookings 79 | }; 80 | } 81 | return db.put(entity); 82 | }); 83 | }; 84 | BookingService = __decorate([ 85 | core_1.Injectable(), 86 | __metadata('design:paramtypes', []) 87 | ], BookingService); 88 | return BookingService; 89 | }()); 90 | exports.BookingService = BookingService; 91 | //# sourceMappingURL=booking.service.js.map -------------------------------------------------------------------------------- /dist/app/booking.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var PouchDB = require("pouchdb"); 13 | var PASSAGIER_ID = "3"; 14 | var URL = "http://www.angular.at/api/buchung"; 15 | var db = new PouchDB("bookingsDb"); 16 | var BookingService = (function () { 17 | function BookingService() { 18 | } 19 | BookingService.prototype.sync = function () { 20 | var that = this; 21 | return this.upload().then(function () { 22 | return that.download(); 23 | }); 24 | }; 25 | BookingService.prototype.download = function () { 26 | var _this = this; 27 | return this.fetchOnline() 28 | .then(function (bookings) { 29 | return _this.save(bookings).then(function () { return bookings; }); 30 | }); 31 | }; 32 | BookingService.prototype.upload = function () { 33 | var promises = []; 34 | return this.fetchLocal().then(function (bookings) { 35 | if (!bookings) 36 | return Promise.resolve(null); 37 | var method = "PUT"; 38 | var mode = "CORS"; 39 | var headers = new Headers(); 40 | headers.set('Content-Type', 'text/json'); 41 | console.debug('bookings', bookings); 42 | var promises = bookings.bookings.filter(function (b) { return b.isDirty; }) 43 | .map(function (b) { return fetch(URL, { method: method, headers: headers, body: JSON.stringify(b) }); }); 44 | if (!promises) 45 | return Promise.resolve(null); 46 | return Promise.all(promises); 47 | }); 48 | }; 49 | BookingService.prototype.fetchOnline = function () { 50 | // let search = new URLSearchParams(); 51 | // search.set('passagierId', PASSAGIER_ID); 52 | // let headers = new Headers(); 53 | // headers.set('Accept', 'text/json'); 54 | var url = URL + "?passagierId=" + encodeURIComponent(PASSAGIER_ID); 55 | var headers = new Headers(); 56 | headers.set('Accept', 'text/json'); 57 | var method = "GET"; 58 | var mode = "CORS"; 59 | return fetch(url, { method: method, headers: headers /*, mode*/ }) 60 | .then(function (r) { return r.json(); }); 61 | }; 62 | BookingService.prototype.fetchLocal = function () { 63 | return db.get('bookings').catch(function (err) { 64 | if (err.status == 404) 65 | return null; 66 | return Promise.reject(err); 67 | }); 68 | }; 69 | BookingService.prototype.save = function (bookings) { 70 | return this.fetchLocal().then(function (entity) { 71 | if (entity) { 72 | entity.bookings = bookings; 73 | } 74 | else { 75 | entity = { 76 | _id: "bookings", 77 | _rev: null, 78 | bookings: bookings 79 | }; 80 | } 81 | return db.put(entity); 82 | }); 83 | }; 84 | BookingService = __decorate([ 85 | core_1.Injectable(), 86 | __metadata('design:paramtypes', []) 87 | ], BookingService); 88 | return BookingService; 89 | }()); 90 | exports.BookingService = BookingService; 91 | //# sourceMappingURL=booking.service.js.map -------------------------------------------------------------------------------- /dist/app/flightsearch.component.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var booking_service_1 = require('./booking.service'); 13 | // 'node_modules/bootstrap/dist/css/bootstrap.css' 14 | var FlightSearchComponent = (function () { 15 | function FlightSearchComponent(changeDetectionRef, bookingervice) { 16 | this.changeDetectionRef = changeDetectionRef; 17 | this.bookingervice = bookingervice; 18 | this.bookings = []; 19 | } 20 | FlightSearchComponent.prototype.ngOnInit = function () { 21 | this.setupPushNotifications(); 22 | this.syncData(); 23 | }; 24 | FlightSearchComponent.prototype.syncData = function () { 25 | var hasPendingRequest = true; 26 | var that = this; 27 | this.bookingervice.sync().then(function (b) { 28 | hasPendingRequest = false; 29 | that.bookings = b; 30 | that.changeDetectionRef.detectChanges(); 31 | }); 32 | this.bookingervice.fetchLocal().then(function (b) { 33 | if (!hasPendingRequest) 34 | return; 35 | if (!b) 36 | return; 37 | that.bookings = b.bookings; 38 | that.changeDetectionRef.detectChanges(); 39 | }); 40 | }; 41 | FlightSearchComponent.prototype.requestUpload = function () { 42 | var _this = this; 43 | var nav = navigator; 44 | if ('serviceWorker' in nav && 'SyncManager' in window) { 45 | nav.serviceWorker 46 | .ready 47 | .then(function (reg) { 48 | return reg.sync.register('upload'); 49 | }) 50 | .catch(function (_) { 51 | return _this.bookingervice.upload(); 52 | }); 53 | } 54 | else { 55 | this.bookingervice.upload(); 56 | } 57 | }; 58 | FlightSearchComponent.prototype.setupPushNotifications = function () { 59 | var nav = navigator; 60 | if ('serviceWorker' in navigator) { 61 | console.log('Service Worker is supported'); 62 | nav.serviceWorker.ready.then(function (reg) { 63 | reg.pushManager.subscribe({ 64 | userVisibleOnly: true 65 | }).then(function (sub) { 66 | console.log('push endpoint:', sub.endpoint); 67 | }).catch(function (err) { 68 | console.error(err); 69 | }); 70 | }).catch(function (error) { 71 | console.log('Error:', error); 72 | }); 73 | } 74 | }; 75 | FlightSearchComponent.prototype.checkin = function (b) { 76 | b.buchungsStatus = 1; 77 | b.isDirty = true; 78 | this.bookingervice.save(this.bookings); 79 | this.requestUpload(); 80 | }; 81 | FlightSearchComponent.prototype.boarding = function (b) { 82 | b.buchungsStatus = 2; 83 | b.isDirty = true; 84 | this.bookingervice.save(this.bookings); 85 | this.requestUpload(); 86 | }; 87 | FlightSearchComponent.prototype.booked = function (b) { 88 | b.buchungsStatus = 0; 89 | b.isDirty = true; 90 | this.bookingervice.save(this.bookings); 91 | this.requestUpload(); 92 | }; 93 | FlightSearchComponent = __decorate([ 94 | core_1.Component({ 95 | selector: 'flight-search', 96 | template: require('./flightsearch.component.html'), 97 | styles: [require('./flightsearch.component.css')], 98 | providers: [booking_service_1.BookingService] 99 | }), 100 | __metadata('design:paramtypes', [core_1.ChangeDetectorRef, booking_service_1.BookingService]) 101 | ], FlightSearchComponent); 102 | return FlightSearchComponent; 103 | }()); 104 | exports.FlightSearchComponent = FlightSearchComponent; 105 | //# sourceMappingURL=flightsearch.component.js.map -------------------------------------------------------------------------------- /data/buchungen.json: -------------------------------------------------------------------------------- 1 | [{"flugID":1,"passagierID":1,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"A","flugSet":null,"id":1,"vorname":"Max","name":"Muster","geburtsdatum":"1970-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":2,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"B","flugSet":null,"id":2,"vorname":"Susi","name":"Sorglos","geburtsdatum":"1971-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":3,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"C","flugSet":null,"id":3,"vorname":"Anna","name":"Muster","geburtsdatum":"1972-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":4,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"A","flugSet":null,"id":4,"vorname":"Rainer","name":"Zufall","geburtsdatum":"1973-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":1,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"A","flugSet":null,"id":1,"vorname":"Max","name":"Muster","geburtsdatum":"1970-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":2,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"B","flugSet":null,"id":2,"vorname":"Susi","name":"Sorglos","geburtsdatum":"1971-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":3,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"C","flugSet":null,"id":3,"vorname":"Anna","name":"Muster","geburtsdatum":"1972-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":4,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"A","flugSet":null,"id":4,"vorname":"Rainer","name":"Zufall","geburtsdatum":"1973-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":1,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"A","flugSet":null,"id":1,"vorname":"Max","name":"Muster","geburtsdatum":"1970-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":2,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"B","flugSet":null,"id":2,"vorname":"Susi","name":"Sorglos","geburtsdatum":"1971-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":3,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"C","flugSet":null,"id":3,"vorname":"Anna","name":"Muster","geburtsdatum":"1972-01-01T00:00:00"},"buchungsStatus":2},{"flugID":1,"passagierID":4,"flug":{"id":1,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T13:13:08.5127969+00:00","plaetze":200,"freiePlaetze":190},"passagier":{"passagierStatus":"A","flugSet":null,"id":4,"vorname":"Rainer","name":"Zufall","geburtsdatum":"1973-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":1,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"A","flugSet":null,"id":1,"vorname":"Max","name":"Muster","geburtsdatum":"1970-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":2,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"B","flugSet":null,"id":2,"vorname":"Susi","name":"Sorglos","geburtsdatum":"1971-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":3,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"C","flugSet":null,"id":3,"vorname":"Anna","name":"Muster","geburtsdatum":"1972-01-01T00:00:00"},"buchungsStatus":2},{"flugID":2,"passagierID":4,"flug":{"id":2,"abflugort":"Graz","zielort":"Hamburg","datum":"2016-05-22T15:13:08.5127969+00:00","plaetze":200,"freiePlaetze":68},"passagier":{"passagierStatus":"A","flugSet":null,"id":4,"vorname":"Rainer","name":"Zufall","geburtsdatum":"1973-01-01T00:00:00"},"buchungsStatus":2}] 2 | -------------------------------------------------------------------------------- /app/flightsearch.component.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var core_1 = require('@angular/core'); 12 | var booking_service_1 = require('./booking.service'); 13 | var booking_status_pipe_1 = require('./booking-status.pipe'); 14 | var card_1 = require('@angular2-material/card'); 15 | var button_1 = require('@angular2-material/button'); 16 | var toolbar_1 = require('@angular2-material/toolbar'); 17 | var sidenav_1 = require('@angular2-material/sidenav'); 18 | var list_1 = require('@angular2-material/list'); 19 | var icon_1 = require('@angular2-material/icon'); 20 | var APP_MD_DIRECTIVES = [ 21 | card_1.MD_CARD_DIRECTIVES, 22 | button_1.MD_BUTTON_DIRECTIVES, 23 | toolbar_1.MD_TOOLBAR_DIRECTIVES, 24 | sidenav_1.MD_SIDENAV_DIRECTIVES, 25 | list_1.MD_LIST_DIRECTIVES, 26 | icon_1.MD_ICON_DIRECTIVES 27 | ]; 28 | var FlightSearchComponent = (function () { 29 | function FlightSearchComponent(changeDetectionRef, bookingervice) { 30 | this.changeDetectionRef = changeDetectionRef; 31 | this.bookingervice = bookingervice; 32 | this.bookings = []; 33 | } 34 | FlightSearchComponent.prototype.ngOnInit = function () { 35 | this.setupPushNotifications(); 36 | this.syncData(); 37 | }; 38 | FlightSearchComponent.prototype.syncData = function () { 39 | var hasPendingRequest = true; 40 | var that = this; 41 | this.bookingervice.sync().then(function (b) { 42 | hasPendingRequest = false; 43 | that.bookings = b; 44 | that.changeDetectionRef.detectChanges(); 45 | }); 46 | this.bookingervice.fetchLocal().then(function (b) { 47 | if (!hasPendingRequest) 48 | return; 49 | if (!b) 50 | return; 51 | that.bookings = b.bookings; 52 | that.changeDetectionRef.detectChanges(); 53 | }); 54 | }; 55 | FlightSearchComponent.prototype.requestUpload = function () { 56 | var _this = this; 57 | var nav = navigator; 58 | if ('serviceWorker' in nav && 'SyncManager' in window) { 59 | nav.serviceWorker 60 | .ready 61 | .then(function (reg) { 62 | return reg.sync.register('upload'); 63 | }) 64 | .catch(function (_) { 65 | return _this.bookingervice.upload(); 66 | }); 67 | } 68 | else { 69 | this.bookingervice.upload(); 70 | } 71 | }; 72 | FlightSearchComponent.prototype.setupPushNotifications = function () { 73 | var nav = navigator; 74 | if ('serviceWorker' in navigator) { 75 | console.log('Service Worker is supported'); 76 | nav.serviceWorker.ready.then(function (reg) { 77 | reg.pushManager.subscribe({ 78 | userVisibleOnly: true 79 | }).then(function (sub) { 80 | console.log('endpoint:', sub.endpoint); 81 | }).catch(function (err) { 82 | console.error(err); 83 | }); 84 | }).catch(function (error) { 85 | console.log('Error:', error); 86 | }); 87 | } 88 | }; 89 | FlightSearchComponent.prototype.checkin = function (b) { 90 | b.buchungsStatus = 1; 91 | b.isDirty = true; 92 | this.bookingervice.save(this.bookings); 93 | this.requestUpload(); 94 | }; 95 | FlightSearchComponent.prototype.boarding = function (b) { 96 | b.buchungsStatus = 2; 97 | b.isDirty = true; 98 | this.bookingervice.save(this.bookings); 99 | this.requestUpload(); 100 | }; 101 | FlightSearchComponent.prototype.booked = function (b) { 102 | b.buchungsStatus = 0; 103 | b.isDirty = true; 104 | this.bookingervice.save(this.bookings); 105 | this.requestUpload(); 106 | }; 107 | FlightSearchComponent = __decorate([ 108 | core_1.Component({ 109 | selector: 'flight-search', 110 | templateUrl: 'app/flightsearch.component.html', 111 | styleUrls: ['app/flightsearch.component.css', 'node_modules/bootstrap/dist/css/bootstrap.css'], 112 | directives: [APP_MD_DIRECTIVES], 113 | providers: [booking_service_1.BookingService, icon_1.MdIconRegistry], 114 | pipes: [booking_status_pipe_1.BookingStatusPipe] 115 | }), 116 | __metadata('design:paramtypes', [core_1.ChangeDetectorRef, booking_service_1.BookingService]) 117 | ], FlightSearchComponent); 118 | return FlightSearchComponent; 119 | }()); 120 | exports.FlightSearchComponent = FlightSearchComponent; 121 | //# sourceMappingURL=flightsearch.component.js.map -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | true 155 | DEFINITION_ORDER 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | project 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | project 288 | 289 | 290 | true 291 | 292 | 293 | 294 | DIRECTORY 295 | 296 | false 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 1474755282915 310 | 311 | 312 | 1474755282915 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | --------------------------------------------------------------------------------
Flight-No.: {{b.flug.id}}
{{b.flug.datum.substr(0,10)}}
{{b.buchungsStatus | bookingStatus}}