From b616f407faa726670b33e291a34a2264f1fa5a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Mon, 10 Dec 2018 11:02:57 -0500 Subject: [PATCH 01/44] Initial commit --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57a8f2055..d52b40cae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -784,7 +784,7 @@ "resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-5.0.0-beta.15.tgz", "integrity": "sha512-71Fiy/UlchvjkWpRaZ90E9hrrf+v/x+CCl6JPGg3nLGYqrVtja5xJCU0jVsGQMrYdgfcwK9d1KLC/3GPvOQK1w==", "requires": { - "@types/cordova": "0.0.34" + "@types/cordova": "^0.0.34" } }, "@ionic-native/in-app-browser": { @@ -792,7 +792,7 @@ "resolved": "https://registry.npmjs.org/@ionic-native/in-app-browser/-/in-app-browser-5.0.0-beta.15.tgz", "integrity": "sha512-C6OO6SUwKeTsDeyN1DpTgCidrcPo1Ny2HOYQpAG4/8Wlkbl0R2Z3vK63wZuRf3hR+4VNge/SRWsXT6qRTFPa8g==", "requires": { - "@types/cordova": "0.0.34" + "@types/cordova": "^0.0.34" } }, "@ionic-native/splash-screen": { @@ -800,7 +800,7 @@ "resolved": "https://registry.npmjs.org/@ionic-native/splash-screen/-/splash-screen-5.0.0-beta.15.tgz", "integrity": "sha512-ZoMw1kmTtKP0ylmtkr5KyJtmrUnJbtO+DIeUp7R/58wdKlvY7nq/y5oNAdmJKuJ6Oe88LqpTz5jm+V2DzXr/gA==", "requires": { - "@types/cordova": "0.0.34" + "@types/cordova": "^0.0.34" } }, "@ionic-native/status-bar": { @@ -808,7 +808,7 @@ "resolved": "https://registry.npmjs.org/@ionic-native/status-bar/-/status-bar-5.0.0-beta.15.tgz", "integrity": "sha512-FSKOCeLq8H9JvdjY7v4wYJCK8Lj/PAnDc+ddvA1j9u2vXOMDABnpTXc+WLssBf3El9n9LPHNa+Kk0nsxV02obA==", "requires": { - "@types/cordova": "0.0.34" + "@types/cordova": "^0.0.34" } }, "@ionic/angular": { From 11f6cb71120eff7a76bc80510f3d83cbd3b9e808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 18 Dec 2018 23:00:10 -0500 Subject: [PATCH 02/44] update login and signup module: made API request --- .gitignore | 1 + package-lock.json | 822 +++++++++++++++++++++++++-- package.json | 3 + src/app/app.module.ts | 10 +- src/app/models.ts | 66 +++ src/app/pages/login/login.html | 8 +- src/app/pages/login/login.ts | 51 +- src/app/pages/signup/signup.html | 30 +- src/app/pages/signup/signup.ts | 49 +- src/app/providers/user-data.ts | 71 ++- src/assets/data/data.json | 35 +- src/environments/environment.prod.ts | 3 - src/environments/environment.ts | 15 - 13 files changed, 1017 insertions(+), 147 deletions(-) create mode 100644 src/app/models.ts delete mode 100644 src/environments/environment.prod.ts delete mode 100644 src/environments/environment.ts diff --git a/.gitignore b/.gitignore index 7002d1672..b6cb3e8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ npm-debug.log* coverage/ dist/ node_modules/ +src/environments tmp/ temp/ hooks/ diff --git a/package-lock.json b/package-lock.json index d52b40cae..5adfecfb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -559,6 +559,11 @@ "tslib": "^1.9.0" } }, + "@angular/fire": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-5.1.1.tgz", + "integrity": "sha512-QfLVEhZYW3+3fh2d1z76/vab1GkLnEQWzFQK06D1ZaT8jZsVEdFMIPr7GSTJWAuOdqBRYq14iqzqEkJH3WHzig==" + }, "@angular/forms": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.1.0.tgz", @@ -779,6 +784,212 @@ } } }, + "@firebase/app": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.3.5.tgz", + "integrity": "sha512-DaAlb74yzwXbkFXvfsUVFeurSETPJAvKNtVpAKlS6RThyD+Y+ci1/8JVw4INm2hihbj/edxlAUelg9eoOZNCKA==", + "requires": { + "@firebase/app-types": "0.3.2", + "@firebase/util": "0.2.3", + "dom-storage": "2.1.0", + "tslib": "1.9.0", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/app-types": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.3.2.tgz", + "integrity": "sha512-ZD8lTgW07NGgo75bTyBJA8Lt9+NweNzot7lrsBtIvfciwUzaFJLsv2EShqjBeuhF7RpG6YFucJ6m67w5buCtzw==" + }, + "@firebase/auth": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.9.0.tgz", + "integrity": "sha512-pNxfxFr4/tJluGfmPYUiuy2Tq/ZSRniJlWP4fj1mg+a9r+KevheeISZdWEZwJMosieXeCg+BzY0tvFD9j5ZrDw==", + "requires": { + "@firebase/auth-types": "0.5.0" + } + }, + "@firebase/auth-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.5.0.tgz", + "integrity": "sha512-DSjtsIjTy5RSiWyGHqiGkLcDgEgFEf2aD2O0t/0+lHmAzxUGrJFO5+IkPNV6i0ffmtiJaXQDJ7z7q4OdypDBCg==" + }, + "@firebase/database": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.3.7.tgz", + "integrity": "sha512-BB5L3PqwQVJUdS1WY+sq3eun5n5oimFWolXYl6pyACJwqL2qnPp0cnjK6kOqTsRPPMayZZmfUI38RBDwXaUJhQ==", + "requires": { + "@firebase/database-types": "0.3.2", + "@firebase/logger": "0.1.2", + "@firebase/util": "0.2.3", + "faye-websocket": "0.11.1", + "tslib": "1.9.0" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/database-types": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.3.2.tgz", + "integrity": "sha512-9ZYdvYQ6r3aaHJarhUM5Hf6lQWu3ZJme+RR0o8qfBb9L04TL3uNjt+AJFku1ysVPntTn+9GqJjiIB2/OC3JtwA==" + }, + "@firebase/firestore": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-0.9.0.tgz", + "integrity": "sha512-ub9BXce75D7t2yQxqopJhqE5YrsdePLg7wP8aMLR2Twe+O89IZqOhdbE0VALjplD2rAWXkOLqf6zYsppu2hh4g==", + "requires": { + "@firebase/firestore-types": "0.8.0", + "@firebase/logger": "0.1.2", + "@firebase/webchannel-wrapper": "0.2.11", + "grpc": "1.16.1", + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/firestore-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-0.8.0.tgz", + "integrity": "sha512-FdLy2TbZ6aAeT9eDmVMPAFsUqhjN2e+jcdVpl0Pz1W6ElRWWyr30hgTY7xIqIKpMs1iT6IF/8w9CKvI6fPbKxA==" + }, + "@firebase/functions": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.3.3.tgz", + "integrity": "sha512-t8CE1AQivqWeDJ1MvaITGn+x6Z78CVnJi3mLz/+2Vx7UwU4HRhkfJcxhrRnnMzWY9OoCJ9j1wUoDsXfKmU546w==", + "requires": { + "@firebase/functions-types": "0.2.1", + "@firebase/messaging-types": "0.2.3", + "isomorphic-fetch": "2.2.1", + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/functions-types": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.2.1.tgz", + "integrity": "sha512-hH78lgDoa5E1peBSXnfQyshENmh/5a8aia+S4Ocjc53OUWRJ4VqYwWUV5gE4b2mqVKTpN4akJccLq2pCnNGZcA==" + }, + "@firebase/logger": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.1.2.tgz", + "integrity": "sha512-4NHGRIbZChg9vDUxynzYrw14G/U/71v0pea+jXPicrpflL0N0PSCULXGGSTmzn9fqZ5W5djEwVLBCVwKndXG8w==" + }, + "@firebase/messaging": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.3.7.tgz", + "integrity": "sha512-8tZgRVJuvmFe5HDUiKvGAsK/jehrMnoUx95XU3RkZHX2D5QHjXAvvXIfFQ118EtG5/whZoEo1nCjEHAd9mSalA==", + "requires": { + "@firebase/messaging-types": "0.2.3", + "@firebase/util": "0.2.3", + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/messaging-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.2.3.tgz", + "integrity": "sha512-avwCgZzcx2uxIW/wT3p3G/EyHftIrvMyiTS7AA7dxDlzfx+8dpAeTsb1+jsHJT4F6foSh5HG17Nw8sDzYuxH1Q==" + }, + "@firebase/polyfill": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.3.tgz", + "integrity": "sha512-xs8IZf1WEbufYXyfV8YjmiFZOaujRRq0T03NteihYfuGVTTym7z5SmvLvEHLEUjf2fgeobPEzZ2JgrCQHS+QHw==", + "requires": { + "core-js": "2.5.5", + "promise-polyfill": "7.1.2", + "whatwg-fetch": "2.0.4" + }, + "dependencies": { + "core-js": { + "version": "2.5.5", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" + }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + } + } + }, + "@firebase/storage": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.2.4.tgz", + "integrity": "sha512-uqA6CoZYkugk69ImqB16VBPP7JRPRfZwcUP9CsE0GPVGQkZQQfBGwzIyEoFA8lUfVLrvxQiL0sQvHUXZ945LMg==", + "requires": { + "@firebase/storage-types": "0.2.3", + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/storage-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.2.3.tgz", + "integrity": "sha512-RaZeam2LgsB7xwAtOQr4G0Geoyf7D5TnLF3a12By6Rh0Z9PqBSlWn0SVYGW3SkmxIdqvWZMZvCyamUlqQvQzWw==" + }, + "@firebase/util": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.3.tgz", + "integrity": "sha512-ngAG4qYpcnnshUKbBlEiR9+j37U7dTrTVJlS4v7ahW1ROuyLT9xj6cWyHQANzcTR2yKLmEv3yfwoZwedz7V0oQ==", + "requires": { + "tslib": "1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==" + } + } + }, + "@firebase/webchannel-wrapper": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.11.tgz", + "integrity": "sha512-WyMXDxk/WZ+f2lOCeEvDWUce2f5Kk2sNfvArK8f+PlUnzFdy/MBzLXrmbMgyZXP7GP4ooUxYV8Sdmoh1hGk1Uw==" + }, "@ionic-native/core": { "version": "5.0.0-beta.15", "resolved": "https://registry.npmjs.org/@ionic-native/core/-/core-5.0.0-beta.15.tgz", @@ -1507,6 +1718,14 @@ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, + "angularfire2": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/angularfire2/-/angularfire2-5.1.1.tgz", + "integrity": "sha512-xW37qu3y9yZyqEYF/j2CIMaavwaufhlESfVKQ6FVCcSI2XaZ7bwlNwLJ6AIMyUL2uuf5P+iHyh9HnnJJkmCyFQ==", + "requires": { + "@angular/fire": "5.1.1" + } + }, "ansi-colors": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.1.tgz", @@ -1528,8 +1747,7 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", @@ -1662,6 +1880,15 @@ "dev": true, "optional": true }, + "ascli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz", + "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=", + "requires": { + "colour": "~0.7.1", + "optjs": "~3.2.2" + } + }, "asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", @@ -1916,8 +2143,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", @@ -2103,7 +2329,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2310,6 +2535,14 @@ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", "dev": true }, + "bytebuffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", + "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=", + "requires": { + "long": "~3" + } + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -2362,9 +2595,7 @@ "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true, - "optional": true + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" }, "camelcase-keys": { "version": "2.1.0", @@ -2532,7 +2763,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", @@ -2566,8 +2796,7 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codelyzer": { "version": "4.5.0", @@ -2621,6 +2850,11 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, + "colour": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz", + "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=" + }, "combine-lists": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", @@ -2701,8 +2935,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "1.6.2", @@ -3643,8 +3876,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -3889,6 +4121,11 @@ "void-elements": "^2.0.0" } }, + "dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==" + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", @@ -3969,7 +4206,6 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "dev": true, "requires": { "iconv-lite": "~0.4.13" } @@ -4701,6 +4937,21 @@ "locate-path": "^2.0.0" } }, + "firebase": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-5.7.0.tgz", + "integrity": "sha512-8sQYXCUbUuzpyZS+XpBogstQE/7lvX6tPWtrUH0Cf4mH7flH/Sue5GUvZzwBpkgKOrMpI+clzuoYm/ffGi/TjQ==", + "requires": { + "@firebase/app": "0.3.5", + "@firebase/auth": "0.9.0", + "@firebase/database": "0.3.7", + "@firebase/firestore": "0.9.0", + "@firebase/functions": "0.3.3", + "@firebase/messaging": "0.3.7", + "@firebase/polyfill": "0.3.3", + "@firebase/storage": "0.2.4" + } + }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", @@ -4825,8 +5076,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.4", @@ -5436,7 +5686,6 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5538,6 +5787,422 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, + "grpc": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.16.1.tgz", + "integrity": "sha512-7uHN1Nd3UqfvwgQ6f5U3+EZb/0iuHJ9mbPH+ydaTkszJsUi3nwdz6DuSh0eJwYVXXn6Gojv2khiQAadMongGKg==", + "requires": { + "lodash": "^4.17.5", + "nan": "^2.0.0", + "node-pre-gyp": "^0.12.0", + "protobufjs": "^5.0.3" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.5", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.1", + "bundled": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true + }, + "npm-packlist": { + "version": "1.1.12", + "bundled": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "sax": { + "version": "1.2.4", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true + } + } + }, "handle-thing": { "version": "1.2.5", "resolved": "http://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", @@ -5779,8 +6444,7 @@ "http-parser-js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", - "dev": true + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==" }, "http-proxy": { "version": "1.17.0", @@ -5908,7 +6572,6 @@ "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -6067,7 +6730,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -6166,8 +6828,7 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ionicons": { "version": "4.4.7", @@ -6326,7 +6987,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6410,8 +7070,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-typedarray": { "version": "1.0.0", @@ -6461,6 +7120,15 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -7021,7 +7689,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -7157,8 +7824,7 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, "lodash.assign": { "version": "4.2.0", @@ -7281,6 +7947,11 @@ "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", "dev": true }, + "long": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -7612,7 +8283,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -7758,8 +8428,7 @@ "nan": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "optional": true + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" }, "nanomatch": { "version": "1.2.13", @@ -7803,6 +8472,15 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-fetch-npm": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", @@ -8080,8 +8758,7 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "oauth-sign": { "version": "0.9.0", @@ -8191,7 +8868,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -8246,6 +8922,11 @@ "wordwrap": "~1.0.0" } }, + "optjs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", + "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -8271,8 +8952,6 @@ "version": "1.4.0", "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "optional": true, "requires": { "lcid": "^1.0.0" } @@ -8826,6 +9505,11 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "promise-polyfill": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.1.2.tgz", + "integrity": "sha512-FuEc12/eKqqoRYIGBrUptCBRhobL19PS2U31vMNTfyck1FxPyMfgsXyW4Mav85y/ZN1hop3hOwRlUDok23oYfQ==" + }, "promise-retry": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", @@ -8836,6 +9520,38 @@ "retry": "^0.10.0" } }, + "protobufjs": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.3.tgz", + "integrity": "sha512-55Kcx1MhPZX0zTbVosMQEO5R6/rikNXd9b6RQK4KSPcrSIIwoXTtebIczUrXlwaSrbz4x8XUVThGPob1n8I4QA==", + "requires": { + "ascli": "~1", + "bytebuffer": "~5", + "glob": "^7.0.5", + "yargs": "^3.10.0" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + } + } + }, "protoduck": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", @@ -9526,8 +10242,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass-graph": { "version": "2.2.4", @@ -10433,7 +11148,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10452,7 +11166,6 @@ "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11735,7 +12448,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", - "dev": true, "requires": { "http-parser-js": ">=0.4.0", "websocket-extensions": ">=0.1.1" @@ -11744,8 +12456,12 @@ "websocket-extensions": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", - "dev": true + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" }, "when": { "version": "3.6.4", @@ -11778,6 +12494,11 @@ "string-width": "^1.0.2 || 2" } }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -11797,7 +12518,6 @@ "version": "2.1.0", "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -11806,8 +12526,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "2.3.0", @@ -11855,6 +12574,11 @@ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", diff --git a/package.json b/package.json index 5a8f47990..dc5df4d9c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "dependencies": { "@angular/common": "~7.1.0", "@angular/core": "~7.1.0", + "@angular/fire": "^5.1.1", "@angular/forms": "~7.1.0", "@angular/http": "~7.1.0", "@angular/platform-browser": "~7.1.0", @@ -32,6 +33,7 @@ "@ionic-native/status-bar": "5.0.0-beta.15", "@ionic/angular": "4.0.0-beta.16", "@ionic/storage": "^2.1.3", + "angularfire2": "^5.1.1", "cordova-android": "^7.1.1", "cordova-ios": "^4.5.5", "cordova-plugin-device": "^2.0.2", @@ -42,6 +44,7 @@ "cordova-plugin-statusbar": "^2.4.2", "cordova-plugin-whitelist": "^1.3.2", "core-js": "^2.5.7", + "firebase": "^5.7.0", "rxjs": "6.3.3", "sw-toolbox": "3.6.0", "zone.js": "^0.8.26" diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 6ebafab6d..7d14b4f77 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -7,10 +7,13 @@ import { StatusBar } from '@ionic-native/status-bar/ngx'; import { IonicModule } from '@ionic/angular'; import { IonicStorageModule } from '@ionic/storage'; +import { environment } from '../environments/environment'; +import { AngularFireModule } from 'angularfire2'; +import { AngularFirestoreModule } from 'angularfire2/firestore'; +import { AngularFireAuthModule } from 'angularfire2/auth'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { ServiceWorkerModule } from '@angular/service-worker'; -import { environment } from '../environments/environment'; @NgModule({ imports: [ @@ -21,7 +24,10 @@ import { environment } from '../environments/environment'; IonicStorageModule.forRoot(), ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production - }) + }), + AngularFireModule.initializeApp(environment.firebase, 'ionic-conference'), + AngularFireAuthModule, + AngularFirestoreModule, ], declarations: [AppComponent], providers: [InAppBrowser, SplashScreen, StatusBar], diff --git a/src/app/models.ts b/src/app/models.ts new file mode 100644 index 000000000..b5ccbec7d --- /dev/null +++ b/src/app/models.ts @@ -0,0 +1,66 @@ +// These are the categories for filtering stuff +export interface Track { + id?: string; + name: string; +} + +export interface Speaker { + id?: string; + name: string; + profilePic?: string; + twitter?: string; + about?: string; + location?: string; + email: string; + phone?: string; + sessions?: IdName[]; // session id & name +} + +export interface Session { + id?: string; + name: string; + date: string; // 2018-12-06 + timeStart: string; // 15:30 for 3:30pm + timeEnd?: string; + location?: string; + description?: string; + speakerIDs: string[]; // speaker's id + tracks: string[]; // name of track +} + +export interface IdName { + id: string; + name: string; +} + +export interface Map { + id?: string; + name: string; + lat: number; + lng: number; + center?: boolean; +} + +export interface UserOptions { + id?: string; + username: string; + password: string; + email: string; + favorites: IdName[]; // session's id and name. +} + +export interface PartOfDay { + partOfDay: string; // morning, afternoon, evening, overnight + timeFrom: string; + timeTo: string; +} + +export interface Schedule { + date: string; // 2018-12-06 + groups: SessionGroup[]; +} + +export interface SessionGroup { + time: PartOfDay; + sessions: Session[]; +} diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html index 4b7d92aa8..825fd6ee4 100644 --- a/src/app/pages/login/login.html +++ b/src/app/pages/login/login.html @@ -17,25 +17,25 @@ Username - -

+

Username is required

Password - + -

+

Password is required

diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 19222240f..94977365d 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -1,12 +1,9 @@ -import { Component, ViewEncapsulation } from '@angular/core'; +import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; - -import { UserOptions } from '../../interfaces/user-options'; - - +import { UserOptions } from '../../models'; @Component({ selector: 'page-login', @@ -14,22 +11,42 @@ import { UserOptions } from '../../interfaces/user-options'; styleUrls: ['./login.scss'], encapsulation: ViewEncapsulation.None }) -export class LoginPage { - login: UserOptions = { username: '', password: '' }; - submitted = false; - - constructor( - public userData: UserData, - public router: Router - ) { } +export class LoginPage implements OnInit { + username: ''; + password: '' ; + users: UserOptions[]; + + constructor(public userData: UserData, + public router: Router, + private userService: UserData) { } + + ngOnInit() { + this.userService.getUsers().subscribe( + (data: UserOptions[]) => { this.users = data; } + ); + } onLogin(form: NgForm) { - this.submitted = true; - if (form.valid) { - this.userData.login(this.login.username); - this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + const user = this.findUser(this.username.toLowerCase().trim()); + if (user) { + if (user.password === this.password) { + this.userData.login(user); + this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + } else { + alert('Invalid password. Try again.'); + } + } else { + alert('User not found. Try again.'); + } + } + } + + findUser(data: string) { + if (data.indexOf('@') > -1) { + return this.users.find(user => user.email.toLowerCase() === data); } + return this.users.find(user => user.username.toLowerCase() === data); } onSignup() { diff --git a/src/app/pages/signup/signup.html b/src/app/pages/signup/signup.html index 38c5bed9c..b572b2ea5 100644 --- a/src/app/pages/signup/signup.html +++ b/src/app/pages/signup/signup.html @@ -26,9 +26,21 @@

+ + Email + + + + +

+ Email is required +

+
+ Password - + @@ -36,6 +48,22 @@ Password is required

+ + + Confirm Password + + + + +

+ Confirm Password is required +

+
+ +

+ Password does not match with Confirm Password +

+
diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index f8b8da113..374f15347 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -1,12 +1,9 @@ -import { Component, ViewEncapsulation } from '@angular/core'; +import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; - -import { UserOptions } from '../../interfaces/user-options'; - - +import { UserOptions } from '../../models'; @Component({ selector: 'page-signup', @@ -14,21 +11,43 @@ import { UserOptions } from '../../interfaces/user-options'; styleUrls: ['./signup.scss'], encapsulation: ViewEncapsulation.None }) -export class SignupPage { - signup: UserOptions = { username: '', password: '' }; +export class SignupPage implements OnInit { + users: UserOptions[]; + signup: UserOptions = { + username: '', password: '', email: '', favorites: [] + }; + confirmPassword = ''; submitted = false; - constructor( - public router: Router, - public userData: UserData - ) {} + constructor(public router: Router, + public userData: UserData, + private userService: UserData) {} + + ngOnInit() { + this.userService.getUsers().subscribe( + (data: UserOptions[]) => { this.users = data; } + ); + } onSignup(form: NgForm) { this.submitted = true; - - if (form.valid) { - this.userData.signup(this.signup.username); - this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + if (form.valid && this.signup.password === this.confirmPassword) { + if (this.isNameUsed(this.signup.username)) { + alert('Name is already taken.'); + } else if (this.isEmailUsed(this.signup.email)) { + alert('Email is already taken.'); + } else { + this.userData.signup(this.signup); + this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + } } } + + isNameUsed(name) { + return this.users.find(ur => ur.username.toLowerCase() === name.toLowerCase()); + } + + isEmailUsed(email) { + return this.users.find(ur => ur.email.toLowerCase() === email.toLowerCase()); + } } diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index c171627b1..8634d9a3e 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -1,20 +1,49 @@ import { Injectable } from '@angular/core'; import { Events } from '@ionic/angular'; import { Storage } from '@ionic/storage'; +import { AngularFirestore, + AngularFirestoreCollection, + AngularFirestoreDocument } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { UserOptions } from '../models'; @Injectable({ providedIn: 'root' }) export class UserData { + usersCollection: AngularFirestoreCollection ; + userDoc: AngularFirestoreDocument ; + users: Observable ; + user: Observable ; _favorites: string[] = []; HAS_LOGGED_IN = 'hasLoggedIn'; HAS_SEEN_TUTORIAL = 'hasSeenTutorial'; - constructor( - public events: Events, - public storage: Storage - ) { } + constructor(private afs: AngularFirestore, + public events: Events, + public storage: Storage) { + this.usersCollection = this.afs.collection( + 'usersYS', ref => ref.orderBy('username', 'asc')); + } + + getUsers(): Observable { + this.users = this.usersCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as UserOptions; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.users; + } + + signup(user: UserOptions) { + this.usersCollection.add(user); + this.login(user); + } hasFavorite(sessionName: string): boolean { return (this._favorites.indexOf(sessionName) > -1); @@ -31,35 +60,47 @@ export class UserData { } } - login(username: string): Promise { + login(user: UserOptions): Promise { return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { - this.setUsername(username); + this.setUser(user); return this.events.publish('user:login'); }); } - signup(username: string): Promise { - return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { - this.setUsername(username); - return this.events.publish('user:signup'); - }); - } + // signup(user: UserOptions): Promise { + // console.log(user); + // return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { + // this.setUsername(user.username); + // return this.events.publish('user:signup'); + // }); + // } logout(): Promise { return this.storage.remove(this.HAS_LOGGED_IN).then(() => { - return this.storage.remove('username'); + return this.storage.remove('user'); }).then(() => { this.events.publish('user:logout'); }); } + setUser(user: UserOptions): Promise { + return this.storage.set('user', user); + } + setUsername(username: string): Promise { + console.log('need to fix'); return this.storage.set('username', username); } getUsername(): Promise { - return this.storage.get('username').then((value) => { - return value; + return this.storage.get('user').then((value) => { + return value.username; + }); + } + + getUserId(): Promise { + return this.storage.get('user').then((value) => { + return value.id; }); } diff --git a/src/assets/data/data.json b/src/assets/data/data.json index 717bc0a35..fcbe9776c 100755 --- a/src/assets/data/data.json +++ b/src/assets/data/data.json @@ -3,7 +3,7 @@ "schedule": [{ "date": "2047-05-17", "groups": [{ - "time": "8:00 am", + "time": "Morning", "sessions": [{ "name": "Breakfast", "timeStart": "8:00 am", @@ -11,10 +11,7 @@ "location": "Dining Hall", "tracks": ["Food"], "id": "1" - }] - }, { - "time": "9:15 am", - "sessions": [{ + }, { "name": "Getting Started with Ionic", "location": "Hall 2", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", @@ -22,6 +19,7 @@ "timeStart": "9:30 am", "timeEnd": "9:45 am", "tracks": ["Ionic"], + "hide": true, "id": "2" }, { "name": "Ionic Tooling", @@ -41,10 +39,7 @@ "timeEnd": "9:30 am", "tracks": ["Ionic"], "id": "4" - }] - }, { - "time": "10:00 am", - "sessions": [{ + }, { "name": "Migrating to Ionic", "location": "Hall 1", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", @@ -80,10 +75,7 @@ "timeEnd": "11:00 am", "tracks": ["Services"], "id": "8" - }] - }, { - "time": "11:00 am", - "sessions": [{ + }, { "name": "Ionic Workshop", "location": "Hall 1", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", @@ -112,7 +104,7 @@ "id": "11" }] }, { - "time": "12:00 pm", + "time": "Afternoon", "sessions": [{ "name": "Lunch", "location": "Dining Hall", @@ -121,10 +113,7 @@ "timeEnd": "1:00 pm", "tracks": ["Food"], "id": "12" - }] - }, { - "time": "1:00 pm", - "sessions": [{ + }, { "name": "Ionic in the Enterprise", "location": "Hall 1", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", @@ -151,10 +140,7 @@ "timeEnd": "2:00 pm", "tracks": ["Services"], "id": "15" - }] - }, { - "time": "2:00 pm", - "sessions": [{ + }, { "name": "Push Notifications in Ionic", "location": "Hall 2", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", @@ -181,10 +167,7 @@ "timeEnd": "3:00 pm", "tracks": ["Design"], "id": "18" - }] - }, { - "time": "3:00", - "sessions": [{ + }, { "name": "Angular Directives in Ionic", "location": "Hall 1", "description": "Mobile devices and browsers are now advanced enough that developers can build native-quality mobile apps using open web technologies like HTML5, Javascript, and CSS. In this talk, we’ll provide background on why and how we created Ionic, the design decisions made as we integrated Ionic with Angular, and the performance considerations for mobile platforms that our team had to overcome. We’ll also review new and upcoming Ionic features, and talk about the hidden powers and benefits of combining mobile app development and Angular.", diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts deleted file mode 100644 index 3612073bc..000000000 --- a/src/environments/environment.prod.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const environment = { - production: true -}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts deleted file mode 100644 index ad4196020..000000000 --- a/src/environments/environment.ts +++ /dev/null @@ -1,15 +0,0 @@ -// The file contents for the current environment will overwrite these during build. -// The build system defaults to the dev environment which uses `environment.ts`, but if you do -// `ng build --env=prod` then `environment.prod.ts` will be used instead. -// The list of which env maps to which file can be found in `.angular-cli.json`. -export const environment = { - production: false -}; - -/* - * In development mode, to ignore zone related error stack frames such as - * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can - * import the following file, but please comment it out in production mode - * because it will have performance impact when throw error - */ -// import 'zone.js/dist/zone-error'; // Included with Angular CLI. From fbfd6e69f1e76abff109a35472b6761d3fdfbd84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 12:44:46 -0500 Subject: [PATCH 03/44] update 'support' mode: connect with firebase --- src/app/models.ts | 7 ++++ src/app/pages/support/support.html | 8 +++-- src/app/pages/support/support.scss | 4 +++ src/app/pages/support/support.ts | 24 +++++++------ src/app/providers/function-data.ts | 22 ++++++++++++ src/app/providers/support-data.ts | 54 ++++++++++++++++++++++++++++++ src/app/providers/user-data.ts | 9 +++-- 7 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 src/app/providers/function-data.ts create mode 100644 src/app/providers/support-data.ts diff --git a/src/app/models.ts b/src/app/models.ts index b5ccbec7d..b40175b6e 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -49,6 +49,13 @@ export interface UserOptions { favorites: IdName[]; // session's id and name. } +export interface Support { + id?: string; + userId: string; + date: string; // 2018-12-19 + support: string; +} + export interface PartOfDay { partOfDay: string; // morning, afternoon, evening, overnight timeFrom: string; diff --git a/src/app/pages/support/support.html b/src/app/pages/support/support.html index 278e9856f..054ef7c87 100644 --- a/src/app/pages/support/support.html +++ b/src/app/pages/support/support.html @@ -5,10 +5,9 @@ Support - - + @@ -26,9 +25,12 @@ Support message is required

-
Submit
+ +

You need to login first!

+
+ diff --git a/src/app/pages/support/support.scss b/src/app/pages/support/support.scss index 3e465b273..64dd92e36 100644 --- a/src/app/pages/support/support.scss +++ b/src/app/pages/support/support.scss @@ -12,4 +12,8 @@ page-support { .list { margin-bottom: 0; } + + .support-msg h4 { + margin: 200px 80px; + } } diff --git a/src/app/pages/support/support.ts b/src/app/pages/support/support.ts index bda531c6c..8c93eae04 100644 --- a/src/app/pages/support/support.ts +++ b/src/app/pages/support/support.ts @@ -1,8 +1,10 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { NgForm } from '@angular/forms'; +import { Storage } from '@ionic/storage'; import { AlertController, ToastController } from '@ionic/angular'; - +import { UserData } from '../../providers/user-data'; +import { SupportData } from '../../providers/support-data'; @Component({ selector: 'page-support', @@ -11,29 +13,29 @@ import { AlertController, ToastController } from '@ionic/angular'; encapsulation: ViewEncapsulation.None }) export class SupportPage { + isLoggedIn = false; submitted = false; supportMessage: string; - constructor( - public alertCtrl: AlertController, - public toastCtrl: ToastController - ) { } + constructor(public alertCtrl: AlertController, + public toastCtrl: ToastController, + private userData: UserData, + private supportData: SupportData, + public storage: Storage) { + } async ionViewDidEnter() { - const toast = await this.toastCtrl.create({ - message: 'This does not actually send a support request.', - duration: 3000 - }); - await toast.present(); + this.userData.isLoggedIn() + .then(res => this.isLoggedIn = res); } async submit(form: NgForm) { this.submitted = true; if (form.valid) { + this.supportData.addSupport(this.supportMessage); this.supportMessage = ''; this.submitted = false; - const toast = await this.toastCtrl.create({ message: 'Your support request has been sent.', duration: 3000 diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts new file mode 100644 index 000000000..2025543a8 --- /dev/null +++ b/src/app/providers/function-data.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class FunctionlData { + + getDataFormat(date: Date) { + if (!date) { + date = new Date(); + } + const dateArray = date.toLocaleDateString().split('/'); + return dateArray[2] + '-' + + this.reform2digits(dateArray[0]) + '-' + + this.reform2digits(dateArray[1]); + } + + reform2digits(value) { + if (value.length === 1) return '0' + value; + return value ; + } +} \ No newline at end of file diff --git a/src/app/providers/support-data.ts b/src/app/providers/support-data.ts new file mode 100644 index 000000000..a0e27ce5f --- /dev/null +++ b/src/app/providers/support-data.ts @@ -0,0 +1,54 @@ +import { Injectable } from '@angular/core'; +import { Events } from '@ionic/angular'; +import { AngularFirestore, + AngularFirestoreCollection, + AngularFirestoreDocument } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { Support } from '../models'; +import { FunctionlData } from './function-data'; +import { UserData } from './user-data'; + +@Injectable({ + providedIn: 'root' +}) +export class SupportData { + supportsCollection: AngularFirestoreCollection ; + supportDoc: AngularFirestoreDocument ; + supports: Observable ; + support: Observable ; + + constructor(private afs: AngularFirestore, + private functionData: FunctionlData, + private userData: UserData, + public events: Events) { + this.supportsCollection = this.afs.collection( + 'supports', ref => ref.orderBy('date', 'asc')); + } + + getSupports(): Observable { + this.supports = this.supportsCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Support; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.supports; + } + + addSupport(message: string) { + const date = this.functionData.getDataFormat(null); + this.userData.getUserId() + .then(id => { + const support: Support = { + date: date, + userId: id, + support: message + }; + this.supportsCollection.add(support); + }); + } +} \ No newline at end of file diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 8634d9a3e..868e3135d 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -25,7 +25,7 @@ export class UserData { public events: Events, public storage: Storage) { this.usersCollection = this.afs.collection( - 'usersYS', ref => ref.orderBy('username', 'asc')); + 'users', ref => ref.orderBy('username', 'asc')); } getUsers(): Observable { @@ -41,8 +41,11 @@ export class UserData { } signup(user: UserOptions) { - this.usersCollection.add(user); - this.login(user); + this.usersCollection.add(user) + .then(res => { + user.id = res.id; + this.login(user); + }); } hasFavorite(sessionName: string): boolean { From 0bdf96f4f0c955f1e98ab4d24ec7c6c7e8f9ddb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 14:22:00 -0500 Subject: [PATCH 04/44] update 'change username' of the account mode --- src/app/interfaces/user-options.ts | 2 +- src/app/pages/account/account.html | 1 + src/app/pages/account/account.ts | 43 +++++++++++++++++++++--------- src/app/providers/function-data.ts | 10 +++---- src/app/providers/support-data.ts | 4 +-- src/app/providers/user-data.ts | 23 ++++++++++------ 6 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/app/interfaces/user-options.ts b/src/app/interfaces/user-options.ts index 16437e175..1dda3fc7f 100644 --- a/src/app/interfaces/user-options.ts +++ b/src/app/interfaces/user-options.ts @@ -1,5 +1,5 @@ -export interface UserOptions { +export interface UserOption { username: string; password: string; } diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index 176248f12..3ed80ecb2 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -19,5 +19,6 @@

{{username}}

Support Logout +

{{ jobDescription }}

diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 6541b5625..4a1f30fc0 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -1,10 +1,9 @@ import { AfterViewInit, Component, ViewEncapsulation } from '@angular/core'; import { Router } from '@angular/router'; - import { AlertController } from '@ionic/angular'; import { UserData } from '../../providers/user-data'; - +import { UserOptions } from '../../models'; @Component({ selector: 'page-account', @@ -13,15 +12,17 @@ import { UserData } from '../../providers/user-data'; encapsulation: ViewEncapsulation.None }) export class AccountPage implements AfterViewInit { + users: UserOptions[]; username: string; + succeed: boolean; + jobDescription: string; - constructor( - public alertCtrl: AlertController, - public router: Router, - public userData: UserData - ) { } + constructor(public alertCtrl: AlertController, + public router: Router, + public userData: UserData) {} ngAfterViewInit() { + this.getUsers(); this.getUsername(); } @@ -33,15 +34,22 @@ export class AccountPage implements AfterViewInit { // clicking OK will update the username and display it // clicking Cancel will close the alert and do nothing async changeUsername() { - const alert = await this.alertCtrl.create({ + this.succeed = false; + const changeForm = await this.alertCtrl.create({ header: 'Change Username', buttons: [ 'Cancel', { text: 'Ok', handler: (data: any) => { - this.userData.setUsername(data.username); - this.getUsername(); + if (this.isNameExist(data.username)) { + alert(data.username + ' is used already. Try another.') + } else { + this.userData.updateUsername(data.username); + this.username = data.username; + this.succeed = true; + this.jobDescription = "User's name is changed." + } } } ], @@ -50,11 +58,11 @@ export class AccountPage implements AfterViewInit { type: 'text', name: 'username', value: this.username, - placeholder: 'username' + placeholder: 'new username' } ] }); - await alert.present(); + await changeForm.present(); } getUsername() { @@ -63,6 +71,17 @@ export class AccountPage implements AfterViewInit { }); } + getUsers() { + this.userData.getUsers().subscribe( + users => { this.users = users; } + ) + } + + isNameExist(name: string) { + return this.users.find( + user => user.username.toLowerCase() === name.toLowerCase()); + } + changePassword() { console.log('Clicked to change password'); } diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index 2025543a8..c3334c8cf 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -4,19 +4,19 @@ import { Injectable } from '@angular/core'; providedIn: 'root' }) export class FunctionlData { - + getDataFormat(date: Date) { if (!date) { date = new Date(); } const dateArray = date.toLocaleDateString().split('/'); - return dateArray[2] + '-' + - this.reform2digits(dateArray[0]) + '-' + + return dateArray[2] + '-' + + this.reform2digits(dateArray[0]) + '-' + this.reform2digits(dateArray[1]); } reform2digits(value) { - if (value.length === 1) return '0' + value; + if (value.length === 1) { return '0' + value; } return value ; } -} \ No newline at end of file +} diff --git a/src/app/providers/support-data.ts b/src/app/providers/support-data.ts index a0e27ce5f..ec7660b08 100644 --- a/src/app/providers/support-data.ts +++ b/src/app/providers/support-data.ts @@ -48,7 +48,7 @@ export class SupportData { userId: id, support: message }; - this.supportsCollection.add(support); + this.supportsCollection.add(support); }); } -} \ No newline at end of file +} diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 868e3135d..501383f41 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -70,14 +70,6 @@ export class UserData { }); } - // signup(user: UserOptions): Promise { - // console.log(user); - // return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { - // this.setUsername(user.username); - // return this.events.publish('user:signup'); - // }); - // } - logout(): Promise { return this.storage.remove(this.HAS_LOGGED_IN).then(() => { return this.storage.remove('user'); @@ -90,6 +82,21 @@ export class UserData { return this.storage.set('user', user); } + updateUsername(username: string) { + this.storage.get('user') + .then((user) => { + const id = user.id ; + delete(user.id); + user.username = username; + this.userDoc = this.afs.doc(`users/${id}`); + this.userDoc.update(user) + .then(() => { + user.id = id; + this.storage.set('user', user); + }); + }) + } + setUsername(username: string): Promise { console.log('need to fix'); return this.storage.set('username', username); From 58702601db6cae8a36f62fc2b2f6abc83034dddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 14:22:22 -0500 Subject: [PATCH 05/44] update 'change username' of the account mode --- src/app/pages/account/account.ts | 6 +++--- src/app/providers/user-data.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 4a1f30fc0..939939492 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -43,12 +43,12 @@ export class AccountPage implements AfterViewInit { text: 'Ok', handler: (data: any) => { if (this.isNameExist(data.username)) { - alert(data.username + ' is used already. Try another.') + alert(data.username + ' is used already. Try another.'); } else { this.userData.updateUsername(data.username); this.username = data.username; this.succeed = true; - this.jobDescription = "User's name is changed." + this.jobDescription = 'User"s name is changed.'; } } } @@ -74,7 +74,7 @@ export class AccountPage implements AfterViewInit { getUsers() { this.userData.getUsers().subscribe( users => { this.users = users; } - ) + ); } isNameExist(name: string) { diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 501383f41..896956168 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -94,7 +94,7 @@ export class UserData { user.id = id; this.storage.set('user', user); }); - }) + }); } setUsername(username: string): Promise { From 34e81e1d397c895b5180927a56bd091fea878fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 14:39:03 -0500 Subject: [PATCH 06/44] change a model name: UserOptions to User --- src/app/models.ts | 2 +- src/app/pages/account/account.ts | 4 ++-- src/app/pages/login/login.ts | 6 +++--- src/app/pages/signup/signup.ts | 8 ++++---- src/app/providers/user-data.ts | 20 ++++++++++---------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/app/models.ts b/src/app/models.ts index b40175b6e..26b691ed5 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -41,7 +41,7 @@ export interface Map { center?: boolean; } -export interface UserOptions { +export interface User { id?: string; username: string; password: string; diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 939939492..ff7f4986e 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -3,7 +3,7 @@ import { Router } from '@angular/router'; import { AlertController } from '@ionic/angular'; import { UserData } from '../../providers/user-data'; -import { UserOptions } from '../../models'; +import { User } from '../../models'; @Component({ selector: 'page-account', @@ -12,7 +12,7 @@ import { UserOptions } from '../../models'; encapsulation: ViewEncapsulation.None }) export class AccountPage implements AfterViewInit { - users: UserOptions[]; + users: User[]; username: string; succeed: boolean; jobDescription: string; diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 94977365d..85fa691a2 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -3,7 +3,7 @@ import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; -import { UserOptions } from '../../models'; +import { User } from '../../models'; @Component({ selector: 'page-login', @@ -14,7 +14,7 @@ import { UserOptions } from '../../models'; export class LoginPage implements OnInit { username: ''; password: '' ; - users: UserOptions[]; + users: User[]; constructor(public userData: UserData, public router: Router, @@ -22,7 +22,7 @@ export class LoginPage implements OnInit { ngOnInit() { this.userService.getUsers().subscribe( - (data: UserOptions[]) => { this.users = data; } + (data: User[]) => { this.users = data; } ); } diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 374f15347..9c2284dfe 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -3,7 +3,7 @@ import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; -import { UserOptions } from '../../models'; +import { User } from '../../models'; @Component({ selector: 'page-signup', @@ -12,8 +12,8 @@ import { UserOptions } from '../../models'; encapsulation: ViewEncapsulation.None }) export class SignupPage implements OnInit { - users: UserOptions[]; - signup: UserOptions = { + users: User[]; + signup: User = { username: '', password: '', email: '', favorites: [] }; confirmPassword = ''; @@ -25,7 +25,7 @@ export class SignupPage implements OnInit { ngOnInit() { this.userService.getUsers().subscribe( - (data: UserOptions[]) => { this.users = data; } + (data: User[]) => { this.users = data; } ); } diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 896956168..1b071e684 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -7,16 +7,16 @@ import { AngularFirestore, import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { UserOptions } from '../models'; +import { User } from '../models'; @Injectable({ providedIn: 'root' }) export class UserData { - usersCollection: AngularFirestoreCollection ; - userDoc: AngularFirestoreDocument ; - users: Observable ; - user: Observable ; + usersCollection: AngularFirestoreCollection ; + userDoc: AngularFirestoreDocument ; + users: Observable ; + user: Observable ; _favorites: string[] = []; HAS_LOGGED_IN = 'hasLoggedIn'; HAS_SEEN_TUTORIAL = 'hasSeenTutorial'; @@ -28,11 +28,11 @@ export class UserData { 'users', ref => ref.orderBy('username', 'asc')); } - getUsers(): Observable { + getUsers(): Observable { this.users = this.usersCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as UserOptions; + const data = action.payload.doc.data() as User; data.id = action.payload.doc.id; return data; }); @@ -40,7 +40,7 @@ export class UserData { return this.users; } - signup(user: UserOptions) { + signup(user: User) { this.usersCollection.add(user) .then(res => { user.id = res.id; @@ -63,7 +63,7 @@ export class UserData { } } - login(user: UserOptions): Promise { + login(user: User): Promise { return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { this.setUser(user); return this.events.publish('user:login'); @@ -78,7 +78,7 @@ export class UserData { }); } - setUser(user: UserOptions): Promise { + setUser(user: User): Promise { return this.storage.set('user', user); } From c042a3e786c1851e11cdee89c16b185539dda16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 15:56:33 -0500 Subject: [PATCH 07/44] update account.ts: add changeEmail(), user-data.ts: updateUsername to updateUser --- src/app/pages/account/account.html | 5 ++- src/app/pages/account/account.ts | 72 +++++++++++++++++++++--------- src/app/providers/user-data.ts | 56 ++++++++++++----------- 3 files changed, 82 insertions(+), 51 deletions(-) diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index 3ed80ecb2..f02b75548 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -8,13 +8,14 @@ -
+
avatar -

{{username}}

+

{{user.username}}

Update Picture Change Username + Change Email Change Password Support Logout diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index ff7f4986e..2ef2a7b52 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -13,7 +13,7 @@ import { User } from '../../models'; }) export class AccountPage implements AfterViewInit { users: User[]; - username: string; + user: User; succeed: boolean; jobDescription: string; @@ -22,8 +22,12 @@ export class AccountPage implements AfterViewInit { public userData: UserData) {} ngAfterViewInit() { - this.getUsers(); - this.getUsername(); + this.userData.getUsers().subscribe( + users => this.users = users + ); + this.userData.getUser().then( + user => this.user = user + ); } updatePicture() { @@ -42,13 +46,13 @@ export class AccountPage implements AfterViewInit { { text: 'Ok', handler: (data: any) => { - if (this.isNameExist(data.username)) { - alert(data.username + ' is used already. Try another.'); + if (this.isTheValueUsed(data.username)) { + alert(data.username + ' was used already. Try another.'); } else { - this.userData.updateUsername(data.username); - this.username = data.username; + this.user.username = data.username; + this.userData.updateUser(this.user); this.succeed = true; - this.jobDescription = 'User"s name is changed.'; + this.jobDescription = 'Username has been changed.'; } } } @@ -57,7 +61,7 @@ export class AccountPage implements AfterViewInit { { type: 'text', name: 'username', - value: this.username, + value: this.user.username, placeholder: 'new username' } ] @@ -65,25 +69,49 @@ export class AccountPage implements AfterViewInit { await changeForm.present(); } - getUsername() { - this.userData.getUsername().then((username) => { - this.username = username; + async changeEmail() { + this.succeed = false; + const changeForm = await this.alertCtrl.create({ + header: 'Change Email', + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + if (this.isTheValueUsed(data.email)) { + alert(data.email + ' was used already. Try another.'); + } else { + this.user.email = data.email; + this.userData.updateUser(this.user); + this.succeed = true; + this.jobDescription = 'Email has been changed.'; + } + } + } + ], + inputs: [ + { + type: 'text', + name: 'email', + value: this.user.email, + placeholder: 'new email' + } + ] }); + await changeForm.present(); } - getUsers() { - this.userData.getUsers().subscribe( - users => { this.users = users; } - ); + changePassword() { + console.log('Clicked to change password'); } - isNameExist(name: string) { + isTheValueUsed(value: string) { + if (value.indexOf('@') < 0) { + return this.users.find( + user => user.username.toLowerCase() === value.toLowerCase()); + } return this.users.find( - user => user.username.toLowerCase() === name.toLowerCase()); - } - - changePassword() { - console.log('Clicked to change password'); + user => user.email.toLowerCase() === value.toLowerCase()); } logout() { diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 1b071e684..82134fac6 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -82,47 +82,49 @@ export class UserData { return this.storage.set('user', user); } - updateUsername(username: string) { - this.storage.get('user') - .then((user) => { - const id = user.id ; - delete(user.id); - user.username = username; - this.userDoc = this.afs.doc(`users/${id}`); - this.userDoc.update(user) - .then(() => { - user.id = id; - this.storage.set('user', user); - }); + updateUser(user: User) { + const id = user.id; + delete(user.id); + this.userDoc = this.afs.doc(`users/${id}`); + this.userDoc.update(user) + .then(() => { + user.id = id; + this.storage.set('user', user); }); } - setUsername(username: string): Promise { - console.log('need to fix'); - return this.storage.set('username', username); + // updateUsername(username: string) { + // this.storage.get('user') + // .then((user) => { + // const id = user.id ; + // delete(user.id); + // user.username = username; + // this.userDoc = this.afs.doc(`users/${id}`); + // this.userDoc.update(user) + // .then(() => { + // user.id = id; + // this.storage.set('user', user); + // }); + // }); + // } + + getUser(): Promise { + return this.storage.get('user').then(user => user); } getUsername(): Promise { - return this.storage.get('user').then((value) => { - return value.username; - }); + return this.storage.get('user').then(value => value.username); } getUserId(): Promise { - return this.storage.get('user').then((value) => { - return value.id; - }); + return this.storage.get('user').then(value => value.id); } isLoggedIn(): Promise { - return this.storage.get(this.HAS_LOGGED_IN).then((value) => { - return value === true; - }); + return this.storage.get(this.HAS_LOGGED_IN).then(value => value); } checkHasSeenTutorial(): Promise { - return this.storage.get(this.HAS_SEEN_TUTORIAL).then((value) => { - return value; - }); + return this.storage.get(this.HAS_SEEN_TUTORIAL).then(value => value); } } From 13b3de5cbca68ae0ff947342af361da2a1f5934f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 19 Dec 2018 16:47:52 -0500 Subject: [PATCH 08/44] add change password mode to account.ts --- src/app/pages/account/account.ts | 47 ++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 2ef2a7b52..3ca9922fc 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -91,7 +91,7 @@ export class AccountPage implements AfterViewInit { ], inputs: [ { - type: 'text', + type: 'email', name: 'email', value: this.user.email, placeholder: 'new email' @@ -101,8 +101,49 @@ export class AccountPage implements AfterViewInit { await changeForm.present(); } - changePassword() { - console.log('Clicked to change password'); + async changePassword() { + this.succeed = false; + const changeForm = await this.alertCtrl.create({ + header: 'Change Password', + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + if (this.user.password !== data.currentPW) { + alert('Current password does not match your password.'); + } else if (data.newPW.length < 4) { + alert('Password should be more than 3 characters.'); + } else if (data.newPW !== data.confirmPW) { + alert('New password does not match Confirm password.'); + } else { + this.user.password = data.newPW; + this.userData.updateUser(this.user); + this.succeed = true; + this.jobDescription = 'Password has been changed.'; + } + } + } + ], + inputs: [ + { + type: 'password', + name: 'newPW', + placeholder: 'new password' + }, + { + type: 'password', + name: 'confirmPW', + placeholder: 'confirm password' + }, + { + type: 'password', + name: 'currentPW', + placeholder: 'current password' + } + ] + }); + await changeForm.present(); } isTheValueUsed(value: string) { From 6e139521e70fee0566a294970c2ac19e85e2f347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Thu, 20 Dec 2018 13:39:55 -0500 Subject: [PATCH 09/44] create more providers and update speaker-list, session-detail connecting firebase --- src/app/pages/account/account.ts | 14 ++-- src/app/pages/login/login.ts | 4 +- .../pages/session-detail/session-detail.ts | 59 ++++++++------- src/app/pages/signup/signup.ts | 7 +- src/app/pages/speaker-list/speaker-list.ts | 72 ++++++++++++++++--- src/app/providers/conference-data.ts | 6 +- src/app/providers/function-data.ts | 31 ++++++-- src/app/providers/session-data.ts | 62 ++++++++++++++++ src/app/providers/speaker-data.ts | 60 ++++++++++++++++ src/app/providers/support-data.ts | 8 +-- 10 files changed, 265 insertions(+), 58 deletions(-) create mode 100644 src/app/providers/session-data.ts create mode 100644 src/app/providers/speaker-data.ts diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 3ca9922fc..25cb408a1 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -19,13 +19,13 @@ export class AccountPage implements AfterViewInit { constructor(public alertCtrl: AlertController, public router: Router, - public userData: UserData) {} + public userProvider: UserData) {} ngAfterViewInit() { - this.userData.getUsers().subscribe( + this.userProvider.getUsers().subscribe( users => this.users = users ); - this.userData.getUser().then( + this.userProvider.getUser().then( user => this.user = user ); } @@ -50,7 +50,7 @@ export class AccountPage implements AfterViewInit { alert(data.username + ' was used already. Try another.'); } else { this.user.username = data.username; - this.userData.updateUser(this.user); + this.userProvider.updateUser(this.user); this.succeed = true; this.jobDescription = 'Username has been changed.'; } @@ -82,7 +82,7 @@ export class AccountPage implements AfterViewInit { alert(data.email + ' was used already. Try another.'); } else { this.user.email = data.email; - this.userData.updateUser(this.user); + this.userProvider.updateUser(this.user); this.succeed = true; this.jobDescription = 'Email has been changed.'; } @@ -118,7 +118,7 @@ export class AccountPage implements AfterViewInit { alert('New password does not match Confirm password.'); } else { this.user.password = data.newPW; - this.userData.updateUser(this.user); + this.userProvider.updateUser(this.user); this.succeed = true; this.jobDescription = 'Password has been changed.'; } @@ -156,7 +156,7 @@ export class AccountPage implements AfterViewInit { } logout() { - this.userData.logout(); + this.userProvider.logout(); this.router.navigateByUrl('/login'); } diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 85fa691a2..998e8b127 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -18,10 +18,10 @@ export class LoginPage implements OnInit { constructor(public userData: UserData, public router: Router, - private userService: UserData) { } + private userProvider: UserData) { } ngOnInit() { - this.userService.getUsers().subscribe( + this.userProvider.getUsers().subscribe( (data: User[]) => { this.users = data; } ); } diff --git a/src/app/pages/session-detail/session-detail.ts b/src/app/pages/session-detail/session-detail.ts index 333cf1148..c4fb44f89 100644 --- a/src/app/pages/session-detail/session-detail.ts +++ b/src/app/pages/session-detail/session-detail.ts @@ -1,8 +1,9 @@ import { Component } from '@angular/core'; - -import { ConferenceData } from '../../providers/conference-data'; import { ActivatedRoute } from '@angular/router'; + import { UserData } from '../../providers/user-data'; +import { SessionData } from '../../providers/session-data'; +import { Session } from '../../models'; @Component({ selector: 'page-session-detail', @@ -10,10 +11,10 @@ import { UserData } from '../../providers/user-data'; templateUrl: 'session-detail.html' }) export class SessionDetailPage { - session: any; + session: Session; isFavorite = false; constructor( - private dataProvider: ConferenceData, + private sessionProvider: SessionData, private userProvider: UserData, private route: ActivatedRoute ) {} @@ -22,7 +23,6 @@ export class SessionDetailPage { console.log('Clicked', item); } - toggleFavorite() { if (this.userProvider.hasFavorite(this.session.name)) { this.userProvider.removeFavorite(this.session.name); @@ -32,27 +32,34 @@ export class SessionDetailPage { this.isFavorite = true; } } + ionViewWillEnter() { - this.dataProvider.load().subscribe((data: any) => { - if ( - data && - data.schedule && - data.schedule[0] && - data.schedule[0].groups - ) { - const sessionId = this.route.snapshot.paramMap.get('sessionId'); - for (const group of data.schedule[0].groups) { - if (group && group.sessions) { - for (const session of group.sessions) { - if (session && session.id === sessionId) { - this.session = session; - this.isFavorite = this.userProvider.hasFavorite(this.session.name); - break; - } - } - } - } - } - }); + const id = this.route.snapshot.paramMap.get('sessionId'); + this.sessionProvider.getSession(id) + .then( data => { this.session = data; } + ); + // const id = this.route.snapshot.paramMap.get('sessionId'); + // this.session = this.sessionProvider.getSession(id); + // this.dataProvider.load().subscribe((data: any) => { + // if ( + // data && + // data.schedule && + // data.schedule[0] && + // data.schedule[0].groups + // ) { + // const sessionId = this.route.snapshot.paramMap.get('sessionId'); + // for (const group of data.schedule[0].groups) { + // if (group && group.sessions) { + // for (const session of group.sessions) { + // if (session && session.id === sessionId) { + // this.session = session; + // this.isFavorite = this.userProvider.hasFavorite(this.session.name); + // break; + // } + // } + // } + // } + // } + // }); } } diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 9c2284dfe..491158b24 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -20,11 +20,10 @@ export class SignupPage implements OnInit { submitted = false; constructor(public router: Router, - public userData: UserData, - private userService: UserData) {} + public userProvider: UserData) {} ngOnInit() { - this.userService.getUsers().subscribe( + this.userProvider.getUsers().subscribe( (data: User[]) => { this.users = data; } ); } @@ -37,7 +36,7 @@ export class SignupPage implements OnInit { } else if (this.isEmailUsed(this.signup.email)) { alert('Email is already taken.'); } else { - this.userData.signup(this.signup); + this.userProvider.signup(this.signup); this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } } diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index 1b99c4a32..626e15c71 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -1,9 +1,10 @@ -import { Component, ViewEncapsulation } from '@angular/core'; +import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; -import { ActionSheetController } from '@ionic/angular'; +import { ActionSheetController, AlertController } from '@ionic/angular'; -import { ConferenceData } from '../../providers/conference-data'; +import { Speaker } from '../../models'; +import { SpeakerData } from '../../providers/speaker-data'; @Component({ selector: 'page-speaker-list', @@ -11,20 +12,27 @@ import { ConferenceData } from '../../providers/conference-data'; styleUrls: ['./speaker-list.scss'], encapsulation: ViewEncapsulation.None }) -export class SpeakerListPage { - speakers: any[] = []; +export class SpeakerListPage implements OnInit { + speakers: Speaker[]; constructor( public actionSheetCtrl: ActionSheetController, - public confData: ConferenceData, + public alertCtrl: AlertController, + private speakerProvider: SpeakerData, public inAppBrowser: InAppBrowser, public router: Router ) {} + ngOnInit() { + this.speakerProvider.getSpeakers().subscribe( + speakers => { this.speakers = speakers; } + ); + } + ionViewDidEnter() { - this.confData.getSpeakers().subscribe((speakers: any[]) => { - this.speakers = speakers; - }); + // this.dataProvider.getSpeakers().subscribe((speakers: any[]) => { + // this.speakers = speakers; + // }); } goToSpeakerTwitter(speaker: any) { @@ -92,4 +100,50 @@ export class SpeakerListPage { await actionSheet.present(); } + + async addNewSpeaker() { + // this.succeed = false; + const changeForm = await this.alertCtrl.create({ + header: 'Change Password', + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + // if (this.user.password !== data.currentPW) { + // alert('Current password does not match your password.'); + // } else if (data.newPW.length < 4) { + // alert('Password should be more than 3 characters.'); + // } else if (data.newPW !== data.confirmPW) { + // alert('New password does not match Confirm password.'); + // } else { + // this.user.password = data.newPW; + // this.userData.updateUser(this.user); + // this.succeed = true; + // this.jobDescription = 'Password has been changed.'; + // } + } + } + ], + inputs: [ + { + type: 'password', + name: 'newPW', + placeholder: 'new password' + }, + { + type: 'password', + name: 'confirmPW', + placeholder: 'confirm password' + }, + { + type: 'password', + name: 'currentPW', + placeholder: 'current password' + } + ] + }); + await changeForm.present(); + } + } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 9891292d4..cc0dce599 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -2,7 +2,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { of } from 'rxjs'; import { map } from 'rxjs/operators'; - import { UserData } from './user-data'; @Injectable({ @@ -11,7 +10,10 @@ import { UserData } from './user-data'; export class ConferenceData { data: any; - constructor(public http: HttpClient, public user: UserData) {} + constructor( + public http: HttpClient, + public user: UserData + ) {} load(): any { if (this.data) { diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index c3334c8cf..dc8816c89 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -5,7 +5,7 @@ import { Injectable } from '@angular/core'; }) export class FunctionlData { - getDataFormat(date: Date) { + getDateFormat(date: Date) { if (!date) { date = new Date(); } @@ -15,8 +15,31 @@ export class FunctionlData { this.reform2digits(dateArray[1]); } - reform2digits(value) { - if (value.length === 1) { return '0' + value; } - return value ; + getAmPmTimeFormat(time: string): string { + if (!time) { return '00:00 am' ; } + let t = +time.split(':')[0]; + let m = time.split(':')[1]; + if (t > 11) { + m = m + ' pm'; + t = (t === 12) ? t : t - 12 ; + } else { + m = m + ' am'; + } + return this.reform2digits(t) + ':' + m ; + } + + get24HoursFormat(time: string): string { + if (!time) { return '' ; } + const data = time.split(' '); + let t = +data[0].split(':')[0]; + const m = data[0].split(':')[1]; + if (data[1] === 'pm' && t < 12) { t = t + 12 ; } + const realTime = (t < 10 ? '0' : '') + t; + return realTime + ':' + m ; + } + + reform2digits(value): string { + value = +value; + return ((value < 10) ? '0' : '') + value ; } } diff --git a/src/app/providers/session-data.ts b/src/app/providers/session-data.ts new file mode 100644 index 000000000..1d1cef267 --- /dev/null +++ b/src/app/providers/session-data.ts @@ -0,0 +1,62 @@ +import { Injectable } from '@angular/core'; +import { AngularFirestore, + AngularFirestoreCollection, + AngularFirestoreDocument } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { Session, Speaker } from '../models'; + +@Injectable({ + providedIn: 'root' +}) +export class SessionData { + sessionsCollection: AngularFirestoreCollection ; + sessionDoc: AngularFirestoreDocument ; + sessions: Observable ; + session: Observable ; + id: string; + + constructor(private afs: AngularFirestore) { + this.sessionsCollection = this.afs.collection( + 'sessions', ref => ref.orderBy('date', 'asc')); + } + + getSessions(): Observable { + this.sessions = this.sessionsCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Session; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.sessions ; + } + + addNewSession(session: Session) { + return this.sessionsCollection.add(session) + .then(docRef => { + const id = docRef.id; + return id; + }); + } + + updateSession(id: string, session: Session) { + this.sessionDoc = this.afs.doc(`sessions/${id}`); + this.sessionDoc.update(session); + } + + deleteSession(session: Session) { + this.sessionDoc = this.afs.doc(`sessions/${session.id}`); + this.sessionDoc.delete(); + } + + getSession(id: string) { + return this.sessionsCollection.doc(id).ref.get() + .then(doc => { + const res = doc.data() as Session ; + return res; + }); + } +} diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts new file mode 100644 index 000000000..9e09d6a48 --- /dev/null +++ b/src/app/providers/speaker-data.ts @@ -0,0 +1,60 @@ +import { Injectable } from '@angular/core'; +import { AngularFirestore, + AngularFirestoreCollection, + AngularFirestoreDocument } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { Speaker } from '../models'; + +@Injectable({ + providedIn: 'root' +}) +export class SpeakerData { + speakersCollection: AngularFirestoreCollection ; + speakerDoc: AngularFirestoreDocument ; + speakers: Observable ; + speaker: Observable ; + + constructor(private afs: AngularFirestore) { + this.speakersCollection = this.afs.collection( + 'speakers', ref => ref.orderBy('name', 'asc')); + } + + getSpeakers(): Observable { + this.speakers = this.speakersCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Speaker; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.speakers ; + } + + getSpeaker(name: string): Speaker { + let speaker; + this.getSpeakers().subscribe( + (data: Speaker[]) => { + speaker = data.find(spk => spk.name === name); + }); + return speaker; + } + + addNewSpeaker(speaker: Speaker) { + this.speakersCollection.add(speaker) ; + } + + updateSpeaker(speaker: Speaker) { + this.speakerDoc = this.afs.doc(`speakers/${speaker.id}`); + delete(speaker.id); + this.speakerDoc.update(speaker); + } + + getSpeakerName(id: string) { + this.speakerDoc = this.afs.doc(`speakers/${id}`); + const name = this.speakerDoc.snapshotChanges.name; + return name; + } +} diff --git a/src/app/providers/support-data.ts b/src/app/providers/support-data.ts index ec7660b08..4168b2520 100644 --- a/src/app/providers/support-data.ts +++ b/src/app/providers/support-data.ts @@ -20,8 +20,8 @@ export class SupportData { support: Observable ; constructor(private afs: AngularFirestore, - private functionData: FunctionlData, - private userData: UserData, + private functionProvider: FunctionlData, + private userProvider: UserData, public events: Events) { this.supportsCollection = this.afs.collection( 'supports', ref => ref.orderBy('date', 'asc')); @@ -40,8 +40,8 @@ export class SupportData { } addSupport(message: string) { - const date = this.functionData.getDataFormat(null); - this.userData.getUserId() + const date = this.functionProvider.getDateFormat(null); + this.userProvider.getUserId() .then(id => { const support: Support = { date: date, From a57388b34bc613c2449b6ee4ea28b9840f3e2edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Thu, 20 Dec 2018 15:58:17 -0500 Subject: [PATCH 10/44] update speaker-detail.ts: add links and show all details of speaker. --- src/app/models.ts | 2 + src/app/pages/account/account.ts | 4 +- .../pages/session-detail/session-detail.html | 2 +- .../pages/speaker-detail/speaker-detail.html | 12 ++-- .../pages/speaker-detail/speaker-detail.ts | 48 ++++++++++----- src/app/pages/speaker-list/speaker-list.ts | 60 ++----------------- src/app/providers/speaker-data.ts | 29 ++++++--- 7 files changed, 72 insertions(+), 85 deletions(-) diff --git a/src/app/models.ts b/src/app/models.ts index 26b691ed5..dfe2f276f 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -9,6 +9,8 @@ export interface Speaker { name: string; profilePic?: string; twitter?: string; + github?: string; + instagram?: string; about?: string; location?: string; email: string; diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 25cb408a1..0d7c8e685 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -4,6 +4,7 @@ import { AlertController } from '@ionic/angular'; import { UserData } from '../../providers/user-data'; import { User } from '../../models'; +import { SpeakerData } from '../../providers/speaker-data'; @Component({ selector: 'page-account', @@ -19,7 +20,8 @@ export class AccountPage implements AfterViewInit { constructor(public alertCtrl: AlertController, public router: Router, - public userProvider: UserData) {} + public userProvider: UserData, + public spkProvider: SpeakerData) {} ngAfterViewInit() { this.userProvider.getUsers().subscribe( diff --git a/src/app/pages/session-detail/session-detail.html b/src/app/pages/session-detail/session-detail.html index 7a40fe5c1..1eb28ebd6 100644 --- a/src/app/pages/session-detail/session-detail.html +++ b/src/app/pages/session-detail/session-detail.html @@ -1,7 +1,7 @@ - + {{session?.name}} diff --git a/src/app/pages/speaker-detail/speaker-detail.html b/src/app/pages/speaker-detail/speaker-detail.html index 6de184107..824af706f 100644 --- a/src/app/pages/speaker-detail/speaker-detail.html +++ b/src/app/pages/speaker-detail/speaker-detail.html @@ -1,7 +1,7 @@ - + {{speaker?.name}} @@ -12,16 +12,20 @@
- + - + - +

{{speaker?.about}}

+

{{speaker?.location}}

+

{{speaker?.email}}

+

{{speaker?.phone}}

+

Sessions involved: {{speaker?.sessions.length}}

diff --git a/src/app/pages/speaker-detail/speaker-detail.ts b/src/app/pages/speaker-detail/speaker-detail.ts index 63b6a47fb..29729b5d5 100644 --- a/src/app/pages/speaker-detail/speaker-detail.ts +++ b/src/app/pages/speaker-detail/speaker-detail.ts @@ -1,7 +1,9 @@ import { Component, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; -import { ConferenceData } from '../../providers/conference-data'; +import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; +import { SpeakerData } from '../../providers/speaker-data'; +import { Speaker } from '../../models'; @Component({ selector: 'page-speaker-detail', @@ -10,30 +12,44 @@ import { ConferenceData } from '../../providers/conference-data'; encapsulation: ViewEncapsulation.None }) export class SpeakerDetailPage { - speaker: any; + speaker: Speaker; constructor( - private dataProvider: ConferenceData, + private speakerProvider: SpeakerData, private router: Router, - private route: ActivatedRoute + private route: ActivatedRoute, + public inAppBrowser: InAppBrowser ) {} ionViewWillEnter() { - this.dataProvider.load().subscribe((data: any) => { - const speakerId = this.route.snapshot.paramMap.get('speakerId'); - if (data && data.speakers) { - for (const speaker of data.speakers) { - if (speaker && speaker.id === speakerId) { - this.speaker = speaker; - break; - } - } - } - }); - + const id = this.route.snapshot.paramMap.get('speakerId'); + this.speakerProvider.getSpeaker(id) + .then( data => { this.speaker = data; } + ); } goToSessionDetail(session: any) { this.router.navigateByUrl(`app/tabs/(schedule:session/${session.id})`); } + + goToSpeakerTwitter() { + this.inAppBrowser.create( + `https://twitter.com/${this.speaker.twitter}`, + '_blank' + ); + } + + goToSpeakergithub() { + this.inAppBrowser.create( + `https://github.com/${this.speaker.github}`, + '_blank' + ); + } + + goToSpeakerInstagram() { + this.inAppBrowser.create( + `https://instagram.com/${this.speaker.instagram}`, + '_blank' + ); + } } diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index 626e15c71..ae6b943ec 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -1,4 +1,4 @@ -import { Component, ViewEncapsulation, OnInit } from '@angular/core'; +import { Component, ViewEncapsulation } from '@angular/core'; import { Router } from '@angular/router'; import { InAppBrowser } from '@ionic-native/in-app-browser/ngx'; import { ActionSheetController, AlertController } from '@ionic/angular'; @@ -12,7 +12,7 @@ import { SpeakerData } from '../../providers/speaker-data'; styleUrls: ['./speaker-list.scss'], encapsulation: ViewEncapsulation.None }) -export class SpeakerListPage implements OnInit { +export class SpeakerListPage { speakers: Speaker[]; constructor( @@ -23,19 +23,13 @@ export class SpeakerListPage implements OnInit { public router: Router ) {} - ngOnInit() { + ionViewDidEnter() { this.speakerProvider.getSpeakers().subscribe( speakers => { this.speakers = speakers; } ); } - ionViewDidEnter() { - // this.dataProvider.getSpeakers().subscribe((speakers: any[]) => { - // this.speakers = speakers; - // }); - } - - goToSpeakerTwitter(speaker: any) { + goToSpeakerTwitter(speaker: Speaker) { this.inAppBrowser.create( `https://twitter.com/${speaker.twitter}`, '_blank' @@ -100,50 +94,4 @@ export class SpeakerListPage implements OnInit { await actionSheet.present(); } - - async addNewSpeaker() { - // this.succeed = false; - const changeForm = await this.alertCtrl.create({ - header: 'Change Password', - buttons: [ - 'Cancel', - { - text: 'Ok', - handler: (data: any) => { - // if (this.user.password !== data.currentPW) { - // alert('Current password does not match your password.'); - // } else if (data.newPW.length < 4) { - // alert('Password should be more than 3 characters.'); - // } else if (data.newPW !== data.confirmPW) { - // alert('New password does not match Confirm password.'); - // } else { - // this.user.password = data.newPW; - // this.userData.updateUser(this.user); - // this.succeed = true; - // this.jobDescription = 'Password has been changed.'; - // } - } - } - ], - inputs: [ - { - type: 'password', - name: 'newPW', - placeholder: 'new password' - }, - { - type: 'password', - name: 'confirmPW', - placeholder: 'confirm password' - }, - { - type: 'password', - name: 'currentPW', - placeholder: 'current password' - } - ] - }); - await changeForm.present(); - } - } diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts index 9e09d6a48..c6e71d6b7 100644 --- a/src/app/providers/speaker-data.ts +++ b/src/app/providers/speaker-data.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { Speaker } from '../models'; @@ -33,13 +33,12 @@ export class SpeakerData { return this.speakers ; } - getSpeaker(name: string): Speaker { - let speaker; - this.getSpeakers().subscribe( - (data: Speaker[]) => { - speaker = data.find(spk => spk.name === name); + getSpeaker(id: string) { + return this.speakersCollection.doc(id).ref.get() + .then(doc => { + const speaker = doc.data() as Speaker; + return speaker; }); - return speaker; } addNewSpeaker(speaker: Speaker) { @@ -57,4 +56,20 @@ export class SpeakerData { const name = this.speakerDoc.snapshotChanges.name; return name; } + + updateSpeakers() { + this.getSpeakers().subscribe( + (speakers: Speaker[]) => { + speakers.forEach( speaker => { + const id = speaker.id; + delete(speaker.id); + speaker.instagram = ''; + speaker.github = 'hogusong'; + if (!speaker.twitter) { speaker.twitter = 'YoungSongJS'; } + this.speakerDoc = this.afs.doc(`speakers/${id}`); + this.speakerDoc.update(speaker); + }); + } + ); + } } From be2f9c17c740b815a84696bbaf03bb1cd84bb616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Thu, 20 Dec 2018 21:39:21 -0500 Subject: [PATCH 11/44] update schedule-filter.ts: work by user's default setting and update user's data --- src/app/models.ts | 1 + src/app/pages/account/account.ts | 4 +-- .../schedule-filter/schedule-filter.html | 5 ++- .../pages/schedule-filter/schedule-filter.ts | 36 +++++++++---------- src/app/pages/signup/signup.ts | 19 ++++++++-- src/app/providers/conference-data.ts | 33 ++++++++++++----- src/app/providers/user-data.ts | 15 -------- 7 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/app/models.ts b/src/app/models.ts index dfe2f276f..a2d2691b0 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -49,6 +49,7 @@ export interface User { password: string; email: string; favorites: IdName[]; // session's id and name. + trackFilter: { name: string, isChecked: boolean }[]; } export interface Support { diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 0d7c8e685..25cb408a1 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -4,7 +4,6 @@ import { AlertController } from '@ionic/angular'; import { UserData } from '../../providers/user-data'; import { User } from '../../models'; -import { SpeakerData } from '../../providers/speaker-data'; @Component({ selector: 'page-account', @@ -20,8 +19,7 @@ export class AccountPage implements AfterViewInit { constructor(public alertCtrl: AlertController, public router: Router, - public userProvider: UserData, - public spkProvider: SpeakerData) {} + public userProvider: UserData) {} ngAfterViewInit() { this.userProvider.getUsers().subscribe( diff --git a/src/app/pages/schedule-filter/schedule-filter.html b/src/app/pages/schedule-filter/schedule-filter.html index ffafd4cd0..4db1879e2 100644 --- a/src/app/pages/schedule-filter/schedule-filter.html +++ b/src/app/pages/schedule-filter/schedule-filter.html @@ -19,12 +19,11 @@ Tracks - + {{track.name}} - + - diff --git a/src/app/pages/schedule-filter/schedule-filter.ts b/src/app/pages/schedule-filter/schedule-filter.ts index 56739e835..a2ed6d8e6 100644 --- a/src/app/pages/schedule-filter/schedule-filter.ts +++ b/src/app/pages/schedule-filter/schedule-filter.ts @@ -2,7 +2,8 @@ import { AfterViewInit, Component, ViewEncapsulation } from '@angular/core'; import { ModalController } from '@ionic/angular'; import { ConferenceData } from '../../providers/conference-data'; - +import { UserData } from '../../providers/user-data'; +import { User } from '../../models'; @Component({ selector: 'page-schedule-filter', @@ -11,43 +12,42 @@ import { ConferenceData } from '../../providers/conference-data'; encapsulation: ViewEncapsulation.None }) export class ScheduleFilterPage implements AfterViewInit { - - tracks: {name: string, isChecked: boolean}[] = []; + user: User; + trackFilter: { name: string, isChecked: boolean }[] = []; constructor( - public confData: ConferenceData, - public modalCtrl: ModalController + public dataProvider: ConferenceData, + public modalCtrl: ModalController, + public userProvider: UserData ) { } // TODO use the ionViewDidEnter event ngAfterViewInit() { - // passed in array of track names that should be excluded (unchecked) - const excludedTrackNames = []; // this.navParams.data.excludedTracks; - - this.confData.getTracks().subscribe((trackNames: string[]) => { - trackNames.forEach(trackName => { - this.tracks.push({ - name: trackName, - isChecked: (excludedTrackNames.indexOf(trackName) === -1) - }); - }); + this.userProvider.getUser().then(user => { + this.user = user; + this.trackFilter = user.trackFilter; }); } resetFilters() { // reset all of the toggles to be checked - this.tracks.forEach(track => { + this.trackFilter.forEach(track => { track.isChecked = true; }); } applyFilters() { + // update user's trackFilter + console.log(this.trackFilter); + this.user.trackFilter = this.trackFilter; + this.userProvider.updateUser(this.user); + // Pass back a new array of track names to exclude - const excludedTrackNames = this.tracks.filter(c => !c.isChecked).map(c => c.name); + const excludedTrackNames = this.trackFilter.filter(c => !c.isChecked).map(c => c.name); this.dismiss(excludedTrackNames); } - dismiss(data?: any) { + dismiss(data: any) { // using the injected ModalController this page // can "dismiss" itself and pass back data this.modalCtrl.dismiss(data); diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 491158b24..c33da1ade 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -3,7 +3,8 @@ import { NgForm } from '@angular/forms'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; -import { User } from '../../models'; +import { ConferenceData } from '../../providers/conference-data'; +import { User, Track } from '../../models'; @Component({ selector: 'page-signup', @@ -14,18 +15,23 @@ import { User } from '../../models'; export class SignupPage implements OnInit { users: User[]; signup: User = { - username: '', password: '', email: '', favorites: [] + username: '', password: '', email: '', favorites: [], trackFilter: [] }; + tracks: Track[]; confirmPassword = ''; submitted = false; constructor(public router: Router, - public userProvider: UserData) {} + public userProvider: UserData, + public dataProvider: ConferenceData) {} ngOnInit() { this.userProvider.getUsers().subscribe( (data: User[]) => { this.users = data; } ); + this.dataProvider.getTracks().subscribe( + (tracks: Track[]) => { this.tracks = tracks; } + ); } onSignup(form: NgForm) { @@ -36,12 +42,19 @@ export class SignupPage implements OnInit { } else if (this.isEmailUsed(this.signup.email)) { alert('Email is already taken.'); } else { + this.setTrackFilter() this.userProvider.signup(this.signup); this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } } } + setTrackFilter() { + this.tracks.forEach(track => { + this.signup.trackFilter.push({ name: track.name, isChecked: true }); + }); + } + isNameUsed(name) { return this.users.find(ur => ur.username.toLowerCase() === name.toLowerCase()); } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index cc0dce599..329b3bc4b 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -1,19 +1,30 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { of } from 'rxjs'; +import { AngularFirestore, + AngularFirestoreCollection, + AngularFirestoreDocument } from 'angularfire2/firestore'; +import { Observable, of } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; +import { Track } from '../models'; @Injectable({ providedIn: 'root' }) export class ConferenceData { + tracksCollection: AngularFirestoreCollection ; + trackDoc: AngularFirestoreDocument ; + tracks: Observable ; + track: Observable ; data: any; constructor( public http: HttpClient, - public user: UserData - ) {} + public user: UserData, + private afs: AngularFirestore) { + this.tracksCollection = this.afs.collection( + 'tracks', ref => ref.orderBy('name', 'asc')); + } load(): any { if (this.data) { @@ -155,12 +166,16 @@ export class ConferenceData { ); } - getTracks() { - return this.load().pipe( - map((data: any) => { - return data.tracks.sort(); - }) - ); + getTracks(): Observable { + this.tracks = this.tracksCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Track; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.tracks ; } getMap() { diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 82134fac6..97e05f8ad 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -93,21 +93,6 @@ export class UserData { }); } - // updateUsername(username: string) { - // this.storage.get('user') - // .then((user) => { - // const id = user.id ; - // delete(user.id); - // user.username = username; - // this.userDoc = this.afs.doc(`users/${id}`); - // this.userDoc.update(user) - // .then(() => { - // user.id = id; - // this.storage.set('user', user); - // }); - // }); - // } - getUser(): Promise { return this.storage.get('user').then(user => user); } From 1bfb8a52ae1a64d66a0ec6c7d1abb6f31667371f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 21 Dec 2018 15:00:38 -0500 Subject: [PATCH 12/44] add 'trackFilter' to user and modify 'signup.ts' to update user file --- src/app/pages/schedule-filter/schedule-filter.ts | 1 - src/app/pages/signup/signup.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/pages/schedule-filter/schedule-filter.ts b/src/app/pages/schedule-filter/schedule-filter.ts index a2ed6d8e6..e2bc7692d 100644 --- a/src/app/pages/schedule-filter/schedule-filter.ts +++ b/src/app/pages/schedule-filter/schedule-filter.ts @@ -38,7 +38,6 @@ export class ScheduleFilterPage implements AfterViewInit { applyFilters() { // update user's trackFilter - console.log(this.trackFilter); this.user.trackFilter = this.trackFilter; this.userProvider.updateUser(this.user); diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index c33da1ade..2a9c17e17 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -42,7 +42,7 @@ export class SignupPage implements OnInit { } else if (this.isEmailUsed(this.signup.email)) { alert('Email is already taken.'); } else { - this.setTrackFilter() + this.setTrackFilter(); this.userProvider.signup(this.signup); this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } From 66b1677ed0ecdfe358c23d1a138a1689fcb5d701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 21 Dec 2018 20:10:50 -0500 Subject: [PATCH 13/44] add 'Select one track mode' to list up the schedule by the selected track. --- .../pages/schedule-track/schedule-track.html | 25 +++++++++ .../pages/schedule-track/schedule-track.scss | 0 .../pages/schedule-track/schedule-track.ts | 41 +++++++++++++++ src/app/pages/schedule/schedule.html | 5 +- src/app/pages/schedule/schedule.module.ts | 7 ++- src/app/pages/schedule/schedule.ts | 52 ++++++++++++++++--- 6 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 src/app/pages/schedule-track/schedule-track.html create mode 100644 src/app/pages/schedule-track/schedule-track.scss create mode 100644 src/app/pages/schedule-track/schedule-track.ts diff --git a/src/app/pages/schedule-track/schedule-track.html b/src/app/pages/schedule-track/schedule-track.html new file mode 100644 index 000000000..a019a52c7 --- /dev/null +++ b/src/app/pages/schedule-track/schedule-track.html @@ -0,0 +1,25 @@ + + + + One Track Session + + + + Cancel + + + + + + + + + Tracks + + + + {{track.name}} + + + + diff --git a/src/app/pages/schedule-track/schedule-track.scss b/src/app/pages/schedule-track/schedule-track.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/pages/schedule-track/schedule-track.ts b/src/app/pages/schedule-track/schedule-track.ts new file mode 100644 index 000000000..f985cb83d --- /dev/null +++ b/src/app/pages/schedule-track/schedule-track.ts @@ -0,0 +1,41 @@ +import { AfterViewInit, Component, ViewEncapsulation } from '@angular/core'; +import { ModalController } from '@ionic/angular'; + +import { ConferenceData } from '../../providers/conference-data'; +import { UserData } from '../../providers/user-data'; +import { Track } from '../../models'; + +@Component({ + selector: 'page-schedule-track', + templateUrl: './schedule-track.html', + styleUrls: ['./schedule-track.scss'], + encapsulation: ViewEncapsulation.None + +}) +export class ScheduleTrackPage implements AfterViewInit { + tracks: Track[] = []; + + constructor(private dataProvider: ConferenceData, + public modalCtrl: ModalController) { } + + ngAfterViewInit() { + this.dataProvider.getTracks().subscribe( + (tracks: Track[]) => { this.tracks = tracks; } + ); + } + + applyTrack(name: string) { + // Pass back a new array of track names to exclude + const excludedTracks = []; + this.tracks.forEach( + (track) => { if (track.name !== name ) { excludedTracks.push(track.name); } + }); + this.dismiss(excludedTracks); + } + + dismiss(data: any) { + // using the injected ModalController this page + // can "dismiss" itself and pass back data + this.modalCtrl.dismiss(data); + } +} diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index 509d31258..76cf78e5d 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -4,10 +4,13 @@ - + All + + Track + Favorites diff --git a/src/app/pages/schedule/schedule.module.ts b/src/app/pages/schedule/schedule.module.ts index 77ba69818..90f545e15 100644 --- a/src/app/pages/schedule/schedule.module.ts +++ b/src/app/pages/schedule/schedule.module.ts @@ -5,6 +5,7 @@ import { IonicModule } from '@ionic/angular'; import { SchedulePage } from './schedule'; import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; +import { ScheduleTrackPage } from '../schedule-track/schedule-track'; import { SchedulePageRoutingModule } from './schedule-routing.module'; @NgModule({ @@ -16,10 +17,12 @@ import { SchedulePageRoutingModule } from './schedule-routing.module'; ], declarations: [ SchedulePage, - ScheduleFilterPage + ScheduleFilterPage, + ScheduleTrackPage ], entryComponents: [ - ScheduleFilterPage + ScheduleFilterPage, + ScheduleTrackPage ] }) export class ScheduleModule { } diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 2d2d53cee..57ffbd56d 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -3,8 +3,10 @@ import { Router } from '@angular/router'; import { AlertController, List, LoadingController, ModalController, ToastController } from '@ionic/angular'; import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; +import { ScheduleTrackPage } from '../schedule-track/schedule-track'; import { ConferenceData } from '../../providers/conference-data'; import { UserData } from '../../providers/user-data'; +import { User } from '../../models'; @Component({ selector: 'page-schedule', @@ -16,9 +18,10 @@ export class SchedulePage { // Gets a reference to the list element @ViewChild('scheduleList') scheduleList: List; + user: User; dayIndex = 0; queryText = ''; - segment = 'all'; + segment = ''; excludeTracks: any = []; shownSessions: any = []; groups: any = []; @@ -26,16 +29,22 @@ export class SchedulePage { constructor( public alertCtrl: AlertController, - public confData: ConferenceData, + public dataProvider: ConferenceData, public loadingCtrl: LoadingController, public modalCtrl: ModalController, public router: Router, public toastCtrl: ToastController, - public user: UserData + public userProvider: UserData ) { } ionViewWillEnter() { // this.app.setTitle('Schedule'); + this.userProvider.getUser().then(user => { + this.user = user; + this.user.trackFilter.forEach(track => { + if (track.isChecked) { this.excludeTracks.push(track.name); } + }); + }); this.updateSchedule(); } @@ -45,12 +54,38 @@ export class SchedulePage { this.scheduleList.closeSlidingItems(); } - this.confData.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { + this.dataProvider.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { this.shownSessions = data.shownSessions; this.groups = data.groups; }); } + processBySegment() { + if (this.segment === 'one') { + this.chooseTrack(); + } else if (this.segment === 'all') { + this.excludeTracks = []; + this.updateSchedule(); + } + } + + async chooseTrack() { + const modal = await this.modalCtrl.create({ + component: ScheduleTrackPage, + componentProps: { excludedTracks: this.excludeTracks } + }); + await modal.present(); + + const { data } = await modal.onWillDismiss(); + if (data) { + this.excludeTracks = data; + this.segment = 'user'; + this.updateSchedule(); + } else { + this.segment = ''; + } + } + async presentFilter() { const modal = await this.modalCtrl.create({ component: ScheduleFilterPage, @@ -61,6 +96,7 @@ export class SchedulePage { const { data } = await modal.onWillDismiss(); if (data) { this.excludeTracks = data; + this.segment = 'user'; this.updateSchedule(); } } @@ -72,13 +108,13 @@ export class SchedulePage { } async addFavorite(slidingItem: HTMLIonItemSlidingElement, sessionData: any) { - if (this.user.hasFavorite(sessionData.name)) { + if (this.userProvider.hasFavorite(sessionData.name)) { // woops, they already favorited it! What shall we do!? // prompt them to remove it this.removeFavorite(slidingItem, sessionData, 'Favorite already added'); } else { // remember this session as a user favorite - this.user.addFavorite(sessionData.name); + this.userProvider.addFavorite(sessionData.name); // create an alert instance const alert = await this.alertCtrl.create({ @@ -114,7 +150,7 @@ export class SchedulePage { text: 'Remove', handler: () => { // they want to remove this session from their favorites - this.user.removeFavorite(sessionData.name); + this.userProvider.removeFavorite(sessionData.name); this.updateSchedule(); // close the sliding item and hide the option buttons @@ -138,7 +174,7 @@ export class SchedulePage { } /*doRefresh(refresher: Refresher) { - this.confData.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { + this.dataProvider.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { this.shownSessions = data.shownSessions; this.groups = data.groups; From 515cf8aa8a9b76edefa5b8a6441385f038208376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sat, 22 Dec 2018 21:17:38 -0500 Subject: [PATCH 14/44] update 'schedule mode': get main sessions from firebase and manipulate them --- src/app/models.ts | 4 +- src/app/pages/schedule/schedule.html | 54 +++++---- src/app/pages/schedule/schedule.ts | 108 +++++++++++++++-- src/app/providers/conference-data.ts | 172 +++++++++------------------ src/app/providers/session-data.ts | 2 +- 5 files changed, 181 insertions(+), 159 deletions(-) diff --git a/src/app/models.ts b/src/app/models.ts index a2d2691b0..50a1e6cfe 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -28,6 +28,7 @@ export interface Session { description?: string; speakerIDs: string[]; // speaker's id tracks: string[]; // name of track + hide?: boolean; } export interface IdName { @@ -60,7 +61,8 @@ export interface Support { } export interface PartOfDay { - partOfDay: string; // morning, afternoon, evening, overnight + indexKey: number; + name: string; // morning, afternoon, evening, overnight timeFrom: string; timeTo: string; } diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index 76cf78e5d..017175169 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -24,40 +24,42 @@ - + - - - - - {{group.time}} - - - - - + + + + -

{{session.name}}

-

- {{session.timeStart}} — {{session.timeEnd}}: {{session.location}} -

+ {{daily.date}} : {{group.partOfDay}}
-
- - - Favorite - - - Remove - - -
+ + + + + +

{{session.name}}

+

+ {{session.timeStart}} — {{session.timeEnd}}: {{session.location}} +

+
+
+ + + Favorite + + + Remove + + +
+
- + No Sessions Found diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 57ffbd56d..1a7956f8a 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -6,7 +6,7 @@ import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; import { ScheduleTrackPage } from '../schedule-track/schedule-track'; import { ConferenceData } from '../../providers/conference-data'; import { UserData } from '../../providers/user-data'; -import { User } from '../../models'; +import { User, Session, PartOfDay } from '../../models'; @Component({ selector: 'page-schedule', @@ -19,13 +19,28 @@ export class SchedulePage { @ViewChild('scheduleList') scheduleList: List; user: User; - dayIndex = 0; + // dayIndex = 0; queryText = ''; segment = ''; - excludeTracks: any = []; - shownSessions: any = []; - groups: any = []; - confDate: string; + excludeTracks: any[] = []; + // shownSessions: any = []; + // groups: any = []; + // confDate: string; + + start = '2019-01-10'; + end = '2019-01-15'; + changePeriod = true; + + partsOfDay: PartOfDay[]; + sessions: Session[]; + schedule: { + date: string, + groups: { + indexKey: number + partOfDay: string, + sessions: any[] + }[] + }[] = []; constructor( public alertCtrl: AlertController, @@ -45,6 +60,11 @@ export class SchedulePage { if (track.isChecked) { this.excludeTracks.push(track.name); } }); }); + + this.dataProvider.getPartsOfDay().subscribe( + response => { this.partsOfDay = response ; } + ); + this.updateSchedule(); } @@ -54,9 +74,73 @@ export class SchedulePage { this.scheduleList.closeSlidingItems(); } - this.dataProvider.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { - this.shownSessions = data.shownSessions; - this.groups = data.groups; + if (this.schedule.length === 0 || this.changePeriod) { + this.changePeriod = false; + this.dataProvider.getSessionInPeriod(this.start, this.end).subscribe( + (response: Session[]) => { + this.sessions = response; + this.buildSchedule(); + }); + } + } + + getFilterOption() { + return { + queryText: this.queryText.toLowerCase().trim(), + segment: this.segment, + excludeTracks: this.excludeTracks + }; + } + + buildSchedule() { + const filterOption = this.getFilterOption(); + this.sessions.forEach(session => { + session = this.dataProvider.filterSession(session, filterOption); + const partOfDay = this.partsOfDay.find(part => part.timeFrom <= session.timeStart && part.timeTo >= session.timeStart); + const newGroup = { + indexKey: partOfDay.indexKey, + partOfDay: partOfDay.name, + sessions: [session] + }; + const newItem = { date: session.date, groups: [newGroup]}; + + const sIndex = this.schedule.findIndex(item => item.date === session.date); + if (sIndex < 0) { + this.schedule.push(newItem); + } else { + const gIndex = this.schedule[sIndex].groups.findIndex( + group => group.partOfDay === partOfDay.name + ); + if (gIndex < 0) { + this.schedule[sIndex].groups.push(newGroup); + } else { + this.schedule[sIndex].groups[gIndex].sessions.push(session); + } + } + }); + this.schedule.sort((a, b) => { + if (a.date > b.date) { return 1; } + return -1; + }); + this.schedule.forEach(item => { + item.groups.sort((a, b) => a.indexKey - b.indexKey); + item.groups.forEach(group => { + group.sessions.sort((a, b) => { + if (a.timeStart > b.timeStart) { return 1; } + return -1; + }); + }); + }); + } + + updateFilter() { + const filterOption = this.getFilterOption(); + this.schedule.forEach(daily => { + daily.groups.forEach(group => { + group.sessions.forEach(session => { + session = this.dataProvider.filterSession(session, filterOption); + }); + }); }); } @@ -65,7 +149,7 @@ export class SchedulePage { this.chooseTrack(); } else if (this.segment === 'all') { this.excludeTracks = []; - this.updateSchedule(); + this.updateFilter(); } } @@ -80,7 +164,7 @@ export class SchedulePage { if (data) { this.excludeTracks = data; this.segment = 'user'; - this.updateSchedule(); + this.updateFilter(); } else { this.segment = ''; } @@ -97,7 +181,7 @@ export class SchedulePage { if (data) { this.excludeTracks = data; this.segment = 'user'; - this.updateSchedule(); + this.updateFilter(); } } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 329b3bc4b..b9e84bc2d 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -3,10 +3,10 @@ import { Injectable } from '@angular/core'; import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore'; -import { Observable, of } from 'rxjs'; +import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; -import { Track } from '../models'; +import { Track, Session, PartOfDay } from '../models'; @Injectable({ providedIn: 'root' @@ -16,115 +16,60 @@ export class ConferenceData { trackDoc: AngularFirestoreDocument ; tracks: Observable ; track: Observable ; + + sessionsCollection: AngularFirestoreCollection; + sessions: Observable ; + session: Observable ; + + partsOfDayCollection: AngularFirestoreCollection; + partsOfDay: Observable; + data: any; constructor( public http: HttpClient, - public user: UserData, + public userProvider: UserData, private afs: AngularFirestore) { this.tracksCollection = this.afs.collection( 'tracks', ref => ref.orderBy('name', 'asc')); + this.partsOfDayCollection = this.afs.collection( + 'partsOfDay', ref => ref.orderBy('indexKey', 'asc')); } - load(): any { - if (this.data) { - return of(this.data); - } else { - return this.http - .get('assets/data/data.json') - .pipe(map(this.processData, this)); - } - } - - processData(data: any) { - // just some good 'ol JS fun with objects and arrays - // build up the data by linking speakers to sessions - this.data = data; - - this.data.tracks = []; - - // loop through each day in the schedule - this.data.schedule.forEach((day: any) => { - // loop through each timeline group in the day - day.groups.forEach((group: any) => { - // loop through each session in the timeline group - group.sessions.forEach((session: any) => { - session.speakers = []; - if (session.speakerNames) { - session.speakerNames.forEach((speakerName: any) => { - const speaker = this.data.speakers.find( - (s: any) => s.name === speakerName - ); - if (speaker) { - session.speakers.push(speaker); - speaker.sessions = speaker.sessions || []; - speaker.sessions.push(session); - } - }); - } - - if (session.tracks) { - session.tracks.forEach((track: any) => { - if (this.data.tracks.indexOf(track) < 0) { - this.data.tracks.push(track); - } - }); - } - }); + getPartsOfDay(): Observable { + this.partsOfDay = this.partsOfDayCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as PartOfDay; + return data; }); - }); - - return this.data; + })); + return this.partsOfDay ; } - getTimeline( - dayIndex: number, - queryText = '', - excludeTracks: any[] = [], - segment = 'all' - ) { - return this.load().pipe( - map((data: any) => { - const day = data.schedule[dayIndex]; - day.shownSessions = 0; - - queryText = queryText.toLowerCase().replace(/,|\.|-/g, ' '); - const queryWords = queryText.split(' ').filter(w => !!w.trim().length); - - day.groups.forEach((group: any) => { - group.hide = true; - - group.sessions.forEach((session: any) => { - // check if this session should show or not - this.filterSession(session, queryWords, excludeTracks, segment); - - if (!session.hide) { - // if this session is not hidden then this group should show - group.hide = false; - day.shownSessions++; - } - }); - }); - - return day; - }) - ); + getSessionInPeriod(start, end): Observable { + this.sessionsCollection = this.afs.collection( + 'sessions', ref => ref.where('date', '>=', start) + .where('date', '<=', end) + .orderBy('date', 'asc')); + this.sessions = this.sessionsCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Session; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.sessions ; } - filterSession( - session: any, - queryWords: string[], - excludeTracks: any[], - segment: string - ) { + filterSession(session: any, options: any) { let matchesQueryText = false; - if (queryWords.length) { + if (options.queryText.length > 0) { // of any query word is in the session name than it passes the query test - queryWords.forEach((queryWord: string) => { - if (session.name.toLowerCase().indexOf(queryWord) > -1) { - matchesQueryText = true; - } - }); + if (session.name.toLowerCase().indexOf(options.queryText) > -1) { + matchesQueryText = true; + } } else { // if there are no query words then this session passes the query test matchesQueryText = true; @@ -134,7 +79,7 @@ export class ConferenceData { // exclude tracks then this session passes the track test let matchesTracks = false; session.tracks.forEach((trackName: string) => { - if (excludeTracks.indexOf(trackName) === -1) { + if (options.excludeTracks.indexOf(trackName) === -1) { matchesTracks = true; } }); @@ -142,28 +87,17 @@ export class ConferenceData { // if the segement is 'favorites', but session is not a user favorite // then this session does not pass the segment test let matchesSegment = false; - if (segment === 'favorites') { - if (this.user.hasFavorite(session.name)) { - matchesSegment = true; - } + if (options.segment === 'favorites') { + this.userProvider.getUser().then(user => { + matchesSegment = (user.favorites.indexOf(session.name) > -1); + }); } else { matchesSegment = true; } // all tests must be true if it should not be hidden session.hide = !(matchesQueryText && matchesTracks && matchesSegment); - } - - getSpeakers() { - return this.load().pipe( - map((data: any) => { - return data.speakers.sort((a: any, b: any) => { - const aName = a.name.split(' ').pop(); - const bName = b.name.split(' ').pop(); - return aName.localeCompare(bName); - }); - }) - ); + return session; } getTracks(): Observable { @@ -178,11 +112,11 @@ export class ConferenceData { return this.tracks ; } - getMap() { - return this.load().pipe( - map((data: any) => { - return data.map; - }) - ); - } + // getMap() { + // return this.load().pipe( + // map((data: any) => { + // return data.map; + // }) + // ); + // } } diff --git a/src/app/providers/session-data.ts b/src/app/providers/session-data.ts index 1d1cef267..f723b31cc 100644 --- a/src/app/providers/session-data.ts +++ b/src/app/providers/session-data.ts @@ -5,7 +5,7 @@ import { AngularFirestore, import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; -import { Session, Speaker } from '../models'; +import { Session } from '../models'; @Injectable({ providedIn: 'root' From 0349790b2d5b3c699eb10576ccebb537a00416c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sat, 22 Dec 2018 22:05:42 -0500 Subject: [PATCH 15/44] update 'session-detail mode': activated toggling favorite function --- src/app/models.ts | 9 +-- .../pages/session-detail/session-detail.ts | 62 ++++++++----------- src/app/providers/conference-data.ts | 8 --- 3 files changed, 28 insertions(+), 51 deletions(-) diff --git a/src/app/models.ts b/src/app/models.ts index 50a1e6cfe..7f0851f19 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -15,7 +15,7 @@ export interface Speaker { location?: string; email: string; phone?: string; - sessions?: IdName[]; // session id & name + sessions?: { id: string, name: string }[]; // session id & name } export interface Session { @@ -31,11 +31,6 @@ export interface Session { hide?: boolean; } -export interface IdName { - id: string; - name: string; -} - export interface Map { id?: string; name: string; @@ -49,7 +44,7 @@ export interface User { username: string; password: string; email: string; - favorites: IdName[]; // session's id and name. + favorites: { id: string, name: string }[]; // session's id and name. trackFilter: { name: string, isChecked: boolean }[]; } diff --git a/src/app/pages/session-detail/session-detail.ts b/src/app/pages/session-detail/session-detail.ts index c4fb44f89..0fb026e9f 100644 --- a/src/app/pages/session-detail/session-detail.ts +++ b/src/app/pages/session-detail/session-detail.ts @@ -3,7 +3,7 @@ import { ActivatedRoute } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { SessionData } from '../../providers/session-data'; -import { Session } from '../../models'; +import { Session, User } from '../../models'; @Component({ selector: 'page-session-detail', @@ -12,6 +12,7 @@ import { Session } from '../../models'; }) export class SessionDetailPage { session: Session; + user: User; isFavorite = false; constructor( private sessionProvider: SessionData, @@ -19,47 +20,36 @@ export class SessionDetailPage { private route: ActivatedRoute ) {} + ionViewWillEnter() { + const id = this.route.snapshot.paramMap.get('sessionId'); + this.sessionProvider.getSession(id) + .then( data => { + data.id = id; + this.session = data; + this.userProvider.getUser().then(user => { + this.user = user; + this.user.favorites.forEach(favorite => { + if (favorite.id === this.session.id) { this.isFavorite = true; } + }); + }); + } + ); + } + sessionClick(item: string) { console.log('Clicked', item); } toggleFavorite() { - if (this.userProvider.hasFavorite(this.session.name)) { - this.userProvider.removeFavorite(this.session.name); - this.isFavorite = false; + if (this.isFavorite) { + const index = this.user.favorites.findIndex(f => f.id === this.session.id); + if (index > -1) { + this.user.favorites.splice(index, 1); + } } else { - this.userProvider.addFavorite(this.session.name); - this.isFavorite = true; + this.user.favorites.push({id: this.session.id, name: this.session.name }); } - } - - ionViewWillEnter() { - const id = this.route.snapshot.paramMap.get('sessionId'); - this.sessionProvider.getSession(id) - .then( data => { this.session = data; } - ); - // const id = this.route.snapshot.paramMap.get('sessionId'); - // this.session = this.sessionProvider.getSession(id); - // this.dataProvider.load().subscribe((data: any) => { - // if ( - // data && - // data.schedule && - // data.schedule[0] && - // data.schedule[0].groups - // ) { - // const sessionId = this.route.snapshot.paramMap.get('sessionId'); - // for (const group of data.schedule[0].groups) { - // if (group && group.sessions) { - // for (const session of group.sessions) { - // if (session && session.id === sessionId) { - // this.session = session; - // this.isFavorite = this.userProvider.hasFavorite(this.session.name); - // break; - // } - // } - // } - // } - // } - // }); + this.userProvider.updateUser(this.user); + this.isFavorite = !this.isFavorite; } } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index b9e84bc2d..90ffdcae2 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -111,12 +111,4 @@ export class ConferenceData { })); return this.tracks ; } - - // getMap() { - // return this.load().pipe( - // map((data: any) => { - // return data.map; - // }) - // ); - // } } From 48604e88e922ed11f97824e2a50b8e0a4977b02c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sat, 22 Dec 2018 22:34:25 -0500 Subject: [PATCH 16/44] fix a bug: initial schedule were loaded opposit way. --- src/app/pages/schedule/schedule.ts | 6 +++--- src/app/providers/user-data.ts | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 1a7956f8a..b87f65bd0 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -55,10 +55,10 @@ export class SchedulePage { ionViewWillEnter() { // this.app.setTitle('Schedule'); this.userProvider.getUser().then(user => { - this.user = user; - this.user.trackFilter.forEach(track => { - if (track.isChecked) { this.excludeTracks.push(track.name); } + user.trackFilter.forEach(track => { + if (!track.isChecked) { this.excludeTracks.push(track.name); } }); + this.user = user; }); this.dataProvider.getPartsOfDay().subscribe( diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 97e05f8ad..87a53ce1b 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -66,6 +66,7 @@ export class UserData { login(user: User): Promise { return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { this.setUser(user); + console.log(user); return this.events.publish('user:login'); }); } From 9461f7b350712b2eab0dec8e6ae14123b3335bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sun, 23 Dec 2018 13:43:03 -0500 Subject: [PATCH 17/44] updated 'schedule mode': fixed showing favorites schedule --- src/app/pages/schedule/schedule.ts | 2 ++ src/app/providers/conference-data.ts | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index b87f65bd0..4d6484a3e 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -150,6 +150,8 @@ export class SchedulePage { } else if (this.segment === 'all') { this.excludeTracks = []; this.updateFilter(); + } else if (this.segment === 'favorites') { + this.updateFilter(); } } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 90ffdcae2..f0e55c168 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -89,14 +89,14 @@ export class ConferenceData { let matchesSegment = false; if (options.segment === 'favorites') { this.userProvider.getUser().then(user => { - matchesSegment = (user.favorites.indexOf(session.name) > -1); + matchesSegment = (user.favorites.findIndex(f => f.name === session.name) > -1); + // all tests must be true if it should not be hidden + session.hide = !(matchesQueryText && matchesTracks && matchesSegment); }); } else { - matchesSegment = true; + // doesn't matter about favorites. + session.hide = !(matchesQueryText && matchesTracks); } - - // all tests must be true if it should not be hidden - session.hide = !(matchesQueryText && matchesTracks && matchesSegment); return session; } From 3447f01f4a02bd8bf18ba7a882bd05167b5fc7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sun, 23 Dec 2018 16:27:14 -0500 Subject: [PATCH 18/44] update app openning mode: let app open after login or signup --- src/app/app.component.html | 4 +-- src/app/app.component.ts | 2 +- src/app/interfaces/user-options.ts | 5 --- src/app/models.ts | 11 +++---- src/app/pages/schedule/schedule.html | 6 ++-- src/app/pages/schedule/schedule.scss | 9 ++++++ src/app/pages/schedule/schedule.ts | 48 ++++++++-------------------- src/app/pages/signup/signup.ts | 2 +- src/app/providers/user-data.ts | 1 - 9 files changed, 35 insertions(+), 53 deletions(-) delete mode 100644 src/app/interfaces/user-options.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index c32d483c1..b88cf4a44 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -14,7 +14,7 @@ Navigate - + {{p.title}} @@ -73,7 +73,7 @@ - + Support diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 240cf968b..eaf41a7db 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -95,7 +95,7 @@ export class AppComponent implements OnInit { logout() { this.userData.logout().then(() => { - return this.navigate('/app/tabs/(schedule:schedule)'); + return this.openTutorial(); }); } diff --git a/src/app/interfaces/user-options.ts b/src/app/interfaces/user-options.ts deleted file mode 100644 index 1dda3fc7f..000000000 --- a/src/app/interfaces/user-options.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export interface UserOption { - username: string; - password: string; -} diff --git a/src/app/models.ts b/src/app/models.ts index 7f0851f19..246e07541 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -64,10 +64,9 @@ export interface PartOfDay { export interface Schedule { date: string; // 2018-12-06 - groups: SessionGroup[]; -} - -export interface SessionGroup { - time: PartOfDay; - sessions: Session[]; + groups: { + indexKey: number + partOfDay: string, + sessions: any[] + }[]; } diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index 017175169..94bcc136c 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -59,8 +59,10 @@

{{session.name}}

- - No Sessions Found + +

No Sessions Found

+

You may

+

Login or Signup!

diff --git a/src/app/pages/schedule/schedule.scss b/src/app/pages/schedule/schedule.scss index 0eddea0fd..b1b2ead45 100644 --- a/src/app/pages/schedule/schedule.scss +++ b/src/app/pages/schedule/schedule.scss @@ -20,3 +20,12 @@ page-schedule { } } +.notFound { + display: inline; + text-align: center; +} +.notFound h4 { + margin-top: 70px; + font-size: 24px; +} + diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 4d6484a3e..d970cd51a 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -19,13 +19,9 @@ export class SchedulePage { @ViewChild('scheduleList') scheduleList: List; user: User; - // dayIndex = 0; queryText = ''; segment = ''; excludeTracks: any[] = []; - // shownSessions: any = []; - // groups: any = []; - // confDate: string; start = '2019-01-10'; end = '2019-01-15'; @@ -54,18 +50,20 @@ export class SchedulePage { ionViewWillEnter() { // this.app.setTitle('Schedule'); - this.userProvider.getUser().then(user => { - user.trackFilter.forEach(track => { - if (!track.isChecked) { this.excludeTracks.push(track.name); } - }); - this.user = user; + this.userProvider.isLoggedIn().then(loggedIn => { + if (loggedIn) { + this.userProvider.getUser().then(user => { + user.trackFilter.forEach(track => { + if (!track.isChecked) { this.excludeTracks.push(track.name); } + }); + this.user = user; + this.dataProvider.getPartsOfDay().subscribe( + response => { this.partsOfDay = response ; } + ); + this.updateSchedule(); + }); + } }); - - this.dataProvider.getPartsOfDay().subscribe( - response => { this.partsOfDay = response ; } - ); - - this.updateSchedule(); } updateSchedule() { @@ -258,24 +256,4 @@ export class SchedulePage { await loading.onWillDismiss(); fab.close(); } - - /*doRefresh(refresher: Refresher) { - this.dataProvider.getTimeline(this.dayIndex, this.queryText, this.excludeTracks, this.segment).subscribe((data: any) => { - this.shownSessions = data.shownSessions; - this.groups = data.groups; - - // simulate a network request that would take longer - // than just pulling from out local json file - setTimeout(() => { - refresher.complete(); - - const toast = this.toastCtrl.create({ - message: 'Sessions have been updated.', - duration: 3000 - }); - toast.present(); - }, 1000); - }); - } - */ } diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 2a9c17e17..627623bc4 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -44,7 +44,7 @@ export class SignupPage implements OnInit { } else { this.setTrackFilter(); this.userProvider.signup(this.signup); - this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + this.router.navigateByUrl('/app/tabs/(speakers:speakers)'); } } } diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 87a53ce1b..97e05f8ad 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -66,7 +66,6 @@ export class UserData { login(user: User): Promise { return this.storage.set(this.HAS_LOGGED_IN, true).then(() => { this.setUser(user); - console.log(user); return this.events.publish('user:login'); }); } From ddd158cf7ff61917e8f5f71b5f91104e1f71aad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Thu, 27 Dec 2018 23:03:54 -0500 Subject: [PATCH 19/44] created 'image downloading module' using AngularFireStorage --- src/app/app.module.ts | 2 ++ src/app/models.ts | 2 +- src/app/pages/map/map.ts | 10 +++------- src/app/providers/conference-data.ts | 18 +++++++++++++++++- src/app/providers/speaker-data.ts | 14 +++++++++++--- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 7d14b4f77..bc4c62526 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,6 +10,7 @@ import { IonicStorageModule } from '@ionic/storage'; import { environment } from '../environments/environment'; import { AngularFireModule } from 'angularfire2'; import { AngularFirestoreModule } from 'angularfire2/firestore'; +import { AngularFireStorageModule } from 'angularfire2/storage'; import { AngularFireAuthModule } from 'angularfire2/auth'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @@ -28,6 +29,7 @@ import { ServiceWorkerModule } from '@angular/service-worker'; AngularFireModule.initializeApp(environment.firebase, 'ionic-conference'), AngularFireAuthModule, AngularFirestoreModule, + AngularFireStorageModule ], declarations: [AppComponent], providers: [InAppBrowser, SplashScreen, StatusBar], diff --git a/src/app/models.ts b/src/app/models.ts index 246e07541..d26b7e304 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -56,7 +56,7 @@ export interface Support { } export interface PartOfDay { - indexKey: number; + indexKey?: number; name: string; // morning, afternoon, evening, overnight timeFrom: string; timeTo: string; diff --git a/src/app/pages/map/map.ts b/src/app/pages/map/map.ts index 271c95451..e01a24bc7 100644 --- a/src/app/pages/map/map.ts +++ b/src/app/pages/map/map.ts @@ -4,10 +4,8 @@ import { ConferenceData } from '../../providers/conference-data'; import { Platform } from '@ionic/angular'; - declare var google: any; - @Component({ selector: 'page-map', templateUrl: 'map.html', @@ -19,16 +17,16 @@ export class MapPage { @ViewChild('mapCanvas') mapElement: ElementRef; constructor( - public confData: ConferenceData, + public dataProvider: ConferenceData, public platform: Platform ) { } ionViewDidEnter() { - this.confData.getMap().subscribe((mapData: any) => { + this.dataProvider.getMap().subscribe((mapData: any) => { const mapEle = this.mapElement.nativeElement; const map = new google.maps.Map(mapEle, { - center: mapData.find((d: any) => d.center), + center: mapData.find((loc: any) => loc.center), zoom: 16 }); @@ -51,8 +49,6 @@ export class MapPage { google.maps.event.addListenerOnce(map, 'idle', () => { mapEle.classList.add('show-map'); }); - }); - } } diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index f0e55c168..cd92d4307 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -6,7 +6,7 @@ import { AngularFirestore, import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; -import { Track, Session, PartOfDay } from '../models'; +import { Track, Session, PartOfDay, Map } from '../models'; @Injectable({ providedIn: 'root' @@ -24,6 +24,9 @@ export class ConferenceData { partsOfDayCollection: AngularFirestoreCollection; partsOfDay: Observable; + mapsCollection: AngularFirestoreCollection; + maps: Observable; + data: any; constructor( @@ -34,6 +37,8 @@ export class ConferenceData { 'tracks', ref => ref.orderBy('name', 'asc')); this.partsOfDayCollection = this.afs.collection( 'partsOfDay', ref => ref.orderBy('indexKey', 'asc')); + this.mapsCollection = this.afs.collection( + 'maps', ref => ref.orderBy('name', 'asc')); } getPartsOfDay(): Observable { @@ -111,4 +116,15 @@ export class ConferenceData { })); return this.tracks ; } + + getMap() { + this.maps = this.mapsCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as any; + return data; + }); + })); + return this.maps ; + } } diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts index c6e71d6b7..b76cba822 100644 --- a/src/app/providers/speaker-data.ts +++ b/src/app/providers/speaker-data.ts @@ -2,7 +2,8 @@ import { Injectable } from '@angular/core'; import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore'; -import { Observable, of } from 'rxjs'; +import { AngularFireStorage } from 'angularfire2/storage'; +import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Speaker } from '../models'; @@ -16,7 +17,8 @@ export class SpeakerData { speakers: Observable ; speaker: Observable ; - constructor(private afs: AngularFirestore) { + constructor(private afs: AngularFirestore, + private storage: AngularFireStorage) { this.speakersCollection = this.afs.collection( 'speakers', ref => ref.orderBy('name', 'asc')); } @@ -27,6 +29,9 @@ export class SpeakerData { return response.map(action => { const data = action.payload.doc.data() as Speaker; data.id = action.payload.doc.id; + this.storage.ref(data.profilePic).getDownloadURL().subscribe(url => { + data.profilePic = url; + }); return data; }); })); @@ -37,7 +42,10 @@ export class SpeakerData { return this.speakersCollection.doc(id).ref.get() .then(doc => { const speaker = doc.data() as Speaker; - return speaker; + this.storage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { + speaker.profilePic = url; + }); + return speaker; }); } From ef5b979ed051a5aab2e4e96da83b28dcbff2934b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 28 Dec 2018 12:22:46 -0500 Subject: [PATCH 20/44] testing pull request --- src/app/providers/conference-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index cd92d4307..25fa1ece5 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -6,7 +6,7 @@ import { AngularFirestore, import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; -import { Track, Session, PartOfDay, Map } from '../models'; +import { Track, Session, PartOfDay } from '../models'; @Injectable({ providedIn: 'root' From f6ee2b25d3ba1294c50021d2e7517f7682cdc095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 28 Dec 2018 14:32:03 -0500 Subject: [PATCH 21/44] updated installing dependencies and matching versions in package.json --- package-lock.json | 244 ++------------------------- package.json | 12 +- src/app/providers/conference-data.ts | 18 +- 3 files changed, 30 insertions(+), 244 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ad16180b..4b740c68f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -930,9 +930,9 @@ "integrity": "sha512-ZD8lTgW07NGgo75bTyBJA8Lt9+NweNzot7lrsBtIvfciwUzaFJLsv2EShqjBeuhF7RpG6YFucJ6m67w5buCtzw==" }, "@firebase/auth": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.9.0.tgz", - "integrity": "sha512-pNxfxFr4/tJluGfmPYUiuy2Tq/ZSRniJlWP4fj1mg+a9r+KevheeISZdWEZwJMosieXeCg+BzY0tvFD9j5ZrDw==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.9.1.tgz", + "integrity": "sha512-kiJtKXzM7DD1UNTdWcMmmRoU4LBX95JPWgCUN6nzumO1Ed+1izsgE4OwYVbZo+inSlOp6au0JTJrecsHHBemug==", "requires": { "@firebase/auth-types": "0.5.0" } @@ -943,9 +943,9 @@ "integrity": "sha512-DSjtsIjTy5RSiWyGHqiGkLcDgEgFEf2aD2O0t/0+lHmAzxUGrJFO5+IkPNV6i0ffmtiJaXQDJ7z7q4OdypDBCg==" }, "@firebase/database": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.3.7.tgz", - "integrity": "sha512-BB5L3PqwQVJUdS1WY+sq3eun5n5oimFWolXYl6pyACJwqL2qnPp0cnjK6kOqTsRPPMayZZmfUI38RBDwXaUJhQ==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.3.8.tgz", + "integrity": "sha512-y+QJjxC62triL1g6e58sapkGKegvbNIp3hOttE6olYG/zzb+U4Q7lUbYjtMkVpGWKYSsQOPu8JkH3FNhFvX95Q==", "requires": { "@firebase/database-types": "0.3.2", "@firebase/logger": "0.1.2", @@ -975,9 +975,9 @@ "integrity": "sha512-9ZYdvYQ6r3aaHJarhUM5Hf6lQWu3ZJme+RR0o8qfBb9L04TL3uNjt+AJFku1ysVPntTn+9GqJjiIB2/OC3JtwA==" }, "@firebase/firestore": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-0.9.0.tgz", - "integrity": "sha512-ub9BXce75D7t2yQxqopJhqE5YrsdePLg7wP8aMLR2Twe+O89IZqOhdbE0VALjplD2rAWXkOLqf6zYsppu2hh4g==", + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-0.9.2.tgz", + "integrity": "sha512-a4T0JOJSS7XjQux9Dclw1hBcPZ61k3mbLHckKtZ/W7UE4nGcZcSGdwnNtQp9Mv6RuRnbGH6x364C7iiGq2hwSg==", "requires": { "@firebase/firestore-types": "0.8.0", "@firebase/logger": "0.1.2", @@ -3271,220 +3271,6 @@ "serialize-javascript": "^1.4.0" } }, - "cordova-android": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-7.0.0.tgz", - "integrity": "sha1-yVvt/PvDhjsYDE0p7/7E95Nh0Z0=", - "requires": { - "android-versions": "^1.2.1", - "cordova-common": "^2.2.0", - "elementtree": "0.1.6", - "nopt": "^3.0.1", - "properties-parser": "^0.2.3", - "q": "^1.4.1", - "shelljs": "^0.5.3" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "android-versions": { - "version": "1.2.1", - "bundled": true - }, - "ansi": { - "version": "0.3.1", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "base64-js": { - "version": "0.0.8", - "bundled": true - }, - "big-integer": { - "version": "1.6.26", - "bundled": true - }, - "bplist-parser": { - "version": "0.1.1", - "bundled": true, - "requires": { - "big-integer": "^1.6.7" - } - }, - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "cordova-common": { - "version": "2.2.0", - "bundled": true, - "requires": { - "ansi": "^0.3.1", - "bplist-parser": "^0.1.0", - "cordova-registry-mapper": "^1.1.8", - "elementtree": "0.1.6", - "glob": "^5.0.13", - "minimatch": "^3.0.0", - "osenv": "^0.1.3", - "plist": "^1.2.0", - "q": "^1.4.1", - "semver": "^5.0.1", - "shelljs": "^0.5.3", - "underscore": "^1.8.3", - "unorm": "^1.3.3" - } - }, - "cordova-registry-mapper": { - "version": "1.1.15", - "bundled": true - }, - "elementtree": { - "version": "0.1.6", - "bundled": true, - "requires": { - "sax": "0.3.5" - } - }, - "glob": { - "version": "5.0.15", - "bundled": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "lodash": { - "version": "3.10.1", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "nopt": { - "version": "3.0.6", - "bundled": true, - "requires": { - "abbrev": "1" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "plist": { - "version": "1.2.0", - "bundled": true, - "requires": { - "base64-js": "0.0.8", - "util-deprecate": "1.0.2", - "xmlbuilder": "4.0.0", - "xmldom": "0.1.x" - } - }, - "properties-parser": { - "version": "0.2.3", - "bundled": true - }, - "q": { - "version": "1.5.1", - "bundled": true - }, - "sax": { - "version": "0.3.5", - "bundled": true - }, - "semver": { - "version": "5.4.1", - "bundled": true - }, - "shelljs": { - "version": "0.5.3", - "bundled": true - }, - "underscore": { - "version": "1.8.3", - "bundled": true - }, - "unorm": { - "version": "1.4.1", - "bundled": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "xmlbuilder": { - "version": "4.0.0", - "bundled": true, - "requires": { - "lodash": "^3.5.0" - } - }, - "xmldom": { - "version": "0.1.27", - "bundled": true - } - } - }, "cordova-ios": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-4.5.5.tgz", @@ -5125,14 +4911,14 @@ } }, "firebase": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-5.7.0.tgz", - "integrity": "sha512-8sQYXCUbUuzpyZS+XpBogstQE/7lvX6tPWtrUH0Cf4mH7flH/Sue5GUvZzwBpkgKOrMpI+clzuoYm/ffGi/TjQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-5.7.2.tgz", + "integrity": "sha512-RrjQ9q4dM9Q97vd+ucfuOAjby4vsjdW350ohy+Rw0lsA4Y+bJ0RAVnYimXqGfPfoIAErRJj6HctutE4gg1G2xw==", "requires": { "@firebase/app": "0.3.5", - "@firebase/auth": "0.9.0", - "@firebase/database": "0.3.7", - "@firebase/firestore": "0.9.0", + "@firebase/auth": "0.9.1", + "@firebase/database": "0.3.8", + "@firebase/firestore": "0.9.2", "@firebase/functions": "0.3.3", "@firebase/messaging": "0.3.7", "@firebase/polyfill": "0.3.3", diff --git a/package.json b/package.json index 7dfdced0b..bf2f4204d 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,10 @@ }, "private": true, "dependencies": { - "@angular/common": "~7.1.0", - "@angular/core": "~7.1.0", + "@angular/common": "~7.1.3", + "@angular/core": "~7.1.3", "@angular/fire": "^5.1.1", - "@angular/forms": "~7.1.0", + "@angular/forms": "~7.1.3", "@angular/http": "~7.1.0", "@angular/platform-browser": "7.1.3", "@angular/platform-browser-dynamic": "7.1.3", @@ -34,7 +34,7 @@ "@ionic/angular": "4.0.0-beta.19", "@ionic/storage": "^2.1.3", "angularfire2": "^5.1.1", - "cordova-android": "^7.1.1", + "cordova-android": "^7.0.0", "cordova-ios": "^4.5.5", "cordova-plugin-device": "^2.0.2", "cordova-plugin-inappbrowser": "^3.0.0", @@ -44,7 +44,7 @@ "cordova-plugin-statusbar": "^2.4.2", "cordova-plugin-whitelist": "^1.3.2", "core-js": "^2.5.7", - "firebase": "^5.7.0", + "firebase": "^5.7.2", "rxjs": "6.3.3", "sw-toolbox": "3.6.0", "zone.js": "^0.8.26" @@ -93,4 +93,4 @@ "cordova-plugin-ionic-keyboard": {} } } -} \ No newline at end of file +} diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 25fa1ece5..82cc9e51f 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -17,12 +17,12 @@ export class ConferenceData { tracks: Observable ; track: Observable ; - sessionsCollection: AngularFirestoreCollection; - sessions: Observable ; - session: Observable ; + sessionsCollection: AngularFirestoreCollection; + sessions: Observable ; + session: Observable ; - partsOfDayCollection: AngularFirestoreCollection; - partsOfDay: Observable; + partsOfDayCollection: AngularFirestoreCollection; + partsOfDay: Observable; mapsCollection: AngularFirestoreCollection; maps: Observable; @@ -41,18 +41,18 @@ export class ConferenceData { 'maps', ref => ref.orderBy('name', 'asc')); } - getPartsOfDay(): Observable { + getPartsOfDay(): Observable { this.partsOfDay = this.partsOfDayCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as PartOfDay; + const data = action.payload.doc.data() as any; return data; }); })); return this.partsOfDay ; } - getSessionInPeriod(start, end): Observable { + getSessionInPeriod(start, end): Observable { this.sessionsCollection = this.afs.collection( 'sessions', ref => ref.where('date', '>=', start) .where('date', '<=', end) @@ -60,7 +60,7 @@ export class ConferenceData { this.sessions = this.sessionsCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as Session; + const data = action.payload.doc.data() as any; data.id = action.payload.doc.id; return data; }); From b4d31b9fc1c661964db95d66271cdb5ec96ab1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 28 Dec 2018 22:13:39 -0500 Subject: [PATCH 22/44] fixed all errors after merge. Mainly version conflict of @ionic/angular. --- package-lock.json | 2137 ++++++++--------- package.json | 22 +- src/app/app-routing.module.ts | 4 +- src/app/app.component.ts | 14 +- src/app/pages/about/about.ts | 1 + src/app/pages/account/account.ts | 1 + src/app/pages/login/login.ts | 1 + .../pages/schedule-filter/schedule-filter.ts | 1 + src/app/pages/schedule/schedule.ts | 15 +- src/app/pages/signup/signup.ts | 1 + src/app/pages/speaker-list/speaker-list.html | 6 +- src/app/pages/speaker-list/speaker-list.ts | 1 + src/app/pages/support/support.ts | 23 +- .../tabs-page/tabs-page-routing.module.ts | 76 +- src/app/pages/tabs-page/tabs-page.html | 24 +- src/app/pages/tutorial/tutorial.ts | 7 +- src/index.html | 2 +- 17 files changed, 1105 insertions(+), 1231 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4b740c68f..200a6b00a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,27 +12,6 @@ "requires": { "@angular-devkit/core": "7.1.0", "rxjs": "6.3.3" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "@angular-devkit/build-angular": { @@ -90,38 +69,10 @@ "webpack-subresource-integrity": "1.1.0-rc.6" }, "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "opn": { - "version": "5.3.0", - "resolved": "http://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true } } @@ -173,57 +124,26 @@ "@angular-devkit/architect": "0.11.0", "@angular-devkit/core": "7.1.0", "rxjs": "6.3.3" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "@angular-devkit/core": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.2.tgz", - "integrity": "sha512-LyjHGuLnLWrgX7SYDkKmc3eW4H5uuaoC+CXYjRfgx3qundrLfvTCRgNGC6FPjhQNnVXH9qar+j9P1aMmKFb4Lw==", - "dev": true, + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", + "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", "requires": { "ajv": "6.5.3", "chokidar": "2.0.4", "fast-json-stable-stringify": "2.0.0", "rxjs": "6.3.3", "source-map": "0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "@angular-devkit/schematics": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.2.tgz", - "integrity": "sha512-NFhHLYWf9gpGQm0s19lq+nAw3CZ0udBpoBLzCm8Crlmu6+7aAXgw7Fv5P4ukWJ/e1m7NDGVids+B6kBGXaY6Ig==", - "dev": true, + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", + "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", "requires": { - "@angular-devkit/core": "7.1.2", + "@angular-devkit/core": "7.1.0", "rxjs": "6.3.3" } }, @@ -242,75 +162,29 @@ "opn": "5.3.0", "semver": "5.5.1", "symbol-observable": "1.2.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", - "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" - } - }, - "opn": { - "version": "5.3.0", - "resolved": "http://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "@angular/common": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.1.3.tgz", - "integrity": "sha512-4LnvTevDJW9Fmpmg6KeEyYcz8O4pS88nkm8FwKz+bkbFEiPz6tIxzhDlGuCAH0UmU4GojdWKMWhvLLvTEyCMpw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.1.4.tgz", + "integrity": "sha512-oQPCilcf1H/OXmt4z6PfGoCSb1YPRBAXGs/KRBARm3tYan2r5CmV0BFwpWXWQrEMt8YQqqLiBQUQ64d8+VFm8Q==", "requires": { "tslib": "^1.9.0" } }, "@angular/compiler": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.1.3.tgz", - "integrity": "sha512-uOcMyP9UBr7EkBWDMnGe/f3A1OidDt3Mq1TCp/8ETAxjerD7HxPJgdP0psBm85j6S5LorTUIOUm6ETfVP09E7A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.1.0.tgz", + "integrity": "sha512-1Hjx6e+lVXZyXFFe4OW34ZpiaGEYyB1MQ7k2C+cMm0ABMQS3LsWT4DYhY7bk0mmMuuXQj66C62MX76ladDtdIg==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "@angular/compiler-cli": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.1.3.tgz", - "integrity": "sha512-24r/7+qyXnDNsKWPxOnMECmncqc+Ucvd/clHHmEXX50EJOw8cA9odOJI1LnO+aWcMVRkjTidL6kVlagddkyOMg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.1.0.tgz", + "integrity": "sha512-Q42B3YmjMNYWTxTWfyDDFa6HSVqwY3rZO5Kp3Q/NKhQ6w/WddduxjARf/OCbtp0bVX3wZNObS6nO4H65rNCtsw==", "dev": true, "requires": { "canonical-path": "1.0.0", @@ -606,12 +480,6 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", @@ -645,9 +513,9 @@ } }, "@angular/core": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.1.3.tgz", - "integrity": "sha512-Vv2Eolb5fZZZLIyodazDTIH6l3wT0ss7oJq+op0aqfrH43HlZ1LkkoovPskX2w0Om9bzPfvfPz+fWm36WXrFyA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.1.4.tgz", + "integrity": "sha512-36uWLrmmlzf8JKaq2A5F2tPQEHvFSsbTQWOT559Drp1tzM2uSA7PysNHv5TXUshDn5i54S2EQFm4bj2YPp4Hzg==", "requires": { "tslib": "^1.9.0" } @@ -658,39 +526,39 @@ "integrity": "sha512-QfLVEhZYW3+3fh2d1z76/vab1GkLnEQWzFQK06D1ZaT8jZsVEdFMIPr7GSTJWAuOdqBRYq14iqzqEkJH3WHzig==" }, "@angular/forms": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.1.3.tgz", - "integrity": "sha512-gzXuQAaYQU2Gus8CZCyQtD/mzzxlgHvFtGRRNg9/UksekftVSk7/l+oj57NGMGh/0MF5rpRB3BYATZlF/TGHsw==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.1.4.tgz", + "integrity": "sha512-YB2lDRe7aMsaO5ZlbeFZGH+uTQOcpotFDKCmTckpefRJ7id6TlUSBYdYRH80qOQfPJGpsnqQvLZkL24UMasKtQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/http": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.1.0.tgz", - "integrity": "sha512-Je3D374ccxTFGpFu9tXi6k95vTaG+3jYYtEQ7i43CHbaGyHR/KwMEr8DEzrABd1zCSxBX71WwHuReG2wBANfcA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.1.4.tgz", + "integrity": "sha512-Lrjb99sHu0Cv7MBbVLev1I1Fe+DJcwG4v7juZB/5nE5opKmbQo3Lfqvt2dVrMOxHeju9ReFznEnuGNMK6+m6pQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/language-service": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.1.0.tgz", - "integrity": "sha512-dgYCD4Kw6j14hPykprSkMJNCo05dKu+JroMR84/PA/J+weN39nAUj4+/TV4oElbRK2Mr/xtHzSkb259y3Rwm/Q==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.1.4.tgz", + "integrity": "sha512-Pvrk3W3+6XfrmpCRcTumfyplv6AQJXKfDdPFSbhdpHJlpdcQRo6TckA85Yln5/CXZSAiPaZeiejQt2OogrIRLg==", "dev": true }, "@angular/platform-browser": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.1.3.tgz", - "integrity": "sha512-cGMPzsrKN6Gz9Ah5Jlp2lWe5Y+k1bCYug8Unnux9BHMpRo++RxYB8rOVK4kpmXQajOh5+NbXDzGEoZwMtlZWYQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.1.0.tgz", + "integrity": "sha512-kCrmaNZukWaXk6qlvzyE1Dln/YB2XOGbhb9e+y3NE94beCgDTWseKViMevIoGm/H+Lzf0I2RPg8GMKkQ7pQwNQ==", "requires": { "tslib": "^1.9.0" } }, "@angular/platform-browser-dynamic": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.1.3.tgz", - "integrity": "sha512-QjcRuGW3MEqaPrWp/4jxOvYevljb1Yjxo0p8xWbtrvL+YVteEVPDWNk4NtzHhQW9j6NzWEjnV5ocNx9I+anXeg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.1.0.tgz", + "integrity": "sha512-0yG6e/ZOI9LNUGgSjJ7xUWZhC41z87klO0oEHhEzQeaDxO/SOBasbMiws4ETuhulMgOR81UCAVobXMoOQJbfWg==", "requires": { "tslib": "^1.9.0" } @@ -705,48 +573,20 @@ "@schematics/angular": "7.1.0", "parse5-html-rewriting-stream": "5.1.0", "rxjs": "6.3.3" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", - "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", - "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - } } }, "@angular/router": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.1.3.tgz", - "integrity": "sha512-vQMUppMmBmUna/sU3tziy9Mqa8HCO/hAp2huTfSA/KF6y9gf1B4J/pISOrHizXL32PisU8Vi0bw+pfIeW/nbQw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.1.0.tgz", + "integrity": "sha512-yrjNvCj7XbXmZSmQfXGEkWJ9ogRZmIk5GHyOfGKNNRXhQK2OBznY0Avyer2r3mcgV/RLrI1FYQyKN9mdLftf6g==", "requires": { "tslib": "^1.9.0" } }, "@angular/service-worker": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-7.1.0.tgz", - "integrity": "sha512-lmeJl8JDvmtDFM7h1gUs8vVsJhMuRKakBIwtQTWEX8TYRh/6fZCObHNjoGGps3BAPrgAbCyxJE2g3rhb/Y4YqA==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-7.1.4.tgz", + "integrity": "sha512-PpR+Y1U1lpiRjH4PH+bbW0ccIV1AyB1lCTfZBa5NvDqUnJ7/df91RVzlCweCL2d187wOYgd2MSfzvDzSdl0Hvw==", "requires": { "tslib": "^1.9.0" } @@ -761,12 +601,12 @@ } }, "@babel/generator": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.1.6.tgz", - "integrity": "sha512-brwPBtVvdYdGxtenbQgfCdDPmtkmUBZPjUoK5SXJEBuHaA5BCubh9ly65fzXz7R6o5rA76Rs22ES8Z+HCc0YIQ==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", + "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", "dev": true, "requires": { - "@babel/types": "^7.1.6", + "@babel/types": "^7.2.2", "jsesc": "^2.5.1", "lodash": "^4.17.10", "source-map": "^0.5.0", @@ -778,6 +618,12 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true } } }, @@ -830,43 +676,43 @@ } }, "@babel/parser": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.1.6.tgz", - "integrity": "sha512-dWP6LJm9nKT6ALaa+bnL247GHHMWir3vSlZ2+IHgHgktZQx0L3Uvq2uAWcuzIe+fujRsYWBW2q622C5UvGK9iQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", + "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", "dev": true }, "@babel/template": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.1.2.tgz", - "integrity": "sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.1.2", - "@babel/types": "^7.1.2" + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" } }, "@babel/traverse": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", - "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.1.6", + "@babel/generator": "^7.2.2", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.1.6", - "@babel/types": "^7.1.6", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.10" }, "dependencies": { "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -887,9 +733,9 @@ } }, "@babel/types": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.1.6.tgz", - "integrity": "sha512-DMiUzlY9DSjVsOylJssxLHSgj6tWM9PRFJOGW/RaOglVOK9nzTxoOMfTfRQXGUCUQ/HmlG2efwC+XqUEJ5ay4w==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz", + "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -954,14 +800,6 @@ "tslib": "1.9.0" }, "dependencies": { - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "requires": { - "websocket-driver": ">=0.5.1" - } - }, "tslib": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", @@ -1144,12 +982,11 @@ } }, "@ionic/angular": { - "version": "4.0.0-beta.19", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-4.0.0-beta.19.tgz", - "integrity": "sha512-yDXx6tduSW9DliplVQv0xnTrxyCFltk3PcKkQDWKCcIwd5nsfPg/5ZcoM3CHKNmmp5mkDljdz8IxCR3VEvdcgQ==", + "version": "4.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-4.0.0-beta.16.tgz", + "integrity": "sha512-JrU1r0+tRw9IMy3+4dr3ikPwZSkYryGzrj9k3izAT4ex24V5wQxO4HUgUe6mz4deWcAKGryNkbU0s+XfSDkceg==", "requires": { - "@ionic/core": "4.0.0-beta.19", - "tslib": "^1.9.3" + "@ionic/core": "4.0.0-beta.16" } }, "@ionic/angular-toolkit": { @@ -1161,105 +998,15 @@ "@schematics/angular": "^7.0.3", "tslib": "^1.9.0", "typescript": "^3.1.5" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.0.6.tgz", - "integrity": "sha512-RPSXUtLrpYDTqAEL0rCyDKxES76EomsPBvUUZTD6UkE2pihoh9ZIxkzhzlE+HU/xdqm28+smQYFhvvEAXFWwSQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.0.6.tgz", - "integrity": "sha512-S/3CrBDoh/BD4mBq8RNGQ8sgNFDsveCuFHDkOyct8+NDg2wcRkEGigyq8eZwVN/iVKCwjxc0I/bC336edoNMIQ==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.0.6", - "rxjs": "6.3.3" - } - }, - "@schematics/angular": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.0.6.tgz", - "integrity": "sha512-jOHL+vSu1cqAo3kRNDmgkq/GR2EDkJx5/h0VXGlbtdEpq892LipKHtyPgXa269AABgPKb3TSNBwZls6g2L9FCw==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.0.6", - "@angular-devkit/schematics": "7.0.6", - "typescript": "3.1.6" - } - }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "typescript": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", - "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - } } }, "@ionic/cli-framework": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ionic/cli-framework/-/cli-framework-1.3.0.tgz", - "integrity": "sha512-hJVWOqZVJXD0pa1amVFPlX7emXdEM6YpbllXkMQwYSubt9TXPRgUboC3JYxvwEfTscnvWO5OnKGZ29f0/zpTQg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@ionic/cli-framework/-/cli-framework-1.5.1.tgz", + "integrity": "sha512-O979w3XRftVfhiQJXv6c2IaOM4mY7z/8BOu54dR2ZJ/zYir6QW65loq6XQ373AqxoQpMc1xHMZqpYyTTVTScRw==", "dev": true, "requires": { - "@ionic/utils-fs": "0.0.4", + "@ionic/utils-fs": "0.0.6", "chalk": "^2.3.0", "debug": "^4.0.0", "inquirer": "^6.0.0", @@ -1269,9 +1016,9 @@ "rimraf": "^2.6.2", "slice-ansi": "^2.0.0", "stream-combiner2": "^1.1.1", - "string-width": "^2.1.1", + "string-width": "^3.0.0", "strip-ansi": "^5.0.0", - "tree-kill": "1.2.0", + "tree-kill": "1.2.1", "tslib": "^1.9.0", "untildify": "^3.0.2", "wrap-ansi": "^4.0.0", @@ -1279,15 +1026,15 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", "dev": true }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1312,24 +1059,14 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.0.0.tgz", + "integrity": "sha512-rr8CUxBbvOZDUvc5lNIJ+OC1nPVpz+Siw9VBtUjB9b6jZehZLFt0JMCZzShFHIsI8cbhm0EsNIfWJMFV3cu3Ew==", "dev": true, "requires": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "strip-ansi": "^5.0.0" } }, "strip-ansi": { @@ -1339,20 +1076,12 @@ "dev": true, "requires": { "ansi-regex": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", - "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", - "dev": true - } } }, "tree-kill": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", - "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", "dev": true }, "wrap-ansi": { @@ -1366,6 +1095,22 @@ "strip-ansi": "^4.0.0" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -1380,21 +1125,29 @@ } }, "@ionic/core": { - "version": "4.0.0-beta.19", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-4.0.0-beta.19.tgz", - "integrity": "sha512-v9Bddlws7+1zpiPblgNQBzCFBrEMtkii+AUPJ+/fSb0uIuDTGlRKPfHrRscxnSgGOch+leOArFQ4N3WBrZZmFQ==", + "version": "4.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-4.0.0-beta.16.tgz", + "integrity": "sha512-dZxJV30uOchQKZWY51ejhayIhg/dZR1dYY6agrBB/sGAZhNEwWgc5tV6IbpQvzx3rSXb9kJi7lZRs/bM9ztoYw==", "requires": { - "ionicons": "4.5.0" + "@types/node": "10.11.0", + "ionicons": "4.4.7" + }, + "dependencies": { + "@types/node": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.0.tgz", + "integrity": "sha512-R4Dvw6KjSYn/SpvjRchBOwXr14vVVcFXCtnM3f0aLvlJS8a599rrcEoihcP2/+Z/f75E5GNPd4aWM7j1yei9og==" + } } }, "@ionic/lab": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@ionic/lab/-/lab-1.0.13.tgz", - "integrity": "sha512-pnYgzfPPdAs3Z9snhHGDaAm2i3Fj0s1K6eAVbCH9hfUE8slv8DTjlcYO2FLDQ0JlFwEaAtL+zXp4guMK/TEWiw==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@ionic/lab/-/lab-1.0.16.tgz", + "integrity": "sha512-I9AzTdZeLTQM0rGpLMv5kYagqfP708jz6IVpLe3O5GI4wHgK7MWR/2PekOhz3QhzAxKcm/i5UcbbAkolWPtKnw==", "dev": true, "requires": { - "@ionic/cli-framework": "1.3.0", - "@ionic/utils-fs": "0.0.4", + "@ionic/cli-framework": "1.5.1", + "@ionic/utils-fs": "0.0.6", "chalk": "^2.3.0", "express": "^4.16.2", "tslib": "^1.9.0" @@ -1411,21 +1164,21 @@ } }, "@ionic/utils-fs": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-0.0.4.tgz", - "integrity": "sha512-eipaSkrX3ODCQzGKxFgruq2J28RoEm+JC0jJv5S64OXATxsnbwuReTmA2EMJyevLJrORWM0yvsgqmiLHH5VYJg==", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@ionic/utils-fs/-/utils-fs-0.0.6.tgz", + "integrity": "sha512-/7EbKNbKiRK1C+WuZ/omgD/XaUZeE/CUXtlMAHeGb3pIilcRF+xwMvLu6Vt63O+EwZ/nSIRQI7nb5YP0yUhkUg==", "dev": true, "requires": { "debug": "^4.0.0", "ncp": "^2.0.0", - "through2": "^2.0.3", + "through2": "^3.0.0", "tslib": "^1.9.0" }, "dependencies": { "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -1436,6 +1189,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true + }, + "through2": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", + "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", + "dev": true, + "requires": { + "readable-stream": "2 || 3", + "xtend": "~4.0.1" + } } } }, @@ -1452,27 +1215,6 @@ "webpack-sources": "1.2.0" }, "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1499,34 +1241,6 @@ "@angular-devkit/core": "7.1.0", "@angular-devkit/schematics": "7.1.0", "typescript": "3.1.6" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", - "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", - "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" - } } }, "@schematics/update": { @@ -1543,43 +1257,6 @@ "rxjs": "6.3.3", "semver": "5.5.1", "semver-intersect": "1.4.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "@angular-devkit/schematics": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", - "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } } }, "@types/cordova": { @@ -1615,9 +1292,9 @@ "dev": true }, "@types/selenium-webdriver": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.13.tgz", - "integrity": "sha512-rI0LGoMiZGUM+tjDakQpwZOvcmQoubiJ7hxqrYU12VRxBuGGvOThxrBOU/QmJKlKg1WG6FMzuvcEyLffvVSsmw==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.14.tgz", + "integrity": "sha512-4GbNCDs98uHCT/OMv40qQC/OpoPbYn9XdXeTiFwHBBFO6eJhYEPUu2zDKirXSbHlvDV8oZ9l8EQ+HrEx/YS9DQ==", "dev": true }, "@webassemblyjs/ast": { @@ -1893,9 +1570,9 @@ } }, "ajv-errors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", - "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", "dev": true }, "ajv-keywords": { @@ -1919,9 +1596,9 @@ } }, "ansi-colors": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.1.tgz", - "integrity": "sha512-Xt+zb6nqgvV9SWAVp0EG3lRsHcbq5DDgqjPPz6pwgtj6RKz65zGXMNa82oJfOSBA/to6GmRP7Dr+6o+kbApTzQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, "ansi-escapes": { @@ -2022,9 +1699,9 @@ "optional": true }, "array-flatten": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, "array-slice": { @@ -2237,7 +1914,7 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true } @@ -2257,6 +1934,14 @@ "lodash": "^4.17.4", "source-map": "^0.5.7", "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "babel-messages": { @@ -2501,6 +2186,17 @@ "qs": "6.5.2", "raw-body": "2.3.3", "type-is": "~1.6.16" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "bonjour": { @@ -2631,14 +2327,14 @@ } }, "browserslist": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.4.tgz", - "integrity": "sha512-u5iz+ijIMUlmV8blX82VGFrB9ecnUg5qEt55CMZ/YJEhha+d8qpBfOFuutJ6F/VKRXjZoD33b6uvarpPxcl3RA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz", + "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000899", - "electron-to-chromium": "^1.3.82", - "node-releases": "^1.0.1" + "caniuse-lite": "^1.0.30000921", + "electron-to-chromium": "^1.3.92", + "node-releases": "^1.1.1" } }, "browserstack": { @@ -2659,14 +2355,6 @@ "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } } }, "buffer-alloc": { @@ -2760,6 +2448,14 @@ "ssri": "^5.2.4", "unique-filename": "^1.1.0", "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + } } }, "cache-base": { @@ -2801,9 +2497,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000910", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000910.tgz", - "integrity": "sha512-u/nxtHGAzCGZzIxt3dA/tpSPOcirBZFWKwz1EPz4aaupnBI2XR0Rbr74g0zc6Hzy41OEM4uMoZ38k56TpYAWjQ==", + "version": "1.0.30000925", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000925.tgz", + "integrity": "sha512-zcYupoUxtW46rOikuDF7vfL9N1Qe9ZuUBTz3n3q8fFsoJIs/h9UN6Vg/0QpjsmvImXw9mVc3g+ZBfqvUz/iALA==", "dev": true }, "canonical-path": { @@ -3004,10 +2700,16 @@ "sprintf-js": "^1.1.1" }, "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, "sprintf-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true } } @@ -3131,7 +2833,7 @@ }, "concat-stream": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "resolved": "http://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { @@ -3168,109 +2870,319 @@ "unpipe": "~1.0.0" } }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "copy-webpack-plugin": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz", + "integrity": "sha512-0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + } + }, + "cordova-android": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-7.1.4.tgz", + "integrity": "sha512-Rtvu002I83uzfVyCsE6p2krFKVHt9TSAqZUATes+zH+o9cdxYGrLHY+PKCQo4SLCdSMdrkIHCDnQPTYTp/d7+g==", + "requires": { + "abbrev": "*", + "android-versions": "1.4.0", + "ansi": "*", + "balanced-match": "*", + "base64-js": "1.2.0", + "big-integer": "1.6.32", + "bplist-parser": "*", + "brace-expansion": "*", + "concat-map": "*", + "cordova-common": "2.2.5", + "cordova-registry-mapper": "*", + "elementtree": "0.1.6", + "glob": "5.0.15", + "inflight": "*", + "inherits": "*", + "minimatch": "*", + "nopt": "3.0.1", + "once": "*", + "path-is-absolute": "1.0.1", + "plist": "2.1.0", + "properties-parser": "0.2.3", + "q": "1.4.1", + "sax": "0.3.5", + "semver": "5.5.0", + "shelljs": "0.5.3", + "underscore": "*", + "unorm": "*", + "wrappy": "*", + "xmlbuilder": "8.2.2", + "xmldom": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "android-versions": { + "version": "1.4.0", + "bundled": true, + "requires": { + "semver": "^5.4.1" + } + }, + "ansi": { + "version": "0.3.1", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "base64-js": { + "version": "1.2.0", + "bundled": true + }, + "big-integer": { + "version": "1.6.32", + "bundled": true + }, + "bplist-parser": { + "version": "0.1.1", + "bundled": true, + "requires": { + "big-integer": "^1.6.7" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "cordova-common": { + "version": "2.2.5", + "bundled": true, + "requires": { + "ansi": "^0.3.1", + "bplist-parser": "^0.1.0", + "cordova-registry-mapper": "^1.1.8", + "elementtree": "0.1.6", + "glob": "^5.0.13", + "minimatch": "^3.0.0", + "plist": "^2.1.0", + "q": "^1.4.1", + "shelljs": "^0.5.3", + "underscore": "^1.8.3", + "unorm": "^1.3.3" + } + }, + "cordova-registry-mapper": { + "version": "1.1.15", + "bundled": true + }, + "elementtree": { + "version": "0.1.6", + "bundled": true, + "requires": { + "sax": "0.3.5" + } + }, + "glob": { + "version": "5.0.15", + "bundled": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nopt": { + "version": "3.0.1", + "bundled": true, + "requires": { + "abbrev": "1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "plist": { + "version": "2.1.0", + "bundled": true, + "requires": { + "base64-js": "1.2.0", + "xmlbuilder": "8.2.2", + "xmldom": "0.1.x" + } + }, + "properties-parser": { + "version": "0.2.3", + "bundled": true + }, + "q": { + "version": "1.4.1", + "bundled": true + }, + "sax": { + "version": "0.3.5", + "bundled": true + }, + "semver": { + "version": "5.5.0", + "bundled": true + }, + "shelljs": { + "version": "0.5.3", + "bundled": true + }, + "underscore": { + "version": "1.9.1", + "bundled": true + }, + "unorm": { + "version": "1.4.1", + "bundled": true + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "xmlbuilder": { + "version": "8.2.2", + "bundled": true + }, + "xmldom": { + "version": "0.1.27", + "bundled": true } } }, - "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", - "dev": true - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "copy-webpack-plugin": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz", - "integrity": "sha512-0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ==", - "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "globby": "^7.1.1", - "is-glob": "^4.0.0", - "loader-utils": "^1.1.0", - "minimatch": "^3.0.4", - "p-limit": "^1.0.0", - "serialize-javascript": "^1.4.0" - } - }, "cordova-ios": { "version": "4.5.5", "resolved": "https://registry.npmjs.org/cordova-ios/-/cordova-ios-4.5.5.tgz", @@ -3316,49 +3228,41 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "bundled": true }, "ansi": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" + "bundled": true }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "bundled": true }, "base64-js": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", - "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=" + "bundled": true }, "big-integer": { "version": "1.6.32", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.32.tgz", - "integrity": "sha512-ljKJdR3wk9thHfLj4DtrNiOSTxvGFaMjWrG4pW75juXC4j7+XuKJVFdg4kgFMYp85PVkO05dFMj2dk2xVsH4xw==" + "bundled": true }, "bplist-creator": { "version": "0.0.7", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz", - "integrity": "sha1-N98VNgkoJLh8QvlXsBNEEXNyrkU=", + "bundled": true, "requires": { "stream-buffers": "~2.2.0" } }, "bplist-parser": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz", - "integrity": "sha1-1g1dzCDLptx+HymbNdPh+V2vuuY=", + "bundled": true, "requires": { "big-integer": "^1.6.7" } }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3366,13 +3270,11 @@ }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "bundled": true }, "cordova-common": { "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cordova-common/-/cordova-common-2.2.5.tgz", - "integrity": "sha1-+TzvKtSUz8v1bEbj1hKqqctfzDI=", + "bundled": true, "requires": { "ansi": "^0.3.1", "bplist-parser": "^0.1.0", @@ -3389,21 +3291,18 @@ }, "cordova-registry-mapper": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/cordova-registry-mapper/-/cordova-registry-mapper-1.1.15.tgz", - "integrity": "sha1-4kS5GFuBdUc7/2B5MkkFEV+D3Hw=" + "bundled": true }, "elementtree": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/elementtree/-/elementtree-0.1.6.tgz", - "integrity": "sha1-KsTEbqMFFsjEy9teOsdBjlkt4gw=", + "bundled": true, "requires": { "sax": "0.3.5" } }, "glob": { "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "bundled": true, "requires": { "inflight": "^1.0.4", "inherits": "2", @@ -3414,8 +3313,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3423,13 +3321,11 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "bundled": true }, "ios-sim": { "version": "6.1.3", - "resolved": "https://registry.npmjs.org/ios-sim/-/ios-sim-6.1.3.tgz", - "integrity": "sha512-xnpRKFH8ytVuSs+qlfBttVjNqFRovONT+K940518eVXWC151AJbzC6L0TCGnxyMPF5ghVCGcyGterfMOJKVb3w==", + "bundled": true, "requires": { "bplist-parser": "^0.0.6", "nopt": "1.0.9", @@ -3439,13 +3335,11 @@ "dependencies": { "bplist-parser": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.0.6.tgz", - "integrity": "sha1-ONo0cYF9+dRKs4kuJ3B7u9daEbk=" + "bundled": true }, "nopt": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.9.tgz", - "integrity": "sha1-O8DXy6e/sNWmdtvtfA6+SKT9RU4=", + "bundled": true, "requires": { "abbrev": "1" } @@ -3454,37 +3348,32 @@ }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "requires": { "brace-expansion": "^1.1.7" } }, "nopt": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "bundled": true, "requires": { "abbrev": "1" } }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "requires": { "wrappy": "1" } }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "bundled": true }, "plist": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", - "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", + "bundled": true, "requires": { "base64-js": "1.2.0", "xmlbuilder": "8.2.2", @@ -3493,23 +3382,19 @@ }, "q": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + "bundled": true }, "sax": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.3.5.tgz", - "integrity": "sha1-iPz8H3PAyLvVt8d2ttPzUB7tBz0=" + "bundled": true }, "shelljs": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", - "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=" + "bundled": true }, "simctl": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/simctl/-/simctl-1.1.1.tgz", - "integrity": "sha512-yY1WQMq/pneY5jQb2+lFp45qEtcz4yKBu1NOPo2OFDVCkwSkQhpkoaAaO1fWhq4IU0+8TQ2r1PMGSTedP0A/Og==", + "bundled": true, "requires": { "shelljs": "^0.2.6", "tail": "^0.4.0" @@ -3517,15 +3402,13 @@ "dependencies": { "shelljs": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz", - "integrity": "sha1-kEktcv/MgVmXa6umL7D2iE8MM3g=" + "bundled": true } } }, "simple-plist": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-0.2.1.tgz", - "integrity": "sha1-cXZts1IyaSjPOoByQrp2IyJjZyM=", + "bundled": true, "requires": { "bplist-creator": "0.0.7", "bplist-parser": "0.1.1", @@ -3534,13 +3417,11 @@ "dependencies": { "base64-js": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.1.2.tgz", - "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=" + "bundled": true }, "plist": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.0.1.tgz", - "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", + "bundled": true, "requires": { "base64-js": "1.1.2", "xmlbuilder": "8.2.2", @@ -3551,38 +3432,31 @@ }, "stream-buffers": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" + "bundled": true }, "tail": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/tail/-/tail-0.4.0.tgz", - "integrity": "sha1-0p3nJ1DMmdseBTr/E8NZ7PtxMAI=" + "bundled": true }, "underscore": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + "bundled": true }, "unorm": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", - "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=" + "bundled": true }, "uuid": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=" + "bundled": true }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "bundled": true }, "xcode": { "version": "0.9.3", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-0.9.3.tgz", - "integrity": "sha1-kQqJwWrubMC0LKgFptC0z4chHPM=", + "bundled": true, "requires": { "pegjs": "^0.10.0", "simple-plist": "^0.2.1", @@ -3591,18 +3465,15 @@ }, "xml-escape": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz", - "integrity": "sha1-OQTBQ/qOs6ADDsZG0pAqLxtwbEQ=" + "bundled": true }, "xmlbuilder": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=" + "bundled": true }, "xmldom": { "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + "bundled": true } } }, @@ -3622,9 +3493,9 @@ "integrity": "sha512-6ucQ6FdlLdBm8kJfFnzozmBTjru/0xekHP/dAhjoCZggkGRlgs8TsUJFkxa/bV+qi7Dlo50JjmpE4UMWAO+aOQ==" }, "cordova-plugin-ionic-webview": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-2.2.3.tgz", - "integrity": "sha512-U6ufU5VVwDZuRvv9MwFixAu37r5VnXoi15T/Fg29BTGZJRZKnQ9lsJfVKtm/uLp4ITc85/3RBubOyUkRE/SOuQ==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/cordova-plugin-ionic-webview/-/cordova-plugin-ionic-webview-2.3.1.tgz", + "integrity": "sha512-tGKRp2iEYbOwZ2sT/uBU2C1YW1a43QI3YGi4WMH4LsgUdDjYGj4OZ8o7xQtRlxOKpdAjtSyLn1wz3Jip04elMg==" }, "cordova-plugin-splashscreen": { "version": "5.0.2", @@ -3642,9 +3513,9 @@ "integrity": "sha1-tehezbv+Wu3tQKG/TuI3LmfZb7Q=" }, "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.1.tgz", + "integrity": "sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg==" }, "core-util-is": { "version": "1.0.2", @@ -4122,9 +3993,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.84", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.84.tgz", - "integrity": "sha512-IYhbzJYOopiTaNWMBp7RjbecUBsbnbDneOP86f3qvS0G0xfzwNSvMJpTrvi5/Y1gU7tg2NAgeg8a8rCYvW9Whw==", + "version": "1.3.96", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.96.tgz", + "integrity": "sha512-ZUXBUyGLeoJxp4Nt6G/GjBRLnyz8IKQGexZ2ndWaoegThgMGFO1tdDYID5gBV32/1S83osjJHyfzvanE/8HY4Q==", "dev": true }, "elliptic": { @@ -4142,6 +4013,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -4486,7 +4363,7 @@ }, "expand-range": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { @@ -4542,7 +4419,7 @@ }, "expand-range": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { @@ -4571,12 +4448,6 @@ "kind-of": "^3.0.2" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", @@ -4637,7 +4508,7 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, @@ -4683,17 +4554,6 @@ "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } } }, "extglob": { @@ -4796,10 +4656,9 @@ "dev": true }, "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", "requires": { "websocket-driver": ">=0.5.1" } @@ -4936,9 +4795,9 @@ } }, "follow-redirects": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.9.tgz", - "integrity": "sha512-Bh65EZI/RU8nx0wbYF9shkFZlqLP+6WT/5FnA3cE/djNSuKNHJEinGGZgu/cQEkeeb2GdFOgenAmn8qaqYke2w==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.0.tgz", + "integrity": "sha512-4Oh4eI3S9OueVV41AgJ1oLjpaJUhbJ7JDGOMhe0AFqoSejl5Q2nn3eGglAzRUKVKZE8jG5MNn66TjCJMAnpsWA==", "dev": true, "requires": { "debug": "=3.1.0" @@ -5063,25 +4922,21 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "bundled": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "bundled": true, "optional": true, "requires": { "delegates": "^1.0.0", @@ -5090,13 +4945,11 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "bundled": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5104,35 +4957,29 @@ }, "chownr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "bundled": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "bundled": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "bundled": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "optional": true, "requires": { "ms": "2.0.0" @@ -5140,26 +4987,22 @@ }, "deep-extend": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "bundled": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -5167,14 +5010,12 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "optional": true, "requires": { "aproba": "^1.0.3", @@ -5189,8 +5030,7 @@ }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "bundled": true, "optional": true, "requires": { "fs.realpath": "^1.0.0", @@ -5203,14 +5043,12 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "optional": true }, "iconv-lite": { "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "bundled": true, "optional": true, "requires": { "safer-buffer": "^2.1.0" @@ -5218,8 +5056,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "optional": true, "requires": { "minimatch": "^3.0.4" @@ -5227,8 +5064,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "optional": true, "requires": { "once": "^1.3.0", @@ -5237,46 +5073,39 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "bundled": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "bundled": true }, "minipass": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "bundled": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5284,8 +5113,7 @@ }, "minizlib": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "bundled": true, "optional": true, "requires": { "minipass": "^2.2.1" @@ -5293,22 +5121,19 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "optional": true }, "needle": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", - "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "bundled": true, "optional": true, "requires": { "debug": "^2.1.2", @@ -5318,8 +5143,7 @@ }, "node-pre-gyp": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", - "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "bundled": true, "optional": true, "requires": { "detect-libc": "^1.0.2", @@ -5336,8 +5160,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "optional": true, "requires": { "abbrev": "1", @@ -5346,14 +5169,12 @@ }, "npm-bundled": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", - "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "bundled": true, "optional": true }, "npm-packlist": { "version": "1.1.10", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", - "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "bundled": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", @@ -5362,8 +5183,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "optional": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -5374,39 +5194,33 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "bundled": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "optional": true, "requires": { "os-homedir": "^1.0.0", @@ -5415,20 +5229,17 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "optional": true }, "rc": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "bundled": true, "optional": true, "requires": { "deep-extend": "^0.5.1", @@ -5439,16 +5250,14 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "optional": true } } }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "optional": true, "requires": { "core-util-is": "~1.0.0", @@ -5462,8 +5271,7 @@ }, "rimraf": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "bundled": true, "optional": true, "requires": { "glob": "^7.0.5" @@ -5471,43 +5279,36 @@ }, "safe-buffer": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "bundled": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "optional": true }, "semver": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "bundled": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5516,8 +5317,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "optional": true, "requires": { "safe-buffer": "~5.1.0" @@ -5525,22 +5325,19 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "optional": true }, "tar": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "bundled": true, "optional": true, "requires": { "chownr": "^1.0.1", @@ -5554,14 +5351,12 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "optional": true }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "optional": true, "requires": { "string-width": "^1.0.2" @@ -5569,13 +5364,11 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "bundled": true }, "yallist": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + "bundled": true } } }, @@ -6222,42 +6015,21 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", - "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", + "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", "dev": true, "requires": { - "punycode": "^2.1.0" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } } } @@ -6346,9 +6118,9 @@ } }, "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -6542,9 +6314,9 @@ } }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -6636,9 +6408,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -6784,9 +6556,9 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, "invariant": { @@ -6804,9 +6576,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ionicons": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.5.0.tgz", - "integrity": "sha512-nNkS/0wmPcW4Lbg+NqivlOl14BGKKpaZZzZVQzH63MuZZvuu5u8F/JCwcUYiPOAYGp02w0UaDL/slz+HZOuB3Q==" + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.4.7.tgz", + "integrity": "sha512-6DOSIWGJnMY7nP69Ov4WduUA/zInJ8bc4/Y/orj76hrL9AgtMozEb4MciZ7ocPxr97wc8J+1c5uHpNZSaWE8KQ==" }, "ip": { "version": "1.1.5", @@ -6828,7 +6600,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -6883,7 +6655,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -7069,9 +6841,9 @@ "dev": true }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isbinaryfile": { "version": "3.0.3", @@ -7400,9 +7172,9 @@ "dev": true }, "js-base64": { - "version": "2.4.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", - "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz", + "integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==", "dev": true, "optional": true }, @@ -7520,12 +7292,6 @@ "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -7548,7 +7314,7 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } @@ -7590,9 +7356,9 @@ }, "dependencies": { "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "source-map": { @@ -7946,9 +7712,9 @@ } }, "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -7999,25 +7765,36 @@ }, "dependencies": { "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + } } }, "mississippi": { @@ -8056,6 +7833,18 @@ "requires": { "figgy-pudding": "^3.5.1" } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -8285,9 +8074,9 @@ } }, "minizlib": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz", - "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "requires": { "minipass": "^2.2.1" @@ -8394,14 +8183,14 @@ }, "mute-stream": { "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "resolved": "http://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==" + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" }, "nanomatch": { "version": "1.2.13", @@ -8541,9 +8330,9 @@ } }, "node-releases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.4.tgz", - "integrity": "sha512-GqRV9GcHw8JCRDaP/JoeNMNzEGzHAknMvIHqMb2VeTOmg1Cf9+ej8bkV12tHfzWHQMCkQ5zUFgwFUkfraynNCw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.2.tgz", + "integrity": "sha512-j1gEV/zX821yxdWp/1vBMN0pSUjuH9oGUdLCb4PfUko6ZW7KdRs3Z+QGGwDUhYtSpQvdVVyLd2V0YvLsmdg5jQ==", "dev": true, "requires": { "semver": "^5.3.0" @@ -8600,7 +8389,7 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true, "optional": true @@ -8855,9 +8644,9 @@ } }, "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "version": "5.3.0", + "resolved": "http://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -9029,25 +8818,36 @@ }, "dependencies": { "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + } } }, "get-stream": { @@ -9087,6 +8887,12 @@ "once": "^1.3.1" } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -9111,6 +8917,12 @@ "yallist": "^3.0.2" } }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", @@ -9120,9 +8932,9 @@ } }, "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", + "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", "dev": true }, "parallel-transform": { @@ -9188,10 +9000,9 @@ } }, "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" }, "parse5-html-rewriting-stream": { "version": "5.1.0", @@ -9200,13 +9011,6 @@ "requires": { "parse5": "^5.1.0", "parse5-sax-parser": "^5.1.0" - }, - "dependencies": { - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" - } } }, "parse5-sax-parser": { @@ -9215,13 +9019,6 @@ "integrity": "sha512-VEhdEDhBkoSILPmsZ96SoIIUow3hZbtgQsqXw7r8DxxnqsCIO0fwkT9mWgBcf9SPjVUh92liuEprHrrYzXBPWQ==", "requires": { "parse5": "^5.1.0" - }, - "dependencies": { - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" - } } }, "parseqs": { @@ -9255,7 +9052,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -9299,6 +9096,13 @@ "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", "requires": { "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } } }, "path-type": { @@ -9514,27 +9318,6 @@ "bytebuffer": "~5", "glob": "^7.0.5", "yargs": "^3.10.0" - }, - "dependencies": { - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yargs": { - "version": "3.32.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - } } }, "protoduck": { @@ -9636,6 +9419,12 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", @@ -9647,14 +9436,14 @@ }, "supports-color": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, "webdriver-manager": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.0.tgz", - "integrity": "sha512-oEc5fmkpz6Yh6udhwir5m0eN5mgRPq9P/NU5YWuT3Up5slt6Zz+znhLU7q4+8rwCZz/Qq3Fgpr/4oao7NPCm2A==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.1.tgz", + "integrity": "sha512-L9TEQmZs6JbMMRQI1w60mfps265/NCr0toYJl7p/R2OAk6oXAfwI6jqYP7EWae+d7Ad2S2Aj4+rzxoSjqk3ZuA==", "dev": true, "requires": { "adm-zip": "^0.4.9", @@ -9701,9 +9490,9 @@ "dev": true }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, "public-encrypt": { @@ -9763,9 +9552,9 @@ }, "dependencies": { "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -9884,11 +9673,22 @@ "http-errors": "1.6.3", "iconv-lite": "0.4.23", "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "raw-loader": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", "dev": true }, @@ -9982,13 +9782,6 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - } } }, "readdirp": { @@ -10059,7 +9852,7 @@ }, "regexpu-core": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { @@ -10076,7 +9869,7 @@ }, "regjsparser": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { @@ -10169,7 +9962,7 @@ }, "resolve": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, @@ -10294,6 +10087,37 @@ "lodash": "^4.0.0", "scss-tokenizer": "^0.2.3", "yargs": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + } } }, "sass-loader": { @@ -10398,9 +10222,9 @@ } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", "dev": true }, "semver-dsl": { @@ -10451,9 +10275,9 @@ } }, "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", "dev": true }, "serve-index": { @@ -10649,6 +10473,11 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -10816,6 +10645,17 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" + }, + "dependencies": { + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } } }, "sockjs-client": { @@ -10841,15 +10681,6 @@ "ms": "^2.1.1" } }, - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -10885,9 +10716,9 @@ "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==" }, "source-map-loader": { "version": "0.2.4", @@ -10952,9 +10783,9 @@ "dev": true }, "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -10978,9 +10809,9 @@ } }, "spdx-license-ids": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, "spdy": { @@ -11031,14 +10862,14 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", + "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -11107,7 +10938,7 @@ }, "stream-browserify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "requires": { @@ -11185,7 +11016,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -11195,7 +11026,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -11319,9 +11150,9 @@ "dev": true }, "tapable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", - "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", "dev": true }, "tar": { @@ -11337,9 +11168,9 @@ } }, "terser": { - "version": "3.10.12", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.10.12.tgz", - "integrity": "sha512-3ODPC1eVt25EVNb04s/PkHxOmzKBQUF6bwwuR6h2DbEF8/j265Y1UkwNtOk9am/pRxfJ5HPapOlUlO6c16mKQQ==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.13.1.tgz", + "integrity": "sha512-ogyZye4DFqOtMzT92Y3Nxxw8OvXmL39HOALro4fc+EUYFFF9G/kk0znkvwMz6PPYgBtdKAodh3FPR70eugdaQA==", "dev": true, "requires": { "commander": "~2.17.1", @@ -11372,24 +11203,24 @@ }, "dependencies": { "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" } }, @@ -11423,6 +11254,15 @@ "path-exists": "^3.0.0" } }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -11442,9 +11282,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -11498,6 +11338,18 @@ "requires": { "figgy-pudding": "^3.5.1" } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -11674,9 +11526,9 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tslint": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", - "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.0.tgz", + "integrity": "sha512-CKEcH1MHUBhoV43SA/Jmy1l24HJJgI0eyLbBNSRyFlsQvb9v6Zdq+Nz2vEOH00nC5SUx4SneJ59PZUS/ARcokQ==", "dev": true, "requires": { "babel-code-frame": "^6.22.0", @@ -11694,12 +11546,12 @@ }, "dependencies": { "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } } } @@ -11715,7 +11567,7 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -11929,11 +11781,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" } } }, @@ -12006,7 +11853,7 @@ "dependencies": { "lru-cache": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", "dev": true } @@ -12076,7 +11923,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -12280,6 +12127,19 @@ } } }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -12298,6 +12158,21 @@ "xregexp": "4.0.0" } }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -12307,6 +12182,15 @@ "locate-path": "^3.0.0" } }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "invert-kv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", @@ -12345,20 +12229,20 @@ "dev": true }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -12379,6 +12263,16 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -12637,10 +12531,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "2.1.2", @@ -12649,41 +12542,17 @@ "dev": true }, "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "optional": true, + "version": "3.32.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", + "camelcase": "^2.0.1", + "cliui": "^3.0.3", "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true, - "optional": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true, - "optional": true - } + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" } }, "yargs-parser": { diff --git a/package.json b/package.json index bf2f4204d..cce7076b4 100644 --- a/package.json +++ b/package.json @@ -17,21 +17,21 @@ }, "private": true, "dependencies": { - "@angular/common": "~7.1.3", - "@angular/core": "~7.1.3", + "@angular/common": "~7.1.0", + "@angular/core": "~7.1.0", "@angular/fire": "^5.1.1", - "@angular/forms": "~7.1.3", + "@angular/forms": "~7.1.0", "@angular/http": "~7.1.0", - "@angular/platform-browser": "7.1.3", - "@angular/platform-browser-dynamic": "7.1.3", + "@angular/platform-browser": "7.1.0", + "@angular/platform-browser-dynamic": "7.1.0", "@angular/pwa": "0.11.0", - "@angular/router": "7.1.3", + "@angular/router": "7.1.0", "@angular/service-worker": "~7.1.0", "@ionic-native/core": "5.0.0-beta.15", "@ionic-native/in-app-browser": "5.0.0-beta.15", "@ionic-native/splash-screen": "5.0.0-beta.15", "@ionic-native/status-bar": "5.0.0-beta.15", - "@ionic/angular": "4.0.0-beta.19", + "@ionic/angular": "^4.0.0-beta.16", "@ionic/storage": "^2.1.3", "angularfire2": "^5.1.1", "cordova-android": "^7.0.0", @@ -52,11 +52,11 @@ "devDependencies": { "@angular-devkit/architect": "0.11.0", "@angular-devkit/build-angular": "0.11.0", - "@angular-devkit/core": "7.1.2", - "@angular-devkit/schematics": "7.1.2", + "@angular-devkit/core": "7.1.0", + "@angular-devkit/schematics": "7.1.0", "@angular/cli": "7.1.0", - "@angular/compiler": "7.1.3", - "@angular/compiler-cli": "7.1.3", + "@angular/compiler": "7.1.0", + "@angular/compiler-cli": "7.1.0", "@angular/language-service": "~7.1.0", "@ionic/angular-toolkit": "1.2.0", "@ionic/lab": "^1.0.0", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 0b9bb3fdd..e59c938fd 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,6 +1,6 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -import { CheckTutorial } from './providers/check-tutorial.service'; +// import { CheckTutorial } from './providers/check-tutorial.service'; const routes: Routes = [ { @@ -31,7 +31,7 @@ const routes: Routes = [ { path: 'tutorial', loadChildren: './pages/tutorial/tutorial.module#TutorialModule', - canLoad: [CheckTutorial] + // canLoad: [CheckTutorial] } ]; diff --git a/src/app/app.component.ts b/src/app/app.component.ts index bb3ae64d1..eaf41a7db 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -17,22 +17,22 @@ export class AppComponent implements OnInit { appPages = [ { title: 'Schedule', - url: '/app/tabs/schedule', + url: '/app/tabs/(schedule:schedule)', icon: 'calendar' }, { title: 'Speakers', - url: '/app/tabs/speakers', + url: '/app/tabs/(speakers:speakers)', icon: 'contacts' }, { title: 'Map', - url: '/app/tabs/map', + url: '/app/tabs/(map:map)', icon: 'map' }, { title: 'About', - url: '/app/tabs/about', + url: '/app/tabs/(about:about)', icon: 'information-circle' } ]; @@ -89,6 +89,10 @@ export class AppComponent implements OnInit { }); } + navigate(url: string) { + return this.router.navigateByUrl(url); + } + logout() { this.userData.logout().then(() => { return this.openTutorial(); @@ -97,7 +101,7 @@ export class AppComponent implements OnInit { openTutorial() { this.menu.enable(false); - this.storage.set('ion_did_tutorial', false); + this.storage.set('ion_did_tutorial', 'false'); this.router.navigateByUrl('/tutorial'); } } diff --git a/src/app/pages/about/about.ts b/src/app/pages/about/about.ts index 5d2e3b301..3e5fb0363 100644 --- a/src/app/pages/about/about.ts +++ b/src/app/pages/about/about.ts @@ -8,6 +8,7 @@ import { PopoverPage } from '../about-popover/about-popover'; selector: 'page-about', templateUrl: 'about.html', styleUrls: ['./about.scss'], + encapsulation: ViewEncapsulation.None }) export class AboutPage { conferenceDate = '2047-05-17'; diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 48ce63db6..25cb408a1 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -9,6 +9,7 @@ import { User } from '../../models'; selector: 'page-account', templateUrl: 'account.html', styleUrls: ['./account.scss'], + encapsulation: ViewEncapsulation.None }) export class AccountPage implements AfterViewInit { users: User[]; diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 998e8b127..6f747691d 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -32,6 +32,7 @@ export class LoginPage implements OnInit { if (user) { if (user.password === this.password) { this.userData.login(user); + // this.router.navigateByUrl('/app/tabs/schedule') this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } else { alert('Invalid password. Try again.'); diff --git a/src/app/pages/schedule-filter/schedule-filter.ts b/src/app/pages/schedule-filter/schedule-filter.ts index db1904507..e2bc7692d 100644 --- a/src/app/pages/schedule-filter/schedule-filter.ts +++ b/src/app/pages/schedule-filter/schedule-filter.ts @@ -9,6 +9,7 @@ import { User } from '../../models'; selector: 'page-schedule-filter', templateUrl: 'schedule-filter.html', styleUrls: ['./schedule-filter.scss'], + encapsulation: ViewEncapsulation.None }) export class ScheduleFilterPage implements AfterViewInit { user: User; diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 07ae93a13..d29b3f3f2 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -1,6 +1,6 @@ -import { Component, ViewChild, OnInit } from '@angular/core'; +import { Component, ViewChild, OnInit, ViewEncapsulation } from '@angular/core'; import { Router } from '@angular/router'; -import { AlertController, IonList, LoadingController, ModalController, ToastController } from '@ionic/angular'; +import { AlertController, List, LoadingController, ModalController, ToastController } from '@ionic/angular'; import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; import { ScheduleTrackPage } from '../schedule-track/schedule-track'; @@ -12,10 +12,11 @@ import { User, Session, PartOfDay } from '../../models'; selector: 'page-schedule', templateUrl: 'schedule.html', styleUrls: ['./schedule.scss'], + encapsulation: ViewEncapsulation.None }) export class SchedulePage implements OnInit { // Gets a reference to the list element - @ViewChild('scheduleList') scheduleList: IonList; + @ViewChild('scheduleList') scheduleList: List; user: User; queryText = ''; @@ -184,7 +185,13 @@ export class SchedulePage implements OnInit { } } - async addFavorite(slidingItem: HTMLIonItemSlidingElement, sessionData: any) { + goToSessionDetail(sessionData: any) { + // go to the session detail page + // and pass in the session data + this.router.navigateByUrl(`app/tabs/(schedule:session/${sessionData.id})`); + } + +async addFavorite(slidingItem: HTMLIonItemSlidingElement, sessionData: any) { if (this.userProvider.hasFavorite(sessionData.name)) { // woops, they already favorited it! What shall we do!? // prompt them to remove it diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 57ec3bb23..627623bc4 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -10,6 +10,7 @@ import { User, Track } from '../../models'; selector: 'page-signup', templateUrl: 'signup.html', styleUrls: ['./signup.scss'], + encapsulation: ViewEncapsulation.None }) export class SignupPage implements OnInit { users: User[]; diff --git a/src/app/pages/speaker-list/speaker-list.html b/src/app/pages/speaker-list/speaker-list.html index 05cd974a4..6cc008fa4 100644 --- a/src/app/pages/speaker-list/speaker-list.html +++ b/src/app/pages/speaker-list/speaker-list.html @@ -14,7 +14,7 @@ - + Speaker profile pic @@ -24,11 +24,11 @@ - +

{{session.name}}

- +

About {{speaker.name}}

diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index 876bf997f..ae6b943ec 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -10,6 +10,7 @@ import { SpeakerData } from '../../providers/speaker-data'; selector: 'page-speaker-list', templateUrl: 'speaker-list.html', styleUrls: ['./speaker-list.scss'], + encapsulation: ViewEncapsulation.None }) export class SpeakerListPage { speakers: Speaker[]; diff --git a/src/app/pages/support/support.ts b/src/app/pages/support/support.ts index 35ac30d3c..d32db0846 100644 --- a/src/app/pages/support/support.ts +++ b/src/app/pages/support/support.ts @@ -10,6 +10,7 @@ import { SupportData } from '../../providers/support-data'; selector: 'page-support', templateUrl: 'support.html', styleUrls: ['./support.scss'], + encapsulation: ViewEncapsulation.None }) export class SupportPage { isLoggedIn = false; @@ -42,26 +43,4 @@ export class SupportPage { await toast.present(); } } - - // If the user enters text in the support question and then navigates - // without submitting first, ask if they meant to leave the page - // async ionViewCanLeave(): Promise { - // // If the support message is empty we should just navigate - // if (!this.supportMessage || this.supportMessage.trim().length === 0) { - // return true; - // } - - // return new Promise((resolve: any, reject: any) => { - // const alert = await this.alertCtrl.create({ - // title: 'Leave this page?', - // message: 'Are you sure you want to leave this page? Your support message will not be submitted.', - // buttons: [ - // { text: 'Stay', handler: reject }, - // { text: 'Leave', role: 'cancel', handler: resolve } - // ] - // }); - - // await alert.present(); - // }); - // } } diff --git a/src/app/pages/tabs-page/tabs-page-routing.module.ts b/src/app/pages/tabs-page/tabs-page-routing.module.ts index fa31409c5..6ebfeac42 100644 --- a/src/app/pages/tabs-page/tabs-page-routing.module.ts +++ b/src/app/pages/tabs-page/tabs-page-routing.module.ts @@ -1,7 +1,14 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; + import { TabsPage } from './tabs-page'; + +import { AboutPage } from '../about/about'; +import { MapPage } from '../map/map'; import { SchedulePage } from '../schedule/schedule'; +import { SessionDetailPage } from '../session-detail/session-detail'; +import { SpeakerDetailPage } from '../speaker-detail/speaker-detail'; +import { SpeakerListPage } from '../speaker-list/speaker-list'; const routes: Routes = [ @@ -9,58 +16,44 @@ const routes: Routes = [ path: 'tabs', component: TabsPage, children: [ + // tab one { path: 'schedule', - children: [ - { - path: '', - component: SchedulePage, - }, - { - path: 'session/:sessionId', - loadChildren: '../session-detail/session-detail.module#SessionDetailModule' - } - ] + component: SchedulePage, + outlet: 'schedule' + }, + { + path: 'session/:sessionId', + component: SessionDetailPage, + outlet: 'schedule' }, + // tab two { path: 'speakers', - children: [ - { - path: '', - loadChildren: '../speaker-list/speaker-list.module#SpeakerListModule' - }, - { - path: 'session/:sessionId', - loadChildren: '../session-detail/session-detail.module#SessionDetailModule' - }, - { - path: 'speaker-details/:speakerId', - loadChildren: '../speaker-detail/speaker-detail.module#SpeakerDetailModule' - } - ] + component: SpeakerListPage, + outlet: 'speakers' }, { - path: 'map', - children: [ - { - path: '', - loadChildren: '../map/map.module#MapModule' - } - ] + path: 'session/:sessionId', + component: SessionDetailPage, + outlet: 'speakers' }, { - path: 'about', - children: [ - { - path: '', - loadChildren: '../about/about.module#AboutModule' - } - ] + path: 'speaker-details/:speakerId', + component: SpeakerDetailPage, + outlet: 'speakers' }, + // tab three { - path: '', - redirectTo: '/app/tabs/schedule', - pathMatch: 'full' + path: 'map', + component: MapPage, + outlet: 'map' + }, + // tab four + { + path: 'about', + component: AboutPage, + outlet: 'about' } ] } @@ -71,4 +64,3 @@ const routes: Routes = [ exports: [RouterModule] }) export class TabsPageRoutingModule { } - diff --git a/src/app/pages/tabs-page/tabs-page.html b/src/app/pages/tabs-page/tabs-page.html index d7da8656e..70e29fbb2 100644 --- a/src/app/pages/tabs-page/tabs-page.html +++ b/src/app/pages/tabs-page/tabs-page.html @@ -1,25 +1,41 @@ - + Schedule - + Speakers - + Map - + About + + + + + + + + + + + + + + + + diff --git a/src/app/pages/tutorial/tutorial.ts b/src/app/pages/tutorial/tutorial.ts index 79fc63ca3..9e6751bf7 100644 --- a/src/app/pages/tutorial/tutorial.ts +++ b/src/app/pages/tutorial/tutorial.ts @@ -1,7 +1,7 @@ import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; import { Router } from '@angular/router'; -import { MenuController, IonSlides } from '@ionic/angular'; +import { MenuController, Slides } from '@ionic/angular'; import { Storage } from '@ionic/storage'; @@ -9,11 +9,12 @@ import { Storage } from '@ionic/storage'; selector: 'page-tutorial', templateUrl: 'tutorial.html', styleUrls: ['./tutorial.scss'], + encapsulation: ViewEncapsulation.None }) export class TutorialPage { showSkip = true; - @ViewChild('slides') slides: IonSlides; + @ViewChild('slides') slides: Slides; constructor( public menu: MenuController, @@ -23,7 +24,7 @@ export class TutorialPage { startApp() { this.router - .navigateByUrl('/app/tabs/schedule') + .navigateByUrl('/app/tabs/(speakers:speakers)') .then(() => this.storage.set('ion_did_tutorial', 'true')); } diff --git a/src/index.html b/src/index.html index b6e26a29c..46281cc6b 100644 --- a/src/index.html +++ b/src/index.html @@ -29,7 +29,7 @@ - + From eee79965dfc3eef956a0ab37379e76be5803284d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sat, 29 Dec 2018 16:02:27 -0500 Subject: [PATCH 23/44] added uploading user's avatar to firebase storage. --- src/app/directive/drop-zone.directive.ts | 31 ++++++++ src/app/models.ts | 1 + src/app/pages/account/account.html | 13 +++- src/app/pages/account/account.module.ts | 6 ++ src/app/pages/account/account.ts | 24 +++++-- .../upload-image/upload-image.component.html | 36 ++++++++++ .../upload-image/upload-image.component.scss | 43 +++++++++++ .../upload-image/upload-image.component.ts | 72 +++++++++++++++++++ src/app/pipe/file-size.pipe.ts | 25 +++++++ src/app/providers/speaker-data.ts | 6 +- src/app/providers/user-data.ts | 23 +++++- src/index.html | 2 + 12 files changed, 270 insertions(+), 12 deletions(-) create mode 100644 src/app/directive/drop-zone.directive.ts create mode 100644 src/app/pages/upload-image/upload-image.component.html create mode 100644 src/app/pages/upload-image/upload-image.component.scss create mode 100644 src/app/pages/upload-image/upload-image.component.ts create mode 100644 src/app/pipe/file-size.pipe.ts diff --git a/src/app/directive/drop-zone.directive.ts b/src/app/directive/drop-zone.directive.ts new file mode 100644 index 000000000..10bc775a1 --- /dev/null +++ b/src/app/directive/drop-zone.directive.ts @@ -0,0 +1,31 @@ +import { Directive, HostListener, Output, EventEmitter } from '@angular/core'; + +@Directive({ + selector: '[appDropZone]' +}) +export class DropZoneDirective { + + @Output() dropped = new EventEmitter(); + @Output() hovered = new EventEmitter(); + + constructor() { } + + @HostListener('drop', ['$event']) + onDrop($event) { + $event.preventDefault(); + this.dropped.emit($event.dataTransfer.files); + this.hovered.emit(false); + } + + @HostListener('dragover', ['$event']) + onDragOver($event) { + $event.preventDefault(); + this.hovered.emit(true); + } + + @HostListener('dragleave', ['$event']) + onDragLeave($event) { + $event.preventDefault(); + this.hovered.emit(false); + } +} diff --git a/src/app/models.ts b/src/app/models.ts index d26b7e304..38bea0872 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -41,6 +41,7 @@ export interface Map { export interface User { id?: string; + avatar?: string; username: string; password: string; email: string; diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index f02b75548..aa4511dfd 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -8,12 +8,13 @@ -
- avatar +
+ avatar + avatar

{{user.username}}

- Update Picture + Update Picture Change Username Change Email Change Password @@ -22,4 +23,10 @@

{{user.username}}

{{ jobDescription }}

+ + + diff --git a/src/app/pages/account/account.module.ts b/src/app/pages/account/account.module.ts index da13bb878..ba5a81e63 100644 --- a/src/app/pages/account/account.module.ts +++ b/src/app/pages/account/account.module.ts @@ -4,6 +4,9 @@ import { IonicModule } from '@ionic/angular'; import { AccountPage } from './account'; import { AccountPageRoutingModule } from './account-routing.module'; +import { UploadImageComponent } from '../upload-image/upload-image.component'; +import { FileSizePipe } from '../../pipe/file-size.pipe'; +import { DropZoneDirective } from '../../directive/drop-zone.directive'; @NgModule({ imports: [ @@ -13,6 +16,9 @@ import { AccountPageRoutingModule } from './account-routing.module'; ], declarations: [ AccountPage, + UploadImageComponent, + FileSizePipe, + DropZoneDirective ] }) export class AccountModule { } diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 25cb408a1..10999eaa0 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -15,6 +15,7 @@ export class AccountPage implements AfterViewInit { users: User[]; user: User; succeed: boolean; + loadImage: boolean; jobDescription: string; constructor(public alertCtrl: AlertController, @@ -25,13 +26,26 @@ export class AccountPage implements AfterViewInit { this.userProvider.getUsers().subscribe( users => this.users = users ); - this.userProvider.getUser().then( - user => this.user = user - ); + this.userProvider.getUserId().then(id => { + this.userProvider.getUserById(id).then(data => { this.user = data; }); + }); + } + + updatePicture(path: string) { + const oldUrl = this.user.avatar; + const id = this.user.id; + + this.user.avatar = path; + this.userProvider.updateUser(this.user); + + this.loadImage = false; + this.user = null; + this.userProvider.getUserById(id).then(data => { this.user = data; }); + this.userProvider.deleteUrl(oldUrl); } - updatePicture() { - console.log('Clicked to update picture'); + onExit() { + this.loadImage = false; } // Present an alert with the current username populated diff --git a/src/app/pages/upload-image/upload-image.component.html b/src/app/pages/upload-image/upload-image.component.html new file mode 100644 index 000000000..aa9c48248 --- /dev/null +++ b/src/app/pages/upload-image/upload-image.component.html @@ -0,0 +1,36 @@ +
Upload User's Avatar
+
+ +

Image Drop Zone

+

Drag and Drop a File

+
+ +
+ +
+ +
+ + + {{ pct | number }}% +
+ +
+ {{ snap.bytesTransferred | fileSize }} of {{ snap.totalBytes | fileSize }} +
diff --git a/src/app/pages/upload-image/upload-image.component.scss b/src/app/pages/upload-image/upload-image.component.scss new file mode 100644 index 000000000..3c4bf3bd1 --- /dev/null +++ b/src/app/pages/upload-image/upload-image.component.scss @@ -0,0 +1,43 @@ +.title { + font-size: 1.4em; + margin-top: 40px; +} + +.dropzone { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + font-weight: 200; + height: 300px; + border: 2px dashed #f16624; + border-radius: 5px; + background: white; + margin: 40px 0; + + &.hovering { + border: 2px solid #f16624; + color: #dadada !important; + } + + .file-label { + font-size: 1em; + } +} + +progress::-webkit-progress-value { + transition: width 0.1s ease; +} + +img { + width: 250px +} + +button { + padding: 10px; + width: 150px; + font-size: 1em; + font-weight: 400; + background-color: #f16624; + color: white +} diff --git a/src/app/pages/upload-image/upload-image.component.ts b/src/app/pages/upload-image/upload-image.component.ts new file mode 100644 index 000000000..c8005536c --- /dev/null +++ b/src/app/pages/upload-image/upload-image.component.ts @@ -0,0 +1,72 @@ +import { Component, Output, Input, EventEmitter } from '@angular/core'; +import { AngularFireStorage, AngularFireUploadTask } from 'angularfire2/storage'; +import { AngularFirestore } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Component({ + selector: 'upload-image', + templateUrl: './upload-image.component.html', + styleUrls: ['./upload-image.component.scss'] +}) +export class UploadImageComponent { + + @Input() username: string; + @Output() exit = new EventEmitter(); + @Output() updateUser = new EventEmitter(); + + // Main task + task: AngularFireUploadTask; + + // State for dropzone CSS toggling + isHovering: boolean; + + // Progress monitoring + percentage: Observable; + + snapshot: Observable; + + // constructor(private db: AngularFirestore) { } + constructor(private storage: AngularFireStorage, private db: AngularFirestore) { } + + toggleHover(event: boolean) { + this.isHovering = event; + } + + startUpload(event: FileList) { + // The File object + const file = event.item(0); + + // Client-side validation example + if (!file || file.type.split('/')[0] !== 'image') { + console.error('unsupported file type :( '); + return; + } + + // The storage path + const path = `avatars/${new Date().getTime()}_${file.name}`; + + // Totally optional metadata + const customMetadata = { app: 'My AngularFire-powered PWA!' }; + + // const ref = this.storage.ref(path); + // this.task = ref.put(file, { customMetadata }); + // The main task + this.task = this.storage.upload(path, file, { customMetadata }); + + // Progress monitoring + this.percentage = this.task.percentageChanges(); + this.snapshot = this.task.snapshotChanges().pipe( + tap(snap => { + if (snap.bytesTransferred === snap.totalBytes) { + this.updateUser.emit(path); + } + }) + ); + } + + // Determines if the upload task is active + isActive(snapshot) { + return snapshot.state === 'running' && snapshot.bytesTransferred < snapshot.totalBytes; + } +} diff --git a/src/app/pipe/file-size.pipe.ts b/src/app/pipe/file-size.pipe.ts new file mode 100644 index 000000000..3bc76a88d --- /dev/null +++ b/src/app/pipe/file-size.pipe.ts @@ -0,0 +1,25 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +const FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; +const FILE_SIZE_UNITS_LONG = ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Pettabytes', 'Exabytes', 'Zettabytes', 'Yottabytes']; + +@Pipe({ + name: 'fileSize' +}) +export class FileSizePipe implements PipeTransform { + + transform(sizeInBytes: number, longForm: boolean): string { + const units = longForm + ? FILE_SIZE_UNITS_LONG + : FILE_SIZE_UNITS; + + let power = Math.round(Math.log(sizeInBytes) / Math.log(1024)); + power = Math.min(power, units.length - 1); + + const size = sizeInBytes / Math.pow(1024, power); // size in new units + const formattedSize = Math.round(size * 100) / 100; // keep up to 2 decimals + const unit = units[power]; + + return size ? `${formattedSize} ${unit}` : '0'; + } +} diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts index b76cba822..436966d59 100644 --- a/src/app/providers/speaker-data.ts +++ b/src/app/providers/speaker-data.ts @@ -18,7 +18,7 @@ export class SpeakerData { speaker: Observable ; constructor(private afs: AngularFirestore, - private storage: AngularFireStorage) { + private fireStorage: AngularFireStorage) { this.speakersCollection = this.afs.collection( 'speakers', ref => ref.orderBy('name', 'asc')); } @@ -29,7 +29,7 @@ export class SpeakerData { return response.map(action => { const data = action.payload.doc.data() as Speaker; data.id = action.payload.doc.id; - this.storage.ref(data.profilePic).getDownloadURL().subscribe(url => { + this.fireStorage.ref(data.profilePic).getDownloadURL().subscribe(url => { data.profilePic = url; }); return data; @@ -42,7 +42,7 @@ export class SpeakerData { return this.speakersCollection.doc(id).ref.get() .then(doc => { const speaker = doc.data() as Speaker; - this.storage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { + this.fireStorage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { speaker.profilePic = url; }); return speaker; diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 97e05f8ad..23c082b3a 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -8,6 +8,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { User } from '../models'; +import { AngularFireStorage } from 'angularfire2/storage'; @Injectable({ providedIn: 'root' @@ -16,12 +17,12 @@ export class UserData { usersCollection: AngularFirestoreCollection ; userDoc: AngularFirestoreDocument ; users: Observable ; - user: Observable ; _favorites: string[] = []; HAS_LOGGED_IN = 'hasLoggedIn'; HAS_SEEN_TUTORIAL = 'hasSeenTutorial'; constructor(private afs: AngularFirestore, + private fireStorage: AngularFireStorage, public events: Events, public storage: Storage) { this.usersCollection = this.afs.collection( @@ -93,6 +94,26 @@ export class UserData { }); } + deleteUrl(oldUrl) { + if (oldUrl) { + this.fireStorage.storage.refFromURL(oldUrl).delete(); + } + } + + getUserById(id: string) { + return this.usersCollection.doc(id).ref.get() + .then(doc => { + const user = doc.data() as User; + user.id = id; + if (user.avatar) { + this.fireStorage.ref(user.avatar).getDownloadURL().subscribe(url => { + user.avatar = url; + }); + } + return user; + }); + } + getUser(): Promise { return this.storage.get('user').then(user => user); } diff --git a/src/index.html b/src/index.html index 46281cc6b..3773ebfb0 100644 --- a/src/index.html +++ b/src/index.html @@ -16,6 +16,8 @@ + + From 280b7ea2aba7026e4a28dfdf220fcd641333045d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sat, 29 Dec 2018 16:55:50 -0500 Subject: [PATCH 24/44] fixed 'stylesheet conflicts' --- .../pages/upload-image/upload-image.component.html | 12 +----------- src/index.html | 2 -- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/app/pages/upload-image/upload-image.component.html b/src/app/pages/upload-image/upload-image.component.html index aa9c48248..38bbdb835 100644 --- a/src/app/pages/upload-image/upload-image.component.html +++ b/src/app/pages/upload-image/upload-image.component.html @@ -8,17 +8,7 @@

Image Drop Zone

Drag and Drop a File

- +
diff --git a/src/index.html b/src/index.html index 3773ebfb0..46281cc6b 100644 --- a/src/index.html +++ b/src/index.html @@ -16,8 +16,6 @@ - - From 7020bccc3b688c457812bc0ab90ab24410dd4ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 2 Jan 2019 11:42:14 -0500 Subject: [PATCH 25/44] Just added primary color for ion-toolbar. --- src/app/pages/about/about.html | 2 +- src/app/pages/account/account.html | 2 +- src/app/pages/login/login.html | 2 +- src/app/pages/map/map.html | 2 +- src/app/pages/schedule-filter/schedule-filter.html | 2 +- src/app/pages/schedule-track/schedule-track.html | 2 +- src/app/pages/schedule/schedule.html | 2 +- src/app/pages/session-detail/session-detail.html | 2 +- src/app/pages/signup/signup.html | 2 +- src/app/pages/speaker-detail/speaker-detail.html | 2 +- src/app/pages/speaker-list/speaker-list.html | 2 +- src/app/pages/support/support.html | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/app/pages/about/about.html b/src/app/pages/about/about.html index ebf908aa7..f9c6d4106 100644 --- a/src/app/pages/about/about.html +++ b/src/app/pages/about/about.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index aa4511dfd..3909f0222 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html index 825fd6ee4..b228c32a3 100644 --- a/src/app/pages/login/login.html +++ b/src/app/pages/login/login.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/map/map.html b/src/app/pages/map/map.html index 68d390b2f..b234023b6 100644 --- a/src/app/pages/map/map.html +++ b/src/app/pages/map/map.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/schedule-filter/schedule-filter.html b/src/app/pages/schedule-filter/schedule-filter.html index 4db1879e2..4bb361d3c 100644 --- a/src/app/pages/schedule-filter/schedule-filter.html +++ b/src/app/pages/schedule-filter/schedule-filter.html @@ -1,5 +1,5 @@ - + Cancel diff --git a/src/app/pages/schedule-track/schedule-track.html b/src/app/pages/schedule-track/schedule-track.html index a019a52c7..a499c53c6 100644 --- a/src/app/pages/schedule-track/schedule-track.html +++ b/src/app/pages/schedule-track/schedule-track.html @@ -1,5 +1,5 @@ - + One Track Session diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index 94bcc136c..d04a30178 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/session-detail/session-detail.html b/src/app/pages/session-detail/session-detail.html index 1eb28ebd6..2a77aef36 100644 --- a/src/app/pages/session-detail/session-detail.html +++ b/src/app/pages/session-detail/session-detail.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/signup/signup.html b/src/app/pages/signup/signup.html index b572b2ea5..fd0f2fdeb 100644 --- a/src/app/pages/signup/signup.html +++ b/src/app/pages/signup/signup.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/speaker-detail/speaker-detail.html b/src/app/pages/speaker-detail/speaker-detail.html index 824af706f..1eb361bd7 100644 --- a/src/app/pages/speaker-detail/speaker-detail.html +++ b/src/app/pages/speaker-detail/speaker-detail.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/speaker-list/speaker-list.html b/src/app/pages/speaker-list/speaker-list.html index 6cc008fa4..89bdf002e 100644 --- a/src/app/pages/speaker-list/speaker-list.html +++ b/src/app/pages/speaker-list/speaker-list.html @@ -1,5 +1,5 @@ - + diff --git a/src/app/pages/support/support.html b/src/app/pages/support/support.html index 054ef7c87..44e69e5e2 100644 --- a/src/app/pages/support/support.html +++ b/src/app/pages/support/support.html @@ -1,5 +1,5 @@ - + From 48edaa21a8ce822a9554848dd0b8302df4b569e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Thu, 3 Jan 2019 13:32:29 -0500 Subject: [PATCH 26/44] Added new set of tabs for admin dashboard to manipulate all databases --- src/app/app-routing.module.ts | 8 ++- src/app/app.component.html | 14 ++++- src/app/app.component.ts | 8 +++ src/app/setup/map/map-setup.html | 12 ++++ src/app/setup/map/map-setup.scss | 0 src/app/setup/map/map-setup.ts | 15 +++++ src/app/setup/map/map.module.ts | 26 ++++++++ .../setup/part-of-day/part-of-day-setup.html | 12 ++++ .../setup/part-of-day/part-of-day-setup.scss | 0 .../setup/part-of-day/part-of-day-setup.ts | 15 +++++ .../setup/part-of-day/part-of-day.module.ts | 26 ++++++++ src/app/setup/sessions/sessions-setup.html | 12 ++++ src/app/setup/sessions/sessions-setup.scss | 0 src/app/setup/sessions/sessions-setup.ts | 32 ++++++++++ src/app/setup/sessions/sessions.module.ts | 26 ++++++++ src/app/setup/speakers/speakers-setup.html | 12 ++++ src/app/setup/speakers/speakers-setup.scss | 0 src/app/setup/speakers/speakers-setup.ts | 15 +++++ src/app/setup/speakers/speakers.module.ts | 26 ++++++++ src/app/setup/support/support-setup.html | 12 ++++ src/app/setup/support/support-setup.scss | 0 src/app/setup/support/support-setup.ts | 15 +++++ src/app/setup/support/support.module.ts | 26 ++++++++ .../tabs-setup/tabs-setup-routing.module.ts | 60 ++++++++++++++++++ src/app/setup/tabs-setup/tabs-setup.module.ts | 39 ++++++++++++ src/app/setup/tabs-setup/tabs-setup.page.html | 61 +++++++++++++++++++ src/app/setup/tabs-setup/tabs-setup.page.scss | 0 src/app/setup/tabs-setup/tabs-setup.page.ts | 15 +++++ src/app/setup/tracks/tracks-setup.html | 12 ++++ src/app/setup/tracks/tracks-setup.scss | 0 src/app/setup/tracks/tracks-setup.ts | 15 +++++ src/app/setup/tracks/tracks.module.ts | 26 ++++++++ 32 files changed, 536 insertions(+), 4 deletions(-) create mode 100644 src/app/setup/map/map-setup.html create mode 100644 src/app/setup/map/map-setup.scss create mode 100644 src/app/setup/map/map-setup.ts create mode 100644 src/app/setup/map/map.module.ts create mode 100644 src/app/setup/part-of-day/part-of-day-setup.html create mode 100644 src/app/setup/part-of-day/part-of-day-setup.scss create mode 100644 src/app/setup/part-of-day/part-of-day-setup.ts create mode 100644 src/app/setup/part-of-day/part-of-day.module.ts create mode 100644 src/app/setup/sessions/sessions-setup.html create mode 100644 src/app/setup/sessions/sessions-setup.scss create mode 100644 src/app/setup/sessions/sessions-setup.ts create mode 100644 src/app/setup/sessions/sessions.module.ts create mode 100644 src/app/setup/speakers/speakers-setup.html create mode 100644 src/app/setup/speakers/speakers-setup.scss create mode 100644 src/app/setup/speakers/speakers-setup.ts create mode 100644 src/app/setup/speakers/speakers.module.ts create mode 100644 src/app/setup/support/support-setup.html create mode 100644 src/app/setup/support/support-setup.scss create mode 100644 src/app/setup/support/support-setup.ts create mode 100644 src/app/setup/support/support.module.ts create mode 100644 src/app/setup/tabs-setup/tabs-setup-routing.module.ts create mode 100644 src/app/setup/tabs-setup/tabs-setup.module.ts create mode 100644 src/app/setup/tabs-setup/tabs-setup.page.html create mode 100644 src/app/setup/tabs-setup/tabs-setup.page.scss create mode 100644 src/app/setup/tabs-setup/tabs-setup.page.ts create mode 100644 src/app/setup/tracks/tracks-setup.html create mode 100644 src/app/setup/tracks/tracks-setup.scss create mode 100644 src/app/setup/tracks/tracks-setup.ts create mode 100644 src/app/setup/tracks/tracks.module.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e59c938fd..e2509bfdc 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,6 +1,5 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; -// import { CheckTutorial } from './providers/check-tutorial.service'; const routes: Routes = [ { @@ -30,8 +29,11 @@ const routes: Routes = [ }, { path: 'tutorial', - loadChildren: './pages/tutorial/tutorial.module#TutorialModule', - // canLoad: [CheckTutorial] + loadChildren: './pages/tutorial/tutorial.module#TutorialModule' + }, + { + path: 'setup', + loadChildren: './setup/tabs-setup/tabs-setup.module#TabsSetupPageModule' } ]; diff --git a/src/app/app.component.html b/src/app/app.component.html index d79c1b7c1..3a1c2ac8f 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -91,7 +91,19 @@ - + + + Configuration + + + + + Set Up + + + + + Tutorial diff --git a/src/app/app.component.ts b/src/app/app.component.ts index eaf41a7db..834aba48d 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -37,6 +37,7 @@ export class AppComponent implements OnInit { } ]; loggedIn = false; + keyword: string; constructor( private events: Events, @@ -72,6 +73,9 @@ export class AppComponent implements OnInit { updateLoggedInStatus(loggedIn: boolean) { setTimeout(() => { this.loggedIn = loggedIn; + this.userData.getUser().then(user => { + this.keyword = user ? user.username : '' ; + }); }, 300); } @@ -99,6 +103,10 @@ export class AppComponent implements OnInit { }); } + onSetup() { + this.router.navigateByUrl('/setup/tabs/(sessions:sessions)'); + } + openTutorial() { this.menu.enable(false); this.storage.set('ion_did_tutorial', 'false'); diff --git a/src/app/setup/map/map-setup.html b/src/app/setup/map/map-setup.html new file mode 100644 index 000000000..ab591f34e --- /dev/null +++ b/src/app/setup/map/map-setup.html @@ -0,0 +1,12 @@ + + + + + + Map + + + + + + diff --git a/src/app/setup/map/map-setup.scss b/src/app/setup/map/map-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/map/map-setup.ts b/src/app/setup/map/map-setup.ts new file mode 100644 index 000000000..4e66cdf87 --- /dev/null +++ b/src/app/setup/map/map-setup.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'map-setup', + templateUrl: './map-setup.html', + styleUrls: ['./map-setup.scss'], +}) +export class MapSetup implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/map/map.module.ts b/src/app/setup/map/map.module.ts new file mode 100644 index 000000000..41e2acdb7 --- /dev/null +++ b/src/app/setup/map/map.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { MapSetup } from './map-setup'; + +const routes: Routes = [ + { + path: '', + component: MapSetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [MapSetup] +}) +export class MapSetupModule {} diff --git a/src/app/setup/part-of-day/part-of-day-setup.html b/src/app/setup/part-of-day/part-of-day-setup.html new file mode 100644 index 000000000..60316845a --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-setup.html @@ -0,0 +1,12 @@ + + + + + + Part of Day + + + + + + diff --git a/src/app/setup/part-of-day/part-of-day-setup.scss b/src/app/setup/part-of-day/part-of-day-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/part-of-day/part-of-day-setup.ts b/src/app/setup/part-of-day/part-of-day-setup.ts new file mode 100644 index 000000000..9dbf8f583 --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-setup.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'part-of-day', + templateUrl: './part-of-day-setup.html', + styleUrls: ['./part-of-day-setup.scss'], +}) +export class PartOfDaySetup implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/part-of-day/part-of-day.module.ts b/src/app/setup/part-of-day/part-of-day.module.ts new file mode 100644 index 000000000..4c4531b57 --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PartOfDaySetup } from './part-of-day-setup'; + +const routes: Routes = [ + { + path: '', + component: PartOfDaySetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [PartOfDaySetup] +}) +export class PartOfDaySetupModule {} diff --git a/src/app/setup/sessions/sessions-setup.html b/src/app/setup/sessions/sessions-setup.html new file mode 100644 index 000000000..cffec4601 --- /dev/null +++ b/src/app/setup/sessions/sessions-setup.html @@ -0,0 +1,12 @@ + + + + + + Sessions + + + + + + diff --git a/src/app/setup/sessions/sessions-setup.scss b/src/app/setup/sessions/sessions-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/sessions/sessions-setup.ts b/src/app/setup/sessions/sessions-setup.ts new file mode 100644 index 000000000..31c35f953 --- /dev/null +++ b/src/app/setup/sessions/sessions-setup.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import { UserData } from '../../providers/user-data'; +import { MenuController } from '@ionic/angular'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'sessions', + templateUrl: './sessions-setup.html', + styleUrls: ['./sessions-setup.scss'], +}) +export class SessionsSetup implements OnInit { + + constructor(private userData: UserData, + public menu: MenuController, + private router: Router) { } + + ngOnInit() { + } + + ionViewWillEnter() { + this.userData.getUser().then(user => { + if ( !user || user.username !== 'admin') { + this.router.navigateByUrl('/tutorial'); + } + }); + // this.menu.enable(false); + } + + ionViewDidLeave() { + // this.menu.enable(true); + } +} diff --git a/src/app/setup/sessions/sessions.module.ts b/src/app/setup/sessions/sessions.module.ts new file mode 100644 index 000000000..e61aa20ca --- /dev/null +++ b/src/app/setup/sessions/sessions.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { SessionsSetup } from './sessions-setup'; + +const routes: Routes = [ + { + path: '', + component: SessionsSetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [SessionsSetup] +}) +export class SessionsSetupModule {} diff --git a/src/app/setup/speakers/speakers-setup.html b/src/app/setup/speakers/speakers-setup.html new file mode 100644 index 000000000..adc59cd9d --- /dev/null +++ b/src/app/setup/speakers/speakers-setup.html @@ -0,0 +1,12 @@ + + + + + + Speakers + + + + + + diff --git a/src/app/setup/speakers/speakers-setup.scss b/src/app/setup/speakers/speakers-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/speakers/speakers-setup.ts b/src/app/setup/speakers/speakers-setup.ts new file mode 100644 index 000000000..2c5669da3 --- /dev/null +++ b/src/app/setup/speakers/speakers-setup.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'speakers-setup', + templateUrl: './speakers-setup.html', + styleUrls: ['./speakers-setup.scss'], +}) +export class SpeakersSetup implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/speakers/speakers.module.ts b/src/app/setup/speakers/speakers.module.ts new file mode 100644 index 000000000..6e299c91f --- /dev/null +++ b/src/app/setup/speakers/speakers.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { SpeakersSetup } from './speakers-setup'; + +const routes: Routes = [ + { + path: '', + component: SpeakersSetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [SpeakersSetup] +}) +export class SpeakersSetupModule {} diff --git a/src/app/setup/support/support-setup.html b/src/app/setup/support/support-setup.html new file mode 100644 index 000000000..6250660cc --- /dev/null +++ b/src/app/setup/support/support-setup.html @@ -0,0 +1,12 @@ + + + + + + Support + + + + + + diff --git a/src/app/setup/support/support-setup.scss b/src/app/setup/support/support-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/support/support-setup.ts b/src/app/setup/support/support-setup.ts new file mode 100644 index 000000000..9dd6c8f81 --- /dev/null +++ b/src/app/setup/support/support-setup.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'support', + templateUrl: './support-setup.html', + styleUrls: ['./support-setup.scss'], +}) +export class SupportSetup implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/support/support.module.ts b/src/app/setup/support/support.module.ts new file mode 100644 index 000000000..860304a42 --- /dev/null +++ b/src/app/setup/support/support.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { SupportSetup } from './support-setup'; + +const routes: Routes = [ + { + path: '', + component: SupportSetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [SupportSetup] +}) +export class SupportSetupModule {} diff --git a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts new file mode 100644 index 000000000..e7304a375 --- /dev/null +++ b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts @@ -0,0 +1,60 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { TabsSetupPage } from './tabs-setup.page'; +import { SessionsSetup } from '../sessions/sessions-setup'; +import { SpeakersSetup } from '../speakers/speakers-setup'; +import { TracksSetup } from '../tracks/tracks-setup'; +import { MapSetup } from '../map/map-setup'; +import { SupportSetup } from '../support/support-setup'; +import { PartOfDaySetup } from '../part-of-day/part-of-day-setup'; + +const routes: Routes = [ + { + path: 'tabs', component: TabsSetupPage, + children: [ + // tab one + { + path: 'sessions', + component: SessionsSetup, + outlet: 'sessions' + }, + // tab two + { + path: 'speakers', + component: SpeakersSetup, + outlet: 'speakers' + }, + // tab three + { + path: 'tracks', + component: TracksSetup, + outlet: 'tracks' + }, + // tab four + { + path: 'partofday', + component: PartOfDaySetup, + outlet: 'partofday' + }, + // tab five + { + path: 'map', + component: MapSetup, + outlet: 'map' + }, + // tab six + { + path: 'support', + component: SupportSetup, + outlet: 'support' + }, + ] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class TabsSetupRoutingModule { } diff --git a/src/app/setup/tabs-setup/tabs-setup.module.ts b/src/app/setup/tabs-setup/tabs-setup.module.ts new file mode 100644 index 000000000..af1119858 --- /dev/null +++ b/src/app/setup/tabs-setup/tabs-setup.module.ts @@ -0,0 +1,39 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { TabsSetupPage } from './tabs-setup.page'; +import { TabsSetupRoutingModule } from './tabs-setup-routing.module'; +import { SessionsSetupModule } from '../sessions/sessions.module'; +import { SpeakersSetupModule } from '../speakers/speakers.module'; +import { TracksSetupModule } from '../tracks/tracks.module'; +import { MapSetupModule } from '../map/map.module'; +import { SupportSetupModule } from '../support/support.module'; +import { PartOfDaySetupModule } from '../part-of-day/part-of-day.module'; + +const routes: Routes = [ + { + path: '', + component: TabsSetupPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + SessionsSetupModule, + SpeakersSetupModule, + TracksSetupModule, + PartOfDaySetupModule, + MapSetupModule, + SupportSetupModule, + TabsSetupRoutingModule + ], + declarations: [TabsSetupPage] +}) +export class TabsSetupPageModule {} diff --git a/src/app/setup/tabs-setup/tabs-setup.page.html b/src/app/setup/tabs-setup/tabs-setup.page.html new file mode 100644 index 000000000..8c99cc8ca --- /dev/null +++ b/src/app/setup/tabs-setup/tabs-setup.page.html @@ -0,0 +1,61 @@ + + + + + + Sessions + + + + + Speakers + + + + + Tracks + + + + + PartOfDay + + + + + Map + + + + + Support + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/setup/tabs-setup/tabs-setup.page.scss b/src/app/setup/tabs-setup/tabs-setup.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/tabs-setup/tabs-setup.page.ts b/src/app/setup/tabs-setup/tabs-setup.page.ts new file mode 100644 index 000000000..5464c1731 --- /dev/null +++ b/src/app/setup/tabs-setup/tabs-setup.page.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'tabs-setup', + templateUrl: './tabs-setup.page.html', + styleUrls: ['./tabs-setup.page.scss'], +}) +export class TabsSetupPage implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/tracks/tracks-setup.html b/src/app/setup/tracks/tracks-setup.html new file mode 100644 index 000000000..3127e9ed1 --- /dev/null +++ b/src/app/setup/tracks/tracks-setup.html @@ -0,0 +1,12 @@ + + + + + + Tracks + + + + + + diff --git a/src/app/setup/tracks/tracks-setup.scss b/src/app/setup/tracks/tracks-setup.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts new file mode 100644 index 000000000..32058e937 --- /dev/null +++ b/src/app/setup/tracks/tracks-setup.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'tracks', + templateUrl: './tracks-setup.html', + styleUrls: ['./tracks-setup.scss'], +}) +export class TracksSetup implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/setup/tracks/tracks.module.ts b/src/app/setup/tracks/tracks.module.ts new file mode 100644 index 000000000..c014c8a37 --- /dev/null +++ b/src/app/setup/tracks/tracks.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { TracksSetup } from './tracks-setup'; + +const routes: Routes = [ + { + path: '', + component: TracksSetup + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [TracksSetup] +}) +export class TracksSetupModule {} From 0a47b08b3f97511696529b030be5c60ffef2b54b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 4 Jan 2019 03:24:53 -0500 Subject: [PATCH 27/44] Created edit/delete module for 'Tracks' in admin setup --- src/app/pages/account/account.ts | 38 +++++++-- .../pages/schedule-filter/schedule-filter.ts | 5 +- src/app/providers/conference-data.ts | 23 +++++ src/app/providers/session-data.ts | 30 ++++++- src/app/providers/user-data.ts | 29 ++++++- src/app/setup/tracks/tracks-setup.html | 12 +++ src/app/setup/tracks/tracks-setup.ts | 84 ++++++++++++++++++- 7 files changed, 201 insertions(+), 20 deletions(-) diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 10999eaa0..581b04229 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -36,7 +36,7 @@ export class AccountPage implements AfterViewInit { const id = this.user.id; this.user.avatar = path; - this.userProvider.updateUser(this.user); + this.updateUserData(this.user); this.loadImage = false; this.user = null; @@ -63,8 +63,12 @@ export class AccountPage implements AfterViewInit { if (this.isTheValueUsed(data.username)) { alert(data.username + ' was used already. Try another.'); } else { + // update after getter user's avatar as string. + this.userProvider.getUser().then(user => { + user.username = data.username; + this.updateUserData(user); + }); this.user.username = data.username; - this.userProvider.updateUser(this.user); this.succeed = true; this.jobDescription = 'Username has been changed.'; } @@ -78,7 +82,8 @@ export class AccountPage implements AfterViewInit { value: this.user.username, placeholder: 'new username' } - ] + ], + backdropDismiss: false }); await changeForm.present(); } @@ -95,8 +100,11 @@ export class AccountPage implements AfterViewInit { if (this.isTheValueUsed(data.email)) { alert(data.email + ' was used already. Try another.'); } else { - this.user.email = data.email; - this.userProvider.updateUser(this.user); + // update after getter user's avatar as string. + this.userProvider.getUser().then(user => { + this.user.email = data.email; + this.updateUserData(user); + }); this.succeed = true; this.jobDescription = 'Email has been changed.'; } @@ -110,7 +118,8 @@ export class AccountPage implements AfterViewInit { value: this.user.email, placeholder: 'new email' } - ] + ], + backdropDismiss: false }); await changeForm.present(); } @@ -131,8 +140,11 @@ export class AccountPage implements AfterViewInit { } else if (data.newPW !== data.confirmPW) { alert('New password does not match Confirm password.'); } else { - this.user.password = data.newPW; - this.userProvider.updateUser(this.user); + // update after getter user's avatar as string. + this.userProvider.getUser().then(user => { + this.user.password = data.newPW; + this.updateUserData(user); + }); this.succeed = true; this.jobDescription = 'Password has been changed.'; } @@ -155,7 +167,8 @@ export class AccountPage implements AfterViewInit { name: 'currentPW', placeholder: 'current password' } - ] + ], + backdropDismiss: false }); await changeForm.present(); } @@ -169,6 +182,13 @@ export class AccountPage implements AfterViewInit { user => user.email.toLowerCase() === value.toLowerCase()); } + updateUserData(user) { + // update logged user info after update user's database + this.userProvider.setUser(user).then(() => { + this.userProvider.updateUser(user); + }); + } + logout() { this.userProvider.logout(); this.router.navigateByUrl('/login'); diff --git a/src/app/pages/schedule-filter/schedule-filter.ts b/src/app/pages/schedule-filter/schedule-filter.ts index e2bc7692d..4d2966c59 100644 --- a/src/app/pages/schedule-filter/schedule-filter.ts +++ b/src/app/pages/schedule-filter/schedule-filter.ts @@ -39,7 +39,10 @@ export class ScheduleFilterPage implements AfterViewInit { applyFilters() { // update user's trackFilter this.user.trackFilter = this.trackFilter; - this.userProvider.updateUser(this.user); + // update loggin user and then update database file. + this.userProvider.setUser(this.user).then(() => { + this.userProvider.updateUser(this.user); + }); // Pass back a new array of track names to exclude const excludedTrackNames = this.trackFilter.filter(c => !c.isChecked).map(c => c.name); diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 82cc9e51f..92f5cfad6 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -7,6 +7,7 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; import { Track, Session, PartOfDay } from '../models'; +import { SessionData } from './session-data'; @Injectable({ providedIn: 'root' @@ -32,6 +33,7 @@ export class ConferenceData { constructor( public http: HttpClient, public userProvider: UserData, + public sessionProvider: SessionData, private afs: AngularFirestore) { this.tracksCollection = this.afs.collection( 'tracks', ref => ref.orderBy('name', 'asc')); @@ -117,6 +119,27 @@ export class ConferenceData { return this.tracks ; } + updateTrack(track: Track, newName: string) { + const oldName = track.name; + track.name = newName; + const id = track.id; + delete(track.id); + this.trackDoc = this.afs.doc(`tracks/${id}`); + this.trackDoc.update(track).then(() => { + this.sessionProvider.updateTrackInSessions(newName, oldName); + this.userProvider.updateTracksInUser(newName, oldName); + }); + } + + removeTrack(track: Track) { + const id = track.id; + this.trackDoc = this.afs.doc(`tracks/${id}`); + this.trackDoc.delete().then(() => { + this.sessionProvider.removeTrackInSession(track.name); + this.userProvider.removeTrackInUser(track.name); + }); + } + getMap() { this.maps = this.mapsCollection.snapshotChanges() .pipe(map(response => { diff --git a/src/app/providers/session-data.ts b/src/app/providers/session-data.ts index f723b31cc..e24f0ea33 100644 --- a/src/app/providers/session-data.ts +++ b/src/app/providers/session-data.ts @@ -42,9 +42,35 @@ export class SessionData { }); } - updateSession(id: string, session: Session) { + updateTrackInSessions(newName: string, oldName: string) { + this.getSessions().subscribe(sessions => { + sessions.forEach(session => { + const idx = session.tracks.findIndex(track => track === oldName); + if (idx > -1) { + session.tracks[idx] = newName; + this.updateSession(session); + } + }); + }); + } + + removeTrackInSession(name: string) { + this.getSessions().subscribe(sessions => { + sessions.forEach(session => { + const idx = session.tracks.findIndex(track => track === name); + if (idx > -1) { + session.tracks.splice(idx, 1); + this.updateSession(session); + } + }); + }); + } + + updateSession(session: Session): Promise { + const id = session.id; + delete(session.id); this.sessionDoc = this.afs.doc(`sessions/${id}`); - this.sessionDoc.update(session); + return this.sessionDoc.update(session); } deleteSession(session: Session) { diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 23c082b3a..1d6a260d3 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -9,6 +9,7 @@ import { map } from 'rxjs/operators'; import { User } from '../models'; import { AngularFireStorage } from 'angularfire2/storage'; +import { CompileShallowModuleMetadata } from '@angular/compiler'; @Injectable({ providedIn: 'root' @@ -87,10 +88,30 @@ export class UserData { const id = user.id; delete(user.id); this.userDoc = this.afs.doc(`users/${id}`); - this.userDoc.update(user) - .then(() => { - user.id = id; - this.storage.set('user', user); + this.userDoc.update(user); + } + + updateTracksInUser(newName: string, oldName: string) { + this.getUsers().subscribe(users => { + users.forEach(user => { + const idx = user.trackFilter.findIndex(track => track.name === oldName); + if (idx > -1) { + user.trackFilter[idx].name = newName; + this.updateUser(user); + } + }); + }); + } + + removeTrackInUser(name) { + this.getUsers().subscribe(users => { + users.forEach(user => { + const idx = user.trackFilter.findIndex(track => track.name === name); + if (idx > -1) { + user.trackFilter.splice(idx, 1); + this.updateUser(user); + } + }); }); } diff --git a/src/app/setup/tracks/tracks-setup.html b/src/app/setup/tracks/tracks-setup.html index 3127e9ed1..74a7dfdcc 100644 --- a/src/app/setup/tracks/tracks-setup.html +++ b/src/app/setup/tracks/tracks-setup.html @@ -4,9 +4,21 @@ Tracks + + Add a New + + + + {{track.name}} + + Edit + + + + diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts index 32058e937..bbea1b330 100644 --- a/src/app/setup/tracks/tracks-setup.ts +++ b/src/app/setup/tracks/tracks-setup.ts @@ -1,15 +1,91 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; +import { UserData } from '../../providers/user-data'; +import { Router } from '@angular/router'; +import { Track, Session } from '../../models'; +import { SessionData } from '../../providers/session-data'; +import { ConferenceData } from '../../providers/conference-data'; +import { AlertController } from '@ionic/angular'; @Component({ selector: 'tracks', templateUrl: './tracks-setup.html', styleUrls: ['./tracks-setup.scss'], }) -export class TracksSetup implements OnInit { +export class TracksSetup { - constructor() { } + tracks: Track[]; + sessions: Session[]; + newName: string; + succeed = false; + jobDescription: string; - ngOnInit() { + constructor(private userData: UserData, + private sessionData: SessionData, + private confData: ConferenceData, + private router: Router, + private alertCtrl: AlertController) { } + + ionViewWillEnter() { + this.userData.getUser().then(user => { + if ( !user || user.username !== 'admin') { + this.router.navigateByUrl('/tutorial'); + } else { + this.confData.getTracks().subscribe(data => { + this.tracks = data; + this.sessionData.getSessions().subscribe(session => { + this.sessions = session; + }); + }); + } + }); } + ionViewDidLeave() {} + + onAddNew() { + console.log('add a new track'); + } + + async changeName(track) { + this.succeed = false; + const changeForm = await this.alertCtrl.create({ + header: 'Change Track', + subHeader: track.name, + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + data.newName = data.newName.trim(); + if (this.isTheValueUsed(data.newName)) { + alert(data.newName + ' was used already. Try another.'); + } else { + this.confData.updateTrack(track, data.newName ); + this.succeed = true; + this.jobDescription = 'Name has been changed.'; + } + } + } + ], + inputs: [ + { + type: 'text', + name: 'newName', + placeholder: 'new name here' + } + ], + backdropDismiss: false + }); + await changeForm.present(); + } + + onRemove(track) { + if (confirm(`Are you sure to delete '${track.name}'?`)) { + this.confData.removeTrack(track); + } + } + + isTheValueUsed(name) { + return this.tracks.find(track => track.name.toLowerCase() === name.toLowerCase()); + } } From 7e6f1ef283237d025e1f3a6e5076878829751b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 4 Jan 2019 20:09:52 -0500 Subject: [PATCH 28/44] Created adding module for 'Tracks' in admin setup. --- src/app/providers/conference-data.ts | 6 +++++ src/app/providers/user-data.ts | 19 +++++++++++++++- src/app/setup/tracks/tracks-setup.html | 2 +- src/app/setup/tracks/tracks-setup.ts | 31 ++++++++++++++++++++++++-- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 92f5cfad6..b5b6e6c24 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -119,6 +119,12 @@ export class ConferenceData { return this.tracks ; } + addTrack(track: Track) { + this.tracksCollection.add(track).then(res => { + this.userProvider.addTrackInUser(track.name); + }); + } + updateTrack(track: Track, newName: string) { const oldName = track.name; track.name = newName; diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 1d6a260d3..917eb916b 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -9,7 +9,6 @@ import { map } from 'rxjs/operators'; import { User } from '../models'; import { AngularFireStorage } from 'angularfire2/storage'; -import { CompileShallowModuleMetadata } from '@angular/compiler'; @Injectable({ providedIn: 'root' @@ -91,6 +90,24 @@ export class UserData { this.userDoc.update(user); } + addTrackInUser(name) { + const track = { name: name, isChecked: false }; + this.getUsers().subscribe(users => { + users.forEach(user => { + const idx = user.trackFilter.findIndex(item => item.name === name); + if (idx < 0) { + user.trackFilter.push(track); + this.updateUser(user); + } + }); + // const len = users.length; + // for (let i=0; i { users.forEach(user => { diff --git a/src/app/setup/tracks/tracks-setup.html b/src/app/setup/tracks/tracks-setup.html index 74a7dfdcc..a960a91f4 100644 --- a/src/app/setup/tracks/tracks-setup.html +++ b/src/app/setup/tracks/tracks-setup.html @@ -5,7 +5,7 @@ Tracks - Add a New + Add a New diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts index bbea1b330..5e21af73d 100644 --- a/src/app/setup/tracks/tracks-setup.ts +++ b/src/app/setup/tracks/tracks-setup.ts @@ -42,8 +42,35 @@ export class TracksSetup { ionViewDidLeave() {} - onAddNew() { - console.log('add a new track'); + async addNewTrack() { + const addForm = await this.alertCtrl.create({ + header: 'Add a Track', + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + data.newName = data.newName.trim(); + if (this.isTheValueUsed(data.newName)) { + alert(data.newName + ' was used already. Try another.'); + } else { + this.confData.addTrack({ name: data.newName }); + this.succeed = true; + this.jobDescription = 'A new Track has been added.'; + } + } + } + ], + inputs: [ + { + type: 'text', + name: 'newName', + placeholder: 'new name here' + } + ], + backdropDismiss: false + }); + await addForm.present(); } async changeName(track) { From e49e416c399de968a88d9eeeaa47deb7719e4f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Fri, 4 Jan 2019 22:42:59 -0500 Subject: [PATCH 29/44] Created UI of 'PartOfDay' module in admin setup. --- .../setup/part-of-day/part-of-day-setup.html | 33 +++++++++++++++++++ .../setup/part-of-day/part-of-day-setup.scss | 8 +++++ .../setup/part-of-day/part-of-day-setup.ts | 15 ++++++++- .../setup/part-of-day/part-of-day.module.ts | 2 +- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/app/setup/part-of-day/part-of-day-setup.html b/src/app/setup/part-of-day/part-of-day-setup.html index 60316845a..27b89ff71 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.html +++ b/src/app/setup/part-of-day/part-of-day-setup.html @@ -4,9 +4,42 @@ Part of Day + + Create a New Set + + + + Index + + + Description + + + From + + + To + + + + + + {{ POD.indexKey }} + + + {{ POD.name }} + + + {{ POD.timeFrom }} + + + {{ POD.timeTo }} + + + diff --git a/src/app/setup/part-of-day/part-of-day-setup.scss b/src/app/setup/part-of-day/part-of-day-setup.scss index e69de29bb..526d594a3 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.scss +++ b/src/app/setup/part-of-day/part-of-day-setup.scss @@ -0,0 +1,8 @@ +.table-header, .table-item { + display: grid; + grid-template-columns: 1fr 3fr 1fr 1fr; + + ion-col { + text-align: left; + } +} diff --git a/src/app/setup/part-of-day/part-of-day-setup.ts b/src/app/setup/part-of-day/part-of-day-setup.ts index 9dbf8f583..d159790c0 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.ts +++ b/src/app/setup/part-of-day/part-of-day-setup.ts @@ -1,4 +1,7 @@ import { Component, OnInit } from '@angular/core'; +import { PartOfDay } from '../../models'; +import { ConferenceData } from '../../providers/conference-data'; +import { Router } from '@angular/router'; @Component({ selector: 'part-of-day', @@ -7,9 +10,19 @@ import { Component, OnInit } from '@angular/core'; }) export class PartOfDaySetup implements OnInit { - constructor() { } + PODs: PartOfDay[]; + + constructor(private confData: ConferenceData, + private router: Router) { } ngOnInit() { + this.confData.getPartsOfDay().subscribe(data => { + this.PODs = data; + }); } + makeNewPOD() { + console.log('open new file here'); + // this.router.navigateByUrl('setup/tabs/(partofday:new)') + } } diff --git a/src/app/setup/part-of-day/part-of-day.module.ts b/src/app/setup/part-of-day/part-of-day.module.ts index 4c4531b57..26e3de437 100644 --- a/src/app/setup/part-of-day/part-of-day.module.ts +++ b/src/app/setup/part-of-day/part-of-day.module.ts @@ -19,7 +19,7 @@ const routes: Routes = [ CommonModule, FormsModule, IonicModule, - RouterModule.forChild(routes) + RouterModule.forChild(routes), ], declarations: [PartOfDaySetup] }) From e15e7c2753cfa0179009853e8e5a9ba872ca68aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sun, 6 Jan 2019 01:35:57 -0500 Subject: [PATCH 30/44] Created edit/create a new set module for 'Parts Of Day' in admin setup --- src/app/models.ts | 1 + src/app/providers/conference-data.ts | 46 +++++-- .../part-of-day-new/part-of-day-new.module.ts | 26 ++++ .../part-of-day-new/part-of-day-new.page.html | 62 ++++++++++ .../part-of-day-new/part-of-day-new.page.scss | 8 ++ .../part-of-day-new/part-of-day-new.page.ts | 114 ++++++++++++++++++ .../setup/part-of-day/part-of-day-setup.html | 7 ++ .../setup/part-of-day/part-of-day-setup.scss | 2 +- .../setup/part-of-day/part-of-day-setup.ts | 40 +++++- .../tabs-setup/tabs-setup-routing.module.ts | 38 ++---- src/app/setup/tabs-setup/tabs-setup.module.ts | 6 +- 11 files changed, 303 insertions(+), 47 deletions(-) create mode 100644 src/app/setup/part-of-day/part-of-day-new/part-of-day-new.module.ts create mode 100644 src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.html create mode 100644 src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.scss create mode 100644 src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts diff --git a/src/app/models.ts b/src/app/models.ts index 38bea0872..59ff72240 100644 --- a/src/app/models.ts +++ b/src/app/models.ts @@ -57,6 +57,7 @@ export interface Support { } export interface PartOfDay { + id?: string; indexKey?: number; name: string; // morning, afternoon, evening, overnight timeFrom: string; diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index b5b6e6c24..1f5293b2f 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -6,7 +6,7 @@ import { AngularFirestore, import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { UserData } from './user-data'; -import { Track, Session, PartOfDay } from '../models'; +import { Track, Session, PartOfDay, Map } from '../models'; import { SessionData } from './session-data'; @Injectable({ @@ -18,15 +18,16 @@ export class ConferenceData { tracks: Observable ; track: Observable ; - sessionsCollection: AngularFirestoreCollection; - sessions: Observable ; - session: Observable ; + sessionsCollection: AngularFirestoreCollection; + sessions: Observable ; + session: Observable ; - partsOfDayCollection: AngularFirestoreCollection; - partsOfDay: Observable; + partsOfDayCollection: AngularFirestoreCollection; + partOfDayDoc: AngularFirestoreDocument; + partsOfDay: Observable; - mapsCollection: AngularFirestoreCollection; - maps: Observable; + mapsCollection: AngularFirestoreCollection; + maps: Observable; data: any; @@ -43,18 +44,19 @@ export class ConferenceData { 'maps', ref => ref.orderBy('name', 'asc')); } - getPartsOfDay(): Observable { + getPartsOfDay(): Observable { this.partsOfDay = this.partsOfDayCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as any; + const data = action.payload.doc.data() as PartOfDay; + data.id = action.payload.doc.id; return data; }); })); return this.partsOfDay ; } - getSessionInPeriod(start, end): Observable { + getSessionInPeriod(start, end): Observable { this.sessionsCollection = this.afs.collection( 'sessions', ref => ref.where('date', '>=', start) .where('date', '<=', end) @@ -62,7 +64,7 @@ export class ConferenceData { this.sessions = this.sessionsCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as any; + const data = action.payload.doc.data() as Session; data.id = action.payload.doc.id; return data; }); @@ -146,11 +148,29 @@ export class ConferenceData { }); } + updatePartOfDay(pod: PartOfDay) { + const id = pod.id; + delete(pod.id); + this.partOfDayDoc = this.afs.doc(`partsOfDay/${id}`); + this.partOfDayDoc.update(pod); + } + + changePartsOfDay(PODs: PartOfDay[], newPODs: PartOfDay[]) { + PODs.forEach(pod => { + const podDoc = this.afs.doc(`partsOfDay/${pod.id}`); + podDoc.delete(); + }); + + newPODs.forEach(pod => { + this.partsOfDayCollection.add(pod); + }); + } + getMap() { this.maps = this.mapsCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as any; + const data = action.payload.doc.data() as Map; return data; }); })); diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.module.ts b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.module.ts new file mode 100644 index 000000000..197c5dcdc --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PartOfDayNewPage } from './part-of-day-new.page'; + +const routes: Routes = [ + { + path: '', + component: PartOfDayNewPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [PartOfDayNewPage] +}) +export class PartOfDayNewPageModule {} diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.html b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.html new file mode 100644 index 000000000..c0267f657 --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.html @@ -0,0 +1,62 @@ + + + + + + New Set of POD + + + + + + + Description: + + + + + From    {{ timeFrom }}    + To     + + + + Cancel + Add POD + + + +
+ + + + Index + + + Description + + + From + + + To + + + + + + + {{ POD.indexKey }} + + + {{ POD.name }} + + + {{ POD.timeFrom }} + + + {{ POD.timeTo }} + + + +
diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.scss b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.scss new file mode 100644 index 000000000..526d594a3 --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.scss @@ -0,0 +1,8 @@ +.table-header, .table-item { + display: grid; + grid-template-columns: 1fr 3fr 1fr 1fr; + + ion-col { + text-align: left; + } +} diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts new file mode 100644 index 000000000..c419fe534 --- /dev/null +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts @@ -0,0 +1,114 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { PartOfDay } from '../../../models'; +import { FunctionlData } from '../../../providers/function-data'; +import { ConferenceData } from '../../../providers/conference-data'; +import { Router } from '@angular/router'; +import { AlertController } from '@ionic/angular'; + +@Component({ + selector: 'part-of-day-new', + templateUrl: './part-of-day-new.page.html', + styleUrls: ['./part-of-day-new.page.scss'], +}) +export class PartOfDayNewPage implements OnInit { + + PODs: PartOfDay[] = []; + newPODs: PartOfDay[] = []; + title = ''; + timeFrom: string; + timeTo: string; + len: number; + + constructor(private cdRef: ChangeDetectorRef, + private alertCtrl: AlertController, + private funProvider: FunctionlData, + private confData: ConferenceData, + private router: Router) { } + + ngOnInit() { + this.confData.getPartsOfDay().subscribe(data => this.PODs = data); + this.setInitialValue(); + } + + setInitialValue() { + this.title = ''; + this.len = this.newPODs.length; + if (this.len === 0) { + this.timeFrom = '00:00'; + } else { + this.timeFrom = this.getNextTime(this.newPODs[this.len - 1].timeTo); + } + this.timeTo = this.getNextTime(this.timeFrom); + } + + getNextTime(time) { + const [h, m] = time.split(':'); + const hour = this.funProvider.reform2digits((m === '59') ? +h + 1 : +h); + const min = this.funProvider.reform2digits((m === '59') ? 0 : +m + 1); + return (hour === '24') ? null : hour + ':' + min ; + } + + cancelInput() { + this.setInitialValue(); + } + + saveInput() { + if (this.isTheValueUsed()) { + alert('Description is not valid. Try again'); + } else { + const newPOD = { + indexKey: this.newPODs.length + 1, + name: this.title, + timeFrom: this.timeFrom, + timeTo: this.timeTo + } as PartOfDay; + this.newPODs.push(newPOD); + if (this.timeTo === '23:59') { + this.presentConfirm(); + } else { + this.setInitialValue(); + } + } + } + + isTheValueUsed() { + this.title = this.title.trim(); + if (this.title === '') { + return true; + } + return this.PODs.find(pod => pod.name.toLowerCase() === this.title.toLowerCase()); + } + + checkTimeTo(value) { + this.cdRef.detectChanges(); + if (value <= this.timeFrom) { + alert('Wrong time for To. Try again.'); + this.timeTo = this.getNextTime(this.timeFrom); + } + } + + async presentConfirm() { + const alert = await this.alertCtrl.create({ + header: 'Confirm Save', + message: 'Done the job. Do you want to save it?', + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + this.router.navigateByUrl('setup/tabs/(partofday:partofday)'); + } + }, + { + text: 'Save', + handler: () => { + this.confData.changePartsOfDay(this.PODs, this.newPODs); + this.router.navigateByUrl('setup/tabs/(partofday:partofday)'); + } + } + ], + backdropDismiss: false + }); + await alert.present(); + } +} diff --git a/src/app/setup/part-of-day/part-of-day-setup.html b/src/app/setup/part-of-day/part-of-day-setup.html index 27b89ff71..cd23966aa 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.html +++ b/src/app/setup/part-of-day/part-of-day-setup.html @@ -24,6 +24,10 @@ To + + Action + + @@ -40,6 +44,9 @@ {{ POD.timeTo }} + + Edit +
diff --git a/src/app/setup/part-of-day/part-of-day-setup.scss b/src/app/setup/part-of-day/part-of-day-setup.scss index 526d594a3..74584060e 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.scss +++ b/src/app/setup/part-of-day/part-of-day-setup.scss @@ -1,6 +1,6 @@ .table-header, .table-item { display: grid; - grid-template-columns: 1fr 3fr 1fr 1fr; + grid-template-columns: 1fr 3fr 1fr 1fr 1fr; ion-col { text-align: left; diff --git a/src/app/setup/part-of-day/part-of-day-setup.ts b/src/app/setup/part-of-day/part-of-day-setup.ts index d159790c0..0d1e1a330 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.ts +++ b/src/app/setup/part-of-day/part-of-day-setup.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { PartOfDay } from '../../models'; import { ConferenceData } from '../../providers/conference-data'; import { Router } from '@angular/router'; +import { AlertController } from '@ionic/angular'; @Component({ selector: 'part-of-day', @@ -13,6 +14,7 @@ export class PartOfDaySetup implements OnInit { PODs: PartOfDay[]; constructor(private confData: ConferenceData, + private alertCtrl: AlertController, private router: Router) { } ngOnInit() { @@ -22,7 +24,41 @@ export class PartOfDaySetup implements OnInit { } makeNewPOD() { - console.log('open new file here'); - // this.router.navigateByUrl('setup/tabs/(partofday:new)') + this.router.navigateByUrl('setup/tabs/(partofday:new)'); + } + + async editTitle(pod) { + const changeForm = await this.alertCtrl.create({ + header: 'Change Description', + subHeader: pod.name, + buttons: [ + 'Cancel', + { + text: 'Ok', + handler: (data: any) => { + data.newName = data.newName.trim(); + if (this.isTheValueUsed(data.newName)) { + alert(data.newName + ' was used already. Try another.'); + } else { + pod.name = data.newName; + this.confData.updatePartOfDay(pod); + } + } + } + ], + inputs: [ + { + type: 'text', + name: 'newName', + placeholder: 'new descrition here' + } + ], + backdropDismiss: false + }); + await changeForm.present(); + } + + isTheValueUsed(name) { + return this.PODs.find(pod => pod.name.toLowerCase() === name.toLowerCase()); } } diff --git a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts index e7304a375..60ed857c8 100644 --- a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts @@ -8,47 +8,25 @@ import { TracksSetup } from '../tracks/tracks-setup'; import { MapSetup } from '../map/map-setup'; import { SupportSetup } from '../support/support-setup'; import { PartOfDaySetup } from '../part-of-day/part-of-day-setup'; +import { PartOfDayNewPage } from '../part-of-day/part-of-day-new/part-of-day-new.page'; const routes: Routes = [ { path: 'tabs', component: TabsSetupPage, children: [ // tab one - { - path: 'sessions', - component: SessionsSetup, - outlet: 'sessions' - }, + { path: 'sessions', component: SessionsSetup, outlet: 'sessions' }, // tab two - { - path: 'speakers', - component: SpeakersSetup, - outlet: 'speakers' - }, + { path: 'speakers', component: SpeakersSetup, outlet: 'speakers' }, // tab three - { - path: 'tracks', - component: TracksSetup, - outlet: 'tracks' - }, + { path: 'tracks', component: TracksSetup, outlet: 'tracks' }, // tab four - { - path: 'partofday', - component: PartOfDaySetup, - outlet: 'partofday' - }, + { path: 'partofday', component: PartOfDaySetup, outlet: 'partofday' }, + { path: 'new', component: PartOfDayNewPage, outlet: 'partofday' }, // tab five - { - path: 'map', - component: MapSetup, - outlet: 'map' - }, + { path: 'map', component: MapSetup, outlet: 'map' }, // tab six - { - path: 'support', - component: SupportSetup, - outlet: 'support' - }, + { path: 'support', component: SupportSetup, outlet: 'support' }, ] } ]; diff --git a/src/app/setup/tabs-setup/tabs-setup.module.ts b/src/app/setup/tabs-setup/tabs-setup.module.ts index af1119858..f1c3ef7e9 100644 --- a/src/app/setup/tabs-setup/tabs-setup.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup.module.ts @@ -13,6 +13,7 @@ import { TracksSetupModule } from '../tracks/tracks.module'; import { MapSetupModule } from '../map/map.module'; import { SupportSetupModule } from '../support/support.module'; import { PartOfDaySetupModule } from '../part-of-day/part-of-day.module'; +import { PartOfDayNewPageModule } from '../part-of-day/part-of-day-new/part-of-day-new.module'; const routes: Routes = [ { @@ -30,10 +31,13 @@ const routes: Routes = [ SpeakersSetupModule, TracksSetupModule, PartOfDaySetupModule, + PartOfDayNewPageModule, MapSetupModule, SupportSetupModule, TabsSetupRoutingModule ], - declarations: [TabsSetupPage] + declarations: [ + TabsSetupPage + ] }) export class TabsSetupPageModule {} From 7e0c70429045a35d49966dac9f5d92b6af711d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Sun, 6 Jan 2019 05:02:39 -0500 Subject: [PATCH 31/44] Created UI of 'Speakers' module in admin setup. --- src/app/setup/speakers/speakers-setup.html | 18 ++++++++++++++++-- src/app/setup/speakers/speakers-setup.ts | 17 ++++++++++++----- .../tabs-setup/tabs-setup-routing.module.ts | 2 +- src/app/setup/tabs-setup/tabs-setup.page.html | 6 +++--- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/app/setup/speakers/speakers-setup.html b/src/app/setup/speakers/speakers-setup.html index adc59cd9d..d403e2316 100644 --- a/src/app/setup/speakers/speakers-setup.html +++ b/src/app/setup/speakers/speakers-setup.html @@ -4,9 +4,23 @@ Speakers + + Add a New + + + + - - + + + + + Speaker profile pic + + {{speaker.name}} ({{ speaker.phone }}) + + diff --git a/src/app/setup/speakers/speakers-setup.ts b/src/app/setup/speakers/speakers-setup.ts index 2c5669da3..92ee5ade1 100644 --- a/src/app/setup/speakers/speakers-setup.ts +++ b/src/app/setup/speakers/speakers-setup.ts @@ -1,15 +1,22 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; +import { SpeakerData } from '../../providers/speaker-data'; +import { Speaker } from '../../models'; @Component({ selector: 'speakers-setup', templateUrl: './speakers-setup.html', styleUrls: ['./speakers-setup.scss'], }) -export class SpeakersSetup implements OnInit { +export class SpeakersSetup { - constructor() { } + speakers: Speaker[]; + queryText = ''; - ngOnInit() { - } + constructor(private speakerProvider: SpeakerData) { } + ionViewDidEnter() { + this.speakerProvider.getSpeakers().subscribe(data => { + this.speakers = data; + }); + } } diff --git a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts index 60ed857c8..02a2a647e 100644 --- a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts @@ -17,7 +17,7 @@ const routes: Routes = [ // tab one { path: 'sessions', component: SessionsSetup, outlet: 'sessions' }, // tab two - { path: 'speakers', component: SpeakersSetup, outlet: 'speakers' }, + { path: 'speaker', component: SpeakersSetup, outlet: 'speaker' }, // tab three { path: 'tracks', component: TracksSetup, outlet: 'tracks' }, // tab four diff --git a/src/app/setup/tabs-setup/tabs-setup.page.html b/src/app/setup/tabs-setup/tabs-setup.page.html index 8c99cc8ca..35cc8feaf 100644 --- a/src/app/setup/tabs-setup/tabs-setup.page.html +++ b/src/app/setup/tabs-setup/tabs-setup.page.html @@ -6,7 +6,7 @@ Sessions - + Speakers @@ -37,8 +37,8 @@ - - + + From 4c2a37ce63f254a5385573a37529160bf46f3697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Mon, 7 Jan 2019 12:49:35 -0500 Subject: [PATCH 32/44] Created add/edit/remove module for 'Speakers' in admin setup --- src/app/app.module.ts | 2 +- src/app/directive/dropzone.directive.ts | 31 +++++ src/app/pages/account/account.module.ts | 8 +- src/app/pipe/filesize.pipe.ts | 25 ++++ src/app/providers/speaker-data.ts | 49 ++++++-- src/app/providers/user-data.ts | 5 - .../speaker-edit/speaker-edit.module.ts | 33 ++++++ .../speaker-edit/speaker-edit.page.html | 61 ++++++++++ .../speaker-edit/speaker-edit.page.scss | 4 + .../speaker-edit/speaker-edit.page.ts | 112 ++++++++++++++++++ src/app/setup/speakers/speakers-setup.html | 9 +- src/app/setup/speakers/speakers-setup.ts | 31 ++++- .../tabs-setup/tabs-setup-routing.module.ts | 2 + src/app/setup/tabs-setup/tabs-setup.module.ts | 2 + src/app/setup/tracks/tracks-setup.html | 2 +- src/app/setup/tracks/tracks-setup.ts | 25 +++- .../setup/upload-image/upload-img.page.html | 26 ++++ .../setup/upload-image/upload-img.page.scss | 43 +++++++ src/app/setup/upload-image/upload-img.page.ts | 72 +++++++++++ 19 files changed, 516 insertions(+), 26 deletions(-) create mode 100644 src/app/directive/dropzone.directive.ts create mode 100644 src/app/pipe/filesize.pipe.ts create mode 100644 src/app/setup/speakers/speaker-edit/speaker-edit.module.ts create mode 100644 src/app/setup/speakers/speaker-edit/speaker-edit.page.html create mode 100644 src/app/setup/speakers/speaker-edit/speaker-edit.page.scss create mode 100644 src/app/setup/speakers/speaker-edit/speaker-edit.page.ts create mode 100644 src/app/setup/upload-image/upload-img.page.html create mode 100644 src/app/setup/upload-image/upload-img.page.scss create mode 100644 src/app/setup/upload-image/upload-img.page.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index bc4c62526..7fcd7ee35 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -33,6 +33,6 @@ import { ServiceWorkerModule } from '@angular/service-worker'; ], declarations: [AppComponent], providers: [InAppBrowser, SplashScreen, StatusBar], - bootstrap: [AppComponent] + bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/directive/dropzone.directive.ts b/src/app/directive/dropzone.directive.ts new file mode 100644 index 000000000..63c0e30f0 --- /dev/null +++ b/src/app/directive/dropzone.directive.ts @@ -0,0 +1,31 @@ +import { Directive, HostListener, Output, EventEmitter } from '@angular/core'; + +@Directive({ + selector: '[appDropzone]' +}) +export class DropzoneDirective { + + @Output() dropped = new EventEmitter(); + @Output() hovered = new EventEmitter(); + + constructor() { } + + @HostListener('drop', ['$event']) + onDrop($event) { + $event.preventDefault(); + this.dropped.emit($event.dataTransfer.files); + this.hovered.emit(false); + } + + @HostListener('dragover', ['$event']) + onDragOver($event) { + $event.preventDefault(); + this.hovered.emit(true); + } + + @HostListener('dragleave', ['$event']) + onDragLeave($event) { + $event.preventDefault(); + this.hovered.emit(false); + } +} diff --git a/src/app/pages/account/account.module.ts b/src/app/pages/account/account.module.ts index ba5a81e63..4ac1fba53 100644 --- a/src/app/pages/account/account.module.ts +++ b/src/app/pages/account/account.module.ts @@ -5,20 +5,20 @@ import { IonicModule } from '@ionic/angular'; import { AccountPage } from './account'; import { AccountPageRoutingModule } from './account-routing.module'; import { UploadImageComponent } from '../upload-image/upload-image.component'; -import { FileSizePipe } from '../../pipe/file-size.pipe'; import { DropZoneDirective } from '../../directive/drop-zone.directive'; +import { FileSizePipe } from '../../pipe/file-size.pipe'; @NgModule({ imports: [ CommonModule, IonicModule, - AccountPageRoutingModule + AccountPageRoutingModule, ], declarations: [ AccountPage, UploadImageComponent, - FileSizePipe, - DropZoneDirective + DropZoneDirective, + FileSizePipe ] }) export class AccountModule { } diff --git a/src/app/pipe/filesize.pipe.ts b/src/app/pipe/filesize.pipe.ts new file mode 100644 index 000000000..ddee650b4 --- /dev/null +++ b/src/app/pipe/filesize.pipe.ts @@ -0,0 +1,25 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +const FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; +const FILE_SIZE_UNITS_LONG = ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Pettabytes', 'Exabytes', 'Zettabytes', 'Yottabytes']; + +@Pipe({ + name: 'filesize' +}) +export class FilesizePipe implements PipeTransform { + + transform(sizeInBytes: number, longForm: boolean): string { + const units = longForm + ? FILE_SIZE_UNITS_LONG + : FILE_SIZE_UNITS; + + let power = Math.round(Math.log(sizeInBytes) / Math.log(1024)); + power = Math.min(power, units.length - 1); + + const size = sizeInBytes / Math.pow(1024, power); // size in new units + const formattedSize = Math.round(size * 100) / 100; // keep up to 2 decimals + const unit = units[power]; + + return size ? `${formattedSize} ${unit}` : '0'; + } +} diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts index 436966d59..174197447 100644 --- a/src/app/providers/speaker-data.ts +++ b/src/app/providers/speaker-data.ts @@ -29,9 +29,11 @@ export class SpeakerData { return response.map(action => { const data = action.payload.doc.data() as Speaker; data.id = action.payload.doc.id; - this.fireStorage.ref(data.profilePic).getDownloadURL().subscribe(url => { - data.profilePic = url; - }); + if (data.profilePic) { + this.fireStorage.ref(data.profilePic).getDownloadURL().subscribe(url => { + data.profilePic = url ? url : ''; + }); + } return data; }); })); @@ -42,17 +44,26 @@ export class SpeakerData { return this.speakersCollection.doc(id).ref.get() .then(doc => { const speaker = doc.data() as Speaker; - this.fireStorage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { - speaker.profilePic = url; - }); - return speaker; + if (speaker.profilePic) { + this.fireStorage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { + speaker.profilePic = url; + }); + } + return speaker; }); } addNewSpeaker(speaker: Speaker) { + console.log(speaker); this.speakersCollection.add(speaker) ; } + removeSpeaker(speaker: Speaker) { + const id = speaker.id; + this.speakerDoc = this.afs.doc(`speakers/${id}`); + this.speakerDoc.delete(); + } + updateSpeaker(speaker: Speaker) { this.speakerDoc = this.afs.doc(`speakers/${speaker.id}`); delete(speaker.id); @@ -80,4 +91,28 @@ export class SpeakerData { } ); } + + getUrl(path): Observable { + return this.fireStorage.ref(path).getDownloadURL(); + } + + deleteUrl(oldUrl) { + if (oldUrl) { + this.fireStorage.storage.refFromURL(oldUrl).delete(); + } + } + + getSpeakerById(id: string) { + return this.speakersCollection.doc(id).ref.get() + .then(doc => { + const speaker = doc.data() as Speaker; + speaker.id = id; + if (speaker.profilePic) { + this.fireStorage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { + speaker.profilePic = url; + }); + } + return speaker; + }); + } } diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 917eb916b..23f429c56 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -100,11 +100,6 @@ export class UserData { this.updateUser(user); } }); - // const len = users.length; - // for (let i=0; i + + + + + {{mode}} Speaker + + Cancel + Save + + + + + + +
+ avatar + avatar +
+ + Name : + + + + Email : + + + + Phone : + + + + Location : + + + + twitter : + + + + github : + + + + instagram : + + + + About : + + +
+ + + + +
diff --git a/src/app/setup/speakers/speaker-edit/speaker-edit.page.scss b/src/app/setup/speakers/speaker-edit/speaker-edit.page.scss new file mode 100644 index 000000000..ceb2a9c10 --- /dev/null +++ b/src/app/setup/speakers/speaker-edit/speaker-edit.page.scss @@ -0,0 +1,4 @@ +img { + max-width: 140px; + border-radius: 50%; +} \ No newline at end of file diff --git a/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts new file mode 100644 index 000000000..8ec45f716 --- /dev/null +++ b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts @@ -0,0 +1,112 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { Speaker } from '../../../models'; +import { SpeakerData } from '../../../providers/speaker-data'; + +@Component({ + selector: 'speaker-edit', + templateUrl: './speaker-edit.page.html', + styleUrls: ['./speaker-edit.page.scss'], +}) +export class SpeakerEditPage implements OnInit { + + mode: string; + id: string; + speaker: Speaker; + loadImage = false; + currentUrl = ''; + newPath = ''; + + constructor(private activatedRoute: ActivatedRoute, + private speakerData: SpeakerData, + private router: Router) { } + + ngOnInit() { + this.mode = this.activatedRoute.snapshot.paramMap.get('id'); + if (this.mode === 'New') { + this.speaker = { + name: '', + profilePic: '', + twitter: '', + github: '', + instagram: '', + about: '', + location: '', + email: '', + phone: '', + sessions: [], + }; + } else { + [this.id, this.mode] = [this.mode, 'Edit']; + this.speakerData.getSpeaker(this.id).then(data => { + this.speaker = data; + this.speaker.id = this.id; + this.currentUrl = data.profilePic; + this.newPath = this.currentUrl; + }); + } + } + + onSubmit() { + if (this.verifiedInput()) { + if (this.mode === 'New') { + this.speakerData.addNewSpeaker(this.speaker); + } else { + this.speakerData.updateSpeaker(this.speaker); + } + this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); + } + } + + verifiedInput() { + this.speaker.name = this.speaker.name.trim() ; + this.speaker.profilePic = this.speaker.profilePic.trim() ; + this.speaker.email = this.speaker.email.trim() ; + this.speaker.phone = this.speaker.phone.trim() ; + this.speaker.github = this.speaker.github.trim(); + this.speaker.instagram = this.speaker.instagram.trim() ; + this.speaker.location = this.speaker.location.trim() ; + this.speaker.twitter = this.speaker.twitter.trim() ; + this.speaker.about = this.speaker.about.trim() ; + if (this.speaker.name.length < 4) { + alert('Name should be more than 4 digits.'); + } if (this.isNameUsed()) { + alert('Name already exist. Try another.'); + } if (this.isEmailUsed()) { + alert('Email is not valid. Try another.'); + } if (this.speaker.phone.length < 10) { + alert('Phone number is not valid. Try again.'); + } else { + return true; + } + return false; + } + + isNameUsed() { + // check validation of name + return false; + } + + isEmailUsed() { + // check validation of email + return false; + } + + onExit() { + this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); + } + + updatePicture(path: string) { + const oldUrl = this.speaker.profilePic; + const id = this.speaker.id; + this.speaker.profilePic = path; + this.speakerData.updateSpeaker(this.speaker); + this.loadImage = false; + this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); + } + + onLoadImage() { + this.loadImage = (this.mode === 'New') ? false : true; + } +} diff --git a/src/app/setup/speakers/speakers-setup.html b/src/app/setup/speakers/speakers-setup.html index d403e2316..043f35200 100644 --- a/src/app/setup/speakers/speakers-setup.html +++ b/src/app/setup/speakers/speakers-setup.html @@ -5,7 +5,7 @@ Speakers - Add a New + Add a New @@ -16,11 +16,14 @@ + [href]="'setup/tabs/(speaker:edit/'+ speaker.id"> Speaker profile pic - {{speaker.name}} ({{ speaker.phone }}) + {{speaker.name}} ({{ speaker.phone }}) + + + diff --git a/src/app/setup/speakers/speakers-setup.ts b/src/app/setup/speakers/speakers-setup.ts index 92ee5ade1..21243ed0d 100644 --- a/src/app/setup/speakers/speakers-setup.ts +++ b/src/app/setup/speakers/speakers-setup.ts @@ -1,6 +1,8 @@ import { Component } from '@angular/core'; import { SpeakerData } from '../../providers/speaker-data'; import { Speaker } from '../../models'; +import { AlertController } from '@ionic/angular'; +import { Router } from '@angular/router'; @Component({ selector: 'speakers-setup', @@ -12,11 +14,38 @@ export class SpeakersSetup { speakers: Speaker[]; queryText = ''; - constructor(private speakerProvider: SpeakerData) { } + constructor(private speakerProvider: SpeakerData, + private alertCtrl: AlertController, + private router: Router) { } ionViewDidEnter() { this.speakerProvider.getSpeakers().subscribe(data => { this.speakers = data; }); } + + async onConfirmToRemove(speaker: Speaker) { + const alert = await this.alertCtrl.create({ + header: 'Confirm Remove', + message: `Are you sure to remove ${speaker.name}?`, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + this.router.navigateByUrl('setup/tabs/(speaker:speaker)'); + } + }, + { + text: 'Remove', + handler: () => { + this.speakerProvider.removeSpeaker(speaker); + this.router.navigateByUrl('setup/tabs/(speaker:speaker)'); + } + } + ], + backdropDismiss: false + }); + await alert.present(); + } } diff --git a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts index 02a2a647e..00e5129fd 100644 --- a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts @@ -9,6 +9,7 @@ import { MapSetup } from '../map/map-setup'; import { SupportSetup } from '../support/support-setup'; import { PartOfDaySetup } from '../part-of-day/part-of-day-setup'; import { PartOfDayNewPage } from '../part-of-day/part-of-day-new/part-of-day-new.page'; +import { SpeakerEditPage } from '../speakers/speaker-edit/speaker-edit.page'; const routes: Routes = [ { @@ -18,6 +19,7 @@ const routes: Routes = [ { path: 'sessions', component: SessionsSetup, outlet: 'sessions' }, // tab two { path: 'speaker', component: SpeakersSetup, outlet: 'speaker' }, + { path: 'edit/:id', component: SpeakerEditPage, outlet: 'speaker' }, // tab three { path: 'tracks', component: TracksSetup, outlet: 'tracks' }, // tab four diff --git a/src/app/setup/tabs-setup/tabs-setup.module.ts b/src/app/setup/tabs-setup/tabs-setup.module.ts index f1c3ef7e9..94e851a64 100644 --- a/src/app/setup/tabs-setup/tabs-setup.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup.module.ts @@ -14,6 +14,7 @@ import { MapSetupModule } from '../map/map.module'; import { SupportSetupModule } from '../support/support.module'; import { PartOfDaySetupModule } from '../part-of-day/part-of-day.module'; import { PartOfDayNewPageModule } from '../part-of-day/part-of-day-new/part-of-day-new.module'; +import { SpeakerEditPageModule } from '../speakers/speaker-edit/speaker-edit.module'; const routes: Routes = [ { @@ -29,6 +30,7 @@ const routes: Routes = [ IonicModule, SessionsSetupModule, SpeakersSetupModule, + SpeakerEditPageModule, TracksSetupModule, PartOfDaySetupModule, PartOfDayNewPageModule, diff --git a/src/app/setup/tracks/tracks-setup.html b/src/app/setup/tracks/tracks-setup.html index a960a91f4..42953f0a7 100644 --- a/src/app/setup/tracks/tracks-setup.html +++ b/src/app/setup/tracks/tracks-setup.html @@ -17,7 +17,7 @@ {{track.name}} Edit - +
diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts index 5e21af73d..0e601f054 100644 --- a/src/app/setup/tracks/tracks-setup.ts +++ b/src/app/setup/tracks/tracks-setup.ts @@ -106,10 +106,27 @@ export class TracksSetup { await changeForm.present(); } - onRemove(track) { - if (confirm(`Are you sure to delete '${track.name}'?`)) { - this.confData.removeTrack(track); - } + async onConfirmToRemove(track: Track) { + const alert = await this.alertCtrl.create({ + header: 'Confirm Remove', + message: `Are you sure to remove ${track.name}?`, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + } + }, + { + text: 'Remove', + handler: () => { + this.confData.removeTrack(track); + } + } + ], + backdropDismiss: false + }); + await alert.present(); } isTheValueUsed(name) { diff --git a/src/app/setup/upload-image/upload-img.page.html b/src/app/setup/upload-image/upload-img.page.html new file mode 100644 index 000000000..ee5ff5519 --- /dev/null +++ b/src/app/setup/upload-image/upload-img.page.html @@ -0,0 +1,26 @@ +
Upload Speaker's Avatar
+
+ +

Image Drop Zone

+

Drag and Drop a File

+
+ +
+ +
+ +
+ + + {{ pct | number }}% +
+ +
+ {{ snap.bytesTransferred | filesize }} of {{ snap.totalBytes | filesize }} +
diff --git a/src/app/setup/upload-image/upload-img.page.scss b/src/app/setup/upload-image/upload-img.page.scss new file mode 100644 index 000000000..3c4bf3bd1 --- /dev/null +++ b/src/app/setup/upload-image/upload-img.page.scss @@ -0,0 +1,43 @@ +.title { + font-size: 1.4em; + margin-top: 40px; +} + +.dropzone { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + font-weight: 200; + height: 300px; + border: 2px dashed #f16624; + border-radius: 5px; + background: white; + margin: 40px 0; + + &.hovering { + border: 2px solid #f16624; + color: #dadada !important; + } + + .file-label { + font-size: 1em; + } +} + +progress::-webkit-progress-value { + transition: width 0.1s ease; +} + +img { + width: 250px +} + +button { + padding: 10px; + width: 150px; + font-size: 1em; + font-weight: 400; + background-color: #f16624; + color: white +} diff --git a/src/app/setup/upload-image/upload-img.page.ts b/src/app/setup/upload-image/upload-img.page.ts new file mode 100644 index 000000000..ed87ae3df --- /dev/null +++ b/src/app/setup/upload-image/upload-img.page.ts @@ -0,0 +1,72 @@ +import { Component, Output, Input, EventEmitter } from '@angular/core'; +import { AngularFireStorage, AngularFireUploadTask } from 'angularfire2/storage'; +import { AngularFirestore } from 'angularfire2/firestore'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Component({ + selector: 'upload-img', + templateUrl: './upload-img.page.html', + styleUrls: ['./upload-img.page.scss'] +}) +export class UploadImgComponent { + + @Input() name: string; + @Output() exit = new EventEmitter(); + @Output() updateImage = new EventEmitter(); + + // Main task + task: AngularFireUploadTask; + + // State for dropzone CSS toggling + isHovering: boolean; + + // Progress monitoring + percentage: Observable; + + snapshot: Observable; + + // constructor(private db: AngularFirestore) { } + constructor(private storage: AngularFireStorage, private db: AngularFirestore) { } + + toggleHover(event: boolean) { + this.isHovering = event; + } + + startUpload(event: FileList) { + // The File object + const file = event.item(0); + + // Client-side validation example + if (!file || file.type.split('/')[0] !== 'image') { + console.error('unsupported file type :( '); + return; + } + + // The storage path + const path = `images/${new Date().getTime()}_${file.name}`; + + // Totally optional metadata + const customMetadata = { app: 'My AngularFire-powered PWA!' }; + + // const ref = this.storage.ref(path); + // this.task = ref.put(file, { customMetadata }); + // The main task + this.task = this.storage.upload(path, file, { customMetadata }); + + // Progress monitoring + this.percentage = this.task.percentageChanges(); + this.snapshot = this.task.snapshotChanges().pipe( + tap(snap => { + if (snap.bytesTransferred === snap.totalBytes) { + this.updateImage.emit(path); + } + }) + ); + } + + // Determines if the upload task is active + isActive(snapshot) { + return snapshot.state === 'running' && snapshot.bytesTransferred < snapshot.totalBytes; + } +} From 477f66e675936217bf76752419c5c2bb452ffed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Mon, 7 Jan 2019 23:57:12 -0500 Subject: [PATCH 33/44] updated after meeting with UI designer --- src/app/app.component.ts | 12 +++----- src/app/pages/account/account.html | 1 - src/app/pages/login/login.ts | 3 +- src/app/pages/schedule/schedule.html | 6 ---- .../pages/session-detail/session-detail.html | 9 ++++-- src/app/pages/speaker-list/speaker-list.ts | 28 +++++++++++++++++++ src/app/pages/tabs-page/tabs-page.html | 5 ++-- src/app/pages/tabs-page/tabs-page.ts | 15 ++++++++-- src/app/pages/tutorial/tutorial.html | 16 ++++++++++- src/app/pages/tutorial/tutorial.scss | 26 +++++++++++++++++ src/app/pages/tutorial/tutorial.ts | 10 +++++-- src/app/providers/user-data.ts | 2 ++ 12 files changed, 107 insertions(+), 26 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 834aba48d..006859f79 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -37,7 +37,7 @@ export class AppComponent implements OnInit { } ]; loggedIn = false; - keyword: string; + keyword = ''; constructor( private events: Events, @@ -53,7 +53,9 @@ export class AppComponent implements OnInit { } ngOnInit() { - this.checkLoginStatus(); + this.userData.isLoggedIn().then(loggedIn => { + this.updateLoggedInStatus(loggedIn); + }); this.listenForLoginEvents(); } @@ -64,12 +66,6 @@ export class AppComponent implements OnInit { }); } - checkLoginStatus() { - return this.userData.isLoggedIn().then(loggedIn => { - return this.updateLoggedInStatus(loggedIn); - }); - } - updateLoggedInStatus(loggedIn: boolean) { setTimeout(() => { this.loggedIn = loggedIn; diff --git a/src/app/pages/account/account.html b/src/app/pages/account/account.html index 3909f0222..1ae712b7a 100644 --- a/src/app/pages/account/account.html +++ b/src/app/pages/account/account.html @@ -18,7 +18,6 @@

{{user.username}}

Change Username Change Email Change Password - Support Logout

{{ jobDescription }}

diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 6f747691d..f7d2c1d4d 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -14,6 +14,7 @@ import { User } from '../../models'; export class LoginPage implements OnInit { username: ''; password: '' ; + submitted = false; users: User[]; constructor(public userData: UserData, @@ -27,12 +28,12 @@ export class LoginPage implements OnInit { } onLogin(form: NgForm) { + this.submitted = true; if (form.valid) { const user = this.findUser(this.username.toLowerCase().trim()); if (user) { if (user.password === this.password) { this.userData.login(user); - // this.router.navigateByUrl('/app/tabs/schedule') this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } else { alert('Invalid password. Try again.'); diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index d04a30178..a78a59da9 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -59,12 +59,6 @@

{{session.name}}

- -

No Sessions Found

-

You may

-

Login or Signup!

-
- diff --git a/src/app/pages/session-detail/session-detail.html b/src/app/pages/session-detail/session-detail.html index 2a77aef36..43da81ff5 100644 --- a/src/app/pages/session-detail/session-detail.html +++ b/src/app/pages/session-detail/session-detail.html @@ -12,11 +12,14 @@ - {{track}} + {{track}} - - + + diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index ae6b943ec..280878d39 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -5,6 +5,7 @@ import { ActionSheetController, AlertController } from '@ionic/angular'; import { Speaker } from '../../models'; import { SpeakerData } from '../../providers/speaker-data'; +import { UserData } from '../../providers/user-data'; @Component({ selector: 'page-speaker-list', @@ -20,6 +21,7 @@ export class SpeakerListPage { public alertCtrl: AlertController, private speakerProvider: SpeakerData, public inAppBrowser: InAppBrowser, + private userProvider: UserData, public router: Router ) {} @@ -27,8 +29,34 @@ export class SpeakerListPage { this.speakerProvider.getSpeakers().subscribe( speakers => { this.speakers = speakers; } ); + // this.userProvider.isLoggedIn().then(loggedIn => { + // if (loggedIn) { this.askLogIn(); } + // }) } + // async askLogIn() { + // const askLogInForm = await this.alertCtrl.create({ + // header: 'Recommendation', + // subHeader: 'You need to login to access all features.', + // buttons: [ + // { + // text: 'Login Now', + // handler: () => { + // this.router.navigate(['/login']); + // } + // }, + // { + // text: 'Login later', + // handler: () => { + + // } + // }, + // ], + // backdropDismiss: false + // }); + // await askLogInForm.present(); + // } + goToSpeakerTwitter(speaker: Speaker) { this.inAppBrowser.create( `https://twitter.com/${speaker.twitter}`, diff --git a/src/app/pages/tabs-page/tabs-page.html b/src/app/pages/tabs-page/tabs-page.html index 70e29fbb2..efd19590a 100644 --- a/src/app/pages/tabs-page/tabs-page.html +++ b/src/app/pages/tabs-page/tabs-page.html @@ -1,7 +1,8 @@ - + Schedule @@ -11,7 +12,7 @@ Speakers - + Map diff --git a/src/app/pages/tabs-page/tabs-page.ts b/src/app/pages/tabs-page/tabs-page.ts index 0afde6465..c096955cc 100644 --- a/src/app/pages/tabs-page/tabs-page.ts +++ b/src/app/pages/tabs-page/tabs-page.ts @@ -1,6 +1,17 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { UserData } from '../../providers/user-data'; @Component({ templateUrl: 'tabs-page.html' }) -export class TabsPage {} +export class TabsPage implements OnInit { + loggedIn = false; + + constructor(private userProvide: UserData) {} + + ngOnInit() { + this.userProvide.isLoggedIn().then(data => { + this.loggedIn = data; + }); + } +} diff --git a/src/app/pages/tutorial/tutorial.html b/src/app/pages/tutorial/tutorial.html index d30cc9591..a1beccc8d 100644 --- a/src/app/pages/tutorial/tutorial.html +++ b/src/app/pages/tutorial/tutorial.html @@ -19,6 +19,9 @@

ionic conference app is a practical preview of the ionic framework in action, and a demonstration of proper code use.

+ + + @@ -27,6 +30,10 @@

What is Ionic?

Ionic Framework is an open source SDK that enables developers to build high quality mobile apps with web technologies like HTML, CSS, and JavaScript.

+ + + +
@@ -35,6 +42,10 @@

What is Ionic Pro?

Ionic Pro is a powerful set of services and features built on top of Ionic Framework that brings a totally new level of app development agility to mobile dev teams.

+ + + +
@@ -42,8 +53,11 @@

What is Ionic Pro?

Ready to Play?

Continue - + + + +
diff --git a/src/app/pages/tutorial/tutorial.scss b/src/app/pages/tutorial/tutorial.scss index 4a8019f87..cdf028cd1 100644 --- a/src/app/pages/tutorial/tutorial.scss +++ b/src/app/pages/tutorial/tutorial.scss @@ -18,6 +18,32 @@ ion-toolbar { margin: 36px 0; } +.btn-right { + float: right; + margin-top: 20px; +} + +.btn-left { + margin-top: 50px; +} + +.btn-both { + display: inline; +} + +.arrow-forward { + float: right; + width: 30px; + margin-right: 20px; + font-size: 30px; +} + +.arrow-back { + float: left; + margin-left: 20px; + font-size: 30px; +} + b { font-weight: 500; } diff --git a/src/app/pages/tutorial/tutorial.ts b/src/app/pages/tutorial/tutorial.ts index 9e6751bf7..b4e97b353 100644 --- a/src/app/pages/tutorial/tutorial.ts +++ b/src/app/pages/tutorial/tutorial.ts @@ -1,15 +1,15 @@ -import { Component, ViewChild, ViewEncapsulation } from '@angular/core'; +import { Component, ViewChild } from '@angular/core'; import { Router } from '@angular/router'; import { MenuController, Slides } from '@ionic/angular'; import { Storage } from '@ionic/storage'; +import { UserData } from '../../providers/user-data'; @Component({ selector: 'page-tutorial', templateUrl: 'tutorial.html', styleUrls: ['./tutorial.scss'], - encapsulation: ViewEncapsulation.None }) export class TutorialPage { showSkip = true; @@ -18,6 +18,7 @@ export class TutorialPage { constructor( public menu: MenuController, + private userProvider: UserData, public router: Router, public storage: Storage ) {} @@ -35,6 +36,11 @@ export class TutorialPage { } ionViewWillEnter() { + this.userProvider.isLoggedIn().then(res => { + if (res) { + this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); + } + }); this.storage.get('ion_did_tutorial').then(res => { if (res === true) { this.router.navigateByUrl('/app/tabs/schedule'); diff --git a/src/app/providers/user-data.ts b/src/app/providers/user-data.ts index 23f429c56..2c186e8b1 100644 --- a/src/app/providers/user-data.ts +++ b/src/app/providers/user-data.ts @@ -88,6 +88,8 @@ export class UserData { delete(user.id); this.userDoc = this.afs.doc(`users/${id}`); this.userDoc.update(user); + user.id = id; + this.setUser(user); } addTrackInUser(name) { From 6154d8c41b2343c7ae0362aec9954b166ac01270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 8 Jan 2019 10:57:22 -0500 Subject: [PATCH 34/44] reassign previously deleted id to object after it has been updated. --- src/app/providers/session-data.ts | 5 +++-- src/app/providers/speaker-data.ts | 16 +++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/app/providers/session-data.ts b/src/app/providers/session-data.ts index e24f0ea33..1ba94e700 100644 --- a/src/app/providers/session-data.ts +++ b/src/app/providers/session-data.ts @@ -66,11 +66,12 @@ export class SessionData { }); } - updateSession(session: Session): Promise { + updateSession(session: Session) { const id = session.id; delete(session.id); this.sessionDoc = this.afs.doc(`sessions/${id}`); - return this.sessionDoc.update(session); + this.sessionDoc.update(session); + session.id = id; } deleteSession(session: Session) { diff --git a/src/app/providers/speaker-data.ts b/src/app/providers/speaker-data.ts index 174197447..37756406c 100644 --- a/src/app/providers/speaker-data.ts +++ b/src/app/providers/speaker-data.ts @@ -27,14 +27,14 @@ export class SpeakerData { this.speakers = this.speakersCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { - const data = action.payload.doc.data() as Speaker; - data.id = action.payload.doc.id; - if (data.profilePic) { - this.fireStorage.ref(data.profilePic).getDownloadURL().subscribe(url => { - data.profilePic = url ? url : ''; + const speaker = action.payload.doc.data() as Speaker; + speaker.id = action.payload.doc.id; + if (speaker.profilePic) { + this.fireStorage.ref(speaker.profilePic).getDownloadURL().subscribe(url => { + speaker.profilePic = url ? url : ''; }); } - return data; + return speaker; }); })); return this.speakers ; @@ -65,9 +65,11 @@ export class SpeakerData { } updateSpeaker(speaker: Speaker) { - this.speakerDoc = this.afs.doc(`speakers/${speaker.id}`); + const id = speaker.id; + this.speakerDoc = this.afs.doc(`speakers/${id}`); delete(speaker.id); this.speakerDoc.update(speaker); + speaker.id = id; } getSpeakerName(id: string) { From 20b8f1016200f440ad686c906e03e5514e3e212b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 8 Jan 2019 15:35:34 -0500 Subject: [PATCH 35/44] updated main page of the session setup mode. --- src/app/app-routing.module.ts | 3 +- src/app/pages/schedule/schedule.ts | 4 +- src/app/providers/session-data.ts | 28 ++++++-- src/app/setup/map/map-setup.ts | 10 ++- .../part-of-day-new/part-of-day-new.page.ts | 16 +++-- .../session-edit/session-edit.module.ts | 26 ++++++++ .../session-edit/session-edit.page.html | 16 +++++ .../session-edit/session-edit.page.scss | 0 .../session-edit/session-edit.page.ts | 47 +++++++++++++ src/app/setup/sessions/sessions-setup.html | 16 ++++- src/app/setup/sessions/sessions-setup.ts | 66 +++++++++++++++---- .../speaker-edit/speaker-edit.page.html | 22 +++---- .../speaker-edit/speaker-edit.page.ts | 5 +- src/app/setup/speakers/speakers-setup.html | 2 +- src/app/setup/speakers/speakers-setup.ts | 18 +++-- .../tabs-setup/tabs-setup-routing.module.ts | 2 + src/app/setup/tabs-setup/tabs-setup.module.ts | 2 + src/app/setup/tracks/tracks-setup.ts | 26 ++++---- 18 files changed, 251 insertions(+), 58 deletions(-) create mode 100644 src/app/setup/sessions/session-edit/session-edit.module.ts create mode 100644 src/app/setup/sessions/session-edit/session-edit.page.html create mode 100644 src/app/setup/sessions/session-edit/session-edit.page.scss create mode 100644 src/app/setup/sessions/session-edit/session-edit.page.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e2509bfdc..303773d0d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -34,7 +34,8 @@ const routes: Routes = [ { path: 'setup', loadChildren: './setup/tabs-setup/tabs-setup.module#TabsSetupPageModule' - } + }, + { path: 'session-edit', loadChildren: './setup/sessions/session-edit/session-edit.module#SessionEditPageModule' } ]; @NgModule({ diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index d29b3f3f2..16f362f22 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -7,6 +7,7 @@ import { ScheduleTrackPage } from '../schedule-track/schedule-track'; import { ConferenceData } from '../../providers/conference-data'; import { UserData } from '../../providers/user-data'; import { User, Session, PartOfDay } from '../../models'; +import { SessionData } from '../../providers/session-data'; @Component({ selector: 'page-schedule', @@ -41,6 +42,7 @@ export class SchedulePage implements OnInit { constructor( public alertCtrl: AlertController, public dataProvider: ConferenceData, + private sessionProvider: SessionData, public loadingCtrl: LoadingController, public modalCtrl: ModalController, public router: Router, @@ -74,7 +76,7 @@ export class SchedulePage implements OnInit { if (this.schedule.length === 0 || this.changePeriod) { this.changePeriod = false; - this.dataProvider.getSessionInPeriod(this.start, this.end).subscribe( + this.sessionProvider.getSessionsInPeriod(this.start, this.end).subscribe( (response: Session[]) => { this.sessions = response; this.buildSchedule(); diff --git a/src/app/providers/session-data.ts b/src/app/providers/session-data.ts index 1ba94e700..d3a77313a 100644 --- a/src/app/providers/session-data.ts +++ b/src/app/providers/session-data.ts @@ -17,12 +17,27 @@ export class SessionData { session: Observable ; id: string; - constructor(private afs: AngularFirestore) { + constructor(private afs: AngularFirestore) {} + + getSessionsInPeriod(start, end): Observable { this.sessionsCollection = this.afs.collection( - 'sessions', ref => ref.orderBy('date', 'asc')); + 'sessions', ref => ref.where('date', '>=', start) + .where('date', '<=', end) + .orderBy('date', 'asc')); + this.sessions = this.sessionsCollection.snapshotChanges() + .pipe(map(response => { + return response.map(action => { + const data = action.payload.doc.data() as Session; + data.id = action.payload.doc.id; + return data; + }); + })); + return this.sessions ; } getSessions(): Observable { + this.sessionsCollection = this.afs.collection( + 'sessions', ref => ref.orderBy('date', 'asc')); this.sessions = this.sessionsCollection.snapshotChanges() .pipe(map(response => { return response.map(action => { @@ -74,16 +89,17 @@ export class SessionData { session.id = id; } - deleteSession(session: Session) { + removeSession(session: Session) { this.sessionDoc = this.afs.doc(`sessions/${session.id}`); this.sessionDoc.delete(); } - getSession(id: string) { + getSession(id: string): Promise { return this.sessionsCollection.doc(id).ref.get() .then(doc => { - const res = doc.data() as Session ; - return res; + const session = doc.data() as Session ; + session.id = id; + return session; }); } } diff --git a/src/app/setup/map/map-setup.ts b/src/app/setup/map/map-setup.ts index 4e66cdf87..3315b18e3 100644 --- a/src/app/setup/map/map-setup.ts +++ b/src/app/setup/map/map-setup.ts @@ -1,4 +1,6 @@ import { Component, OnInit } from '@angular/core'; +import { UserData } from '../../providers/user-data'; +import { Router } from '@angular/router'; @Component({ selector: 'map-setup', @@ -7,9 +9,15 @@ import { Component, OnInit } from '@angular/core'; }) export class MapSetup implements OnInit { - constructor() { } + constructor(private userProvider: UserData, + private router: Router) { } ngOnInit() { + this.userProvider.getUser().then(user => { + if ( !user || user.username !== 'admin') { + this.router.navigateByUrl('/tutorial'); + } + }); } } diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts index c419fe534..e9b8b1c86 100644 --- a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts @@ -4,6 +4,7 @@ import { FunctionlData } from '../../../providers/function-data'; import { ConferenceData } from '../../../providers/conference-data'; import { Router } from '@angular/router'; import { AlertController } from '@ionic/angular'; +import { UserData } from '../../../providers/user-data'; @Component({ selector: 'part-of-day-new', @@ -22,12 +23,19 @@ export class PartOfDayNewPage implements OnInit { constructor(private cdRef: ChangeDetectorRef, private alertCtrl: AlertController, private funProvider: FunctionlData, - private confData: ConferenceData, + private userProvider: UserData, + private confProvider: ConferenceData, private router: Router) { } ngOnInit() { - this.confData.getPartsOfDay().subscribe(data => this.PODs = data); - this.setInitialValue(); + this.userProvider.getUser().then(user => { + if ( !user || user.username !== 'admin') { + this.router.navigateByUrl('/tutorial'); + } else { + this.confProvider.getPartsOfDay().subscribe(data => this.PODs = data); + this.setInitialValue(); + } + }); } setInitialValue() { @@ -102,7 +110,7 @@ export class PartOfDayNewPage implements OnInit { { text: 'Save', handler: () => { - this.confData.changePartsOfDay(this.PODs, this.newPODs); + this.confProvider.changePartsOfDay(this.PODs, this.newPODs); this.router.navigateByUrl('setup/tabs/(partofday:partofday)'); } } diff --git a/src/app/setup/sessions/session-edit/session-edit.module.ts b/src/app/setup/sessions/session-edit/session-edit.module.ts new file mode 100644 index 000000000..4f04e0e6a --- /dev/null +++ b/src/app/setup/sessions/session-edit/session-edit.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { SessionEditPage } from './session-edit.page'; + +const routes: Routes = [ + { + path: '', + component: SessionEditPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [SessionEditPage] +}) +export class SessionEditPageModule {} diff --git a/src/app/setup/sessions/session-edit/session-edit.page.html b/src/app/setup/sessions/session-edit/session-edit.page.html new file mode 100644 index 000000000..78b0c327b --- /dev/null +++ b/src/app/setup/sessions/session-edit/session-edit.page.html @@ -0,0 +1,16 @@ + + + + + + {{mode}} Session + + Cancel + Save + + + + + + + diff --git a/src/app/setup/sessions/session-edit/session-edit.page.scss b/src/app/setup/sessions/session-edit/session-edit.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts new file mode 100644 index 000000000..9fb141b34 --- /dev/null +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -0,0 +1,47 @@ +import { Component, OnInit } from '@angular/core'; +import { Session } from '../../../models'; +import { SessionData } from '../../../providers/session-data'; +import { Router, ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'session-edit', + templateUrl: './session-edit.page.html', + styleUrls: ['./session-edit.page.scss'], +}) +export class SessionEditPage implements OnInit { + + mode: string; + id: string; + session: Session; + + constructor(private activatedRoute: ActivatedRoute, + private sessionProvider: SessionData, + private router: Router) { } + + ngOnInit() { + this.mode = this.activatedRoute.snapshot.paramMap.get('id'); + if (this.mode === 'New') { + this.session = { + name: '', + date: '', // 2018-12-06 + timeStart: '', // 15:30 for 3:30pm + timeEnd: '', + location: '', + description: '', + speakerIDs: [], // speaker's id + tracks: [], // name of track + }; + } else { + [this.id, this.mode] = [this.mode, 'Edit']; + this.sessionProvider.getSession(this.id).then(data => { + this.session = data; + this.session.id = this.id; + }); + } + } + + onExit() { + this.router.navigateByUrl('/setup/tabs/(sessions:sessions)'); + } + +} diff --git a/src/app/setup/sessions/sessions-setup.html b/src/app/setup/sessions/sessions-setup.html index cffec4601..f64b89537 100644 --- a/src/app/setup/sessions/sessions-setup.html +++ b/src/app/setup/sessions/sessions-setup.html @@ -4,9 +4,23 @@ Sessions + + Add a New + + + + - + + + {{session.name}} ( {{ session.date }} ) + + + + + diff --git a/src/app/setup/sessions/sessions-setup.ts b/src/app/setup/sessions/sessions-setup.ts index 31c35f953..bf7402ac4 100644 --- a/src/app/setup/sessions/sessions-setup.ts +++ b/src/app/setup/sessions/sessions-setup.ts @@ -1,8 +1,14 @@ import { Component, OnInit } from '@angular/core'; -import { UserData } from '../../providers/user-data'; -import { MenuController } from '@ionic/angular'; +import { AlertController } from '@ionic/angular'; import { Router } from '@angular/router'; +import { UserData } from '../../providers/user-data'; +import { SessionData } from '../../providers/session-data'; +import { SpeakerData } from '../../providers/speaker-data'; +import { ConferenceData } from '../../providers/conference-data'; + +import { Session, Speaker, Track } from '../../models'; + @Component({ selector: 'sessions', templateUrl: './sessions-setup.html', @@ -10,23 +16,61 @@ import { Router } from '@angular/router'; }) export class SessionsSetup implements OnInit { - constructor(private userData: UserData, - public menu: MenuController, + startDate = '2000-01-01'; + endDate = '2019-01-31'; + queryText = ''; + sessions: Session[]; + speakers: Speaker[]; + tracks: Track[]; + + constructor(private userProvider: UserData, + private sessionProvider: SessionData, + private speakerProvider: SpeakerData, + private confProvider: ConferenceData, + private alertCtrl: AlertController, private router: Router) { } ngOnInit() { - } - - ionViewWillEnter() { - this.userData.getUser().then(user => { + this.userProvider.getUser().then(user => { if ( !user || user.username !== 'admin') { this.router.navigateByUrl('/tutorial'); + } else { + this.sessionProvider.getSessionsInPeriod(this.startDate, this.endDate) + .subscribe(data => { + this.sessions = data; + }); + this.speakerProvider.getSpeakers().subscribe(data => { + this.speakers = data; + }); + this.confProvider.getTracks().subscribe(data => { + this.tracks = data; + }); } }); - // this.menu.enable(false); } - ionViewDidLeave() { - // this.menu.enable(true); + async onConfirmToRemove(session: Session) { + const alert = await this.alertCtrl.create({ + header: 'Confirm Remove', + message: `Are you sure to remove ${session.name}?`, + buttons: [ + { + text: 'Cancel', + role: 'cancel', + handler: () => { + this.router.navigateByUrl('setup/tabs/(sessions:sessions)'); + } + }, + { + text: 'Remove', + handler: () => { + // this.sessionProvider.removeSession(session); + this.router.navigateByUrl('setup/tabs/(sessions:sessions)'); + } + } + ], + backdropDismiss: false + }); + await alert.present(); } } diff --git a/src/app/setup/speakers/speaker-edit/speaker-edit.page.html b/src/app/setup/speakers/speaker-edit/speaker-edit.page.html index 5571c179b..7a2f81224 100644 --- a/src/app/setup/speakers/speaker-edit/speaker-edit.page.html +++ b/src/app/setup/speakers/speaker-edit/speaker-edit.page.html @@ -1,15 +1,15 @@ - - - - - {{mode}} Speaker - - Cancel - Save - - - + + + + + {{mode}} Speaker + + Cancel + Save + + + diff --git a/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts index 8ec45f716..4134fa5da 100644 --- a/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts +++ b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts @@ -16,7 +16,6 @@ export class SpeakerEditPage implements OnInit { speaker: Speaker; loadImage = false; currentUrl = ''; - newPath = ''; constructor(private activatedRoute: ActivatedRoute, private speakerData: SpeakerData, @@ -42,8 +41,8 @@ export class SpeakerEditPage implements OnInit { this.speakerData.getSpeaker(this.id).then(data => { this.speaker = data; this.speaker.id = this.id; + // to keep profile's path as string. this.currentUrl = data.profilePic; - this.newPath = this.currentUrl; }); } } @@ -53,6 +52,8 @@ export class SpeakerEditPage implements OnInit { if (this.mode === 'New') { this.speakerData.addNewSpeaker(this.speaker); } else { + // to reassign it's origin path as string. + this.speaker.profilePic = this.currentUrl; this.speakerData.updateSpeaker(this.speaker); } this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); diff --git a/src/app/setup/speakers/speakers-setup.html b/src/app/setup/speakers/speakers-setup.html index 043f35200..90448aa43 100644 --- a/src/app/setup/speakers/speakers-setup.html +++ b/src/app/setup/speakers/speakers-setup.html @@ -15,7 +15,7 @@ - Speaker profile pic diff --git a/src/app/setup/speakers/speakers-setup.ts b/src/app/setup/speakers/speakers-setup.ts index 21243ed0d..f25c2b354 100644 --- a/src/app/setup/speakers/speakers-setup.ts +++ b/src/app/setup/speakers/speakers-setup.ts @@ -1,26 +1,34 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { SpeakerData } from '../../providers/speaker-data'; import { Speaker } from '../../models'; import { AlertController } from '@ionic/angular'; import { Router } from '@angular/router'; +import { UserData } from '../../providers/user-data'; @Component({ selector: 'speakers-setup', templateUrl: './speakers-setup.html', styleUrls: ['./speakers-setup.scss'], }) -export class SpeakersSetup { +export class SpeakersSetup implements OnInit { speakers: Speaker[]; queryText = ''; constructor(private speakerProvider: SpeakerData, + private userProvider: UserData, private alertCtrl: AlertController, private router: Router) { } - ionViewDidEnter() { - this.speakerProvider.getSpeakers().subscribe(data => { - this.speakers = data; + ngOnInit() { + this.userProvider.getUser().then(user => { + if ( !user || user.username !== 'admin') { + this.router.navigateByUrl('/tutorial'); + } else { + this.speakerProvider.getSpeakers().subscribe(data => { + this.speakers = data; + }); + } }); } diff --git a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts index 00e5129fd..66ef3588f 100644 --- a/src/app/setup/tabs-setup/tabs-setup-routing.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup-routing.module.ts @@ -10,6 +10,7 @@ import { SupportSetup } from '../support/support-setup'; import { PartOfDaySetup } from '../part-of-day/part-of-day-setup'; import { PartOfDayNewPage } from '../part-of-day/part-of-day-new/part-of-day-new.page'; import { SpeakerEditPage } from '../speakers/speaker-edit/speaker-edit.page'; +import { SessionEditPage } from '../sessions/session-edit/session-edit.page'; const routes: Routes = [ { @@ -17,6 +18,7 @@ const routes: Routes = [ children: [ // tab one { path: 'sessions', component: SessionsSetup, outlet: 'sessions' }, + { path: 'update/:id', component: SessionEditPage, outlet: 'sessions'}, // tab two { path: 'speaker', component: SpeakersSetup, outlet: 'speaker' }, { path: 'edit/:id', component: SpeakerEditPage, outlet: 'speaker' }, diff --git a/src/app/setup/tabs-setup/tabs-setup.module.ts b/src/app/setup/tabs-setup/tabs-setup.module.ts index 94e851a64..35af3fa3b 100644 --- a/src/app/setup/tabs-setup/tabs-setup.module.ts +++ b/src/app/setup/tabs-setup/tabs-setup.module.ts @@ -15,6 +15,7 @@ import { SupportSetupModule } from '../support/support.module'; import { PartOfDaySetupModule } from '../part-of-day/part-of-day.module'; import { PartOfDayNewPageModule } from '../part-of-day/part-of-day-new/part-of-day-new.module'; import { SpeakerEditPageModule } from '../speakers/speaker-edit/speaker-edit.module'; +import { SessionEditPageModule } from '../sessions/session-edit/session-edit.module'; const routes: Routes = [ { @@ -29,6 +30,7 @@ const routes: Routes = [ FormsModule, IonicModule, SessionsSetupModule, + SessionEditPageModule, SpeakersSetupModule, SpeakerEditPageModule, TracksSetupModule, diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts index 0e601f054..bd20d25b0 100644 --- a/src/app/setup/tracks/tracks-setup.ts +++ b/src/app/setup/tracks/tracks-setup.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { UserData } from '../../providers/user-data'; import { Router } from '@angular/router'; import { Track, Session } from '../../models'; @@ -11,7 +11,7 @@ import { AlertController } from '@ionic/angular'; templateUrl: './tracks-setup.html', styleUrls: ['./tracks-setup.scss'], }) -export class TracksSetup { +export class TracksSetup implements OnInit { tracks: Track[]; sessions: Session[]; @@ -19,20 +19,20 @@ export class TracksSetup { succeed = false; jobDescription: string; - constructor(private userData: UserData, - private sessionData: SessionData, - private confData: ConferenceData, + constructor(private userProvider: UserData, + private sessionProvider: SessionData, + private confProvider: ConferenceData, private router: Router, private alertCtrl: AlertController) { } - ionViewWillEnter() { - this.userData.getUser().then(user => { + ngOnInit() { + this.userProvider.getUser().then(user => { if ( !user || user.username !== 'admin') { this.router.navigateByUrl('/tutorial'); } else { - this.confData.getTracks().subscribe(data => { + this.confProvider.getTracks().subscribe(data => { this.tracks = data; - this.sessionData.getSessions().subscribe(session => { + this.sessionProvider.getSessions().subscribe(session => { this.sessions = session; }); }); @@ -40,8 +40,6 @@ export class TracksSetup { }); } - ionViewDidLeave() {} - async addNewTrack() { const addForm = await this.alertCtrl.create({ header: 'Add a Track', @@ -54,7 +52,7 @@ export class TracksSetup { if (this.isTheValueUsed(data.newName)) { alert(data.newName + ' was used already. Try another.'); } else { - this.confData.addTrack({ name: data.newName }); + this.confProvider.addTrack({ name: data.newName }); this.succeed = true; this.jobDescription = 'A new Track has been added.'; } @@ -87,7 +85,7 @@ export class TracksSetup { if (this.isTheValueUsed(data.newName)) { alert(data.newName + ' was used already. Try another.'); } else { - this.confData.updateTrack(track, data.newName ); + this.confProvider.updateTrack(track, data.newName ); this.succeed = true; this.jobDescription = 'Name has been changed.'; } @@ -120,7 +118,7 @@ export class TracksSetup { { text: 'Remove', handler: () => { - this.confData.removeTrack(track); + this.confProvider.removeTrack(track); } } ], From c5229ff8f9a7420eff68b40bc5d8806a5b8b3da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 10:26:39 -0500 Subject: [PATCH 36/44] added 'select speakers module' to session-edit. --- src/app/app-routing.module.ts | 3 +- src/app/pages/login/login.ts | 23 +++++- src/app/pages/signup/signup.ts | 23 +++++- src/app/providers/function-data.ts | 11 ++- .../pick-speakers/pick-speakers.module.ts | 26 +++++++ .../pick-speakers/pick-speakers.page.html | 36 +++++++++ .../pick-speakers/pick-speakers.page.scss | 0 .../pick-speakers/pick-speakers.page.ts | 54 ++++++++++++++ .../session-edit/session-edit.module.ts | 5 +- .../session-edit/session-edit.page.html | 57 +++++++++++++++ .../session-edit/session-edit.page.scss | 11 +++ .../session-edit/session-edit.page.ts | 73 ++++++++++++++++++- src/app/setup/sessions/sessions-setup.ts | 14 +--- src/app/setup/sessions/sessions.module.ts | 4 +- 14 files changed, 316 insertions(+), 24 deletions(-) create mode 100644 src/app/setup/sessions/pick-speakers/pick-speakers.module.ts create mode 100644 src/app/setup/sessions/pick-speakers/pick-speakers.page.html create mode 100644 src/app/setup/sessions/pick-speakers/pick-speakers.page.scss create mode 100644 src/app/setup/sessions/pick-speakers/pick-speakers.page.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 303773d0d..fdf06b630 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -35,7 +35,8 @@ const routes: Routes = [ path: 'setup', loadChildren: './setup/tabs-setup/tabs-setup.module#TabsSetupPageModule' }, - { path: 'session-edit', loadChildren: './setup/sessions/session-edit/session-edit.module#SessionEditPageModule' } + { path: 'session-edit', loadChildren: './setup/sessions/session-edit/session-edit.module#SessionEditPageModule' }, + { path: 'pick-speakers', loadChildren: './setup/sessions/pick-speakers/pick-speakers.module#PickSpeakersPageModule' } ]; @NgModule({ diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index f7d2c1d4d..885bc2c87 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -4,6 +4,7 @@ import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { User } from '../../models'; +import { AlertController } from '@ionic/angular'; @Component({ selector: 'page-login', @@ -19,6 +20,7 @@ export class LoginPage implements OnInit { constructor(public userData: UserData, public router: Router, + private alertCtrl: AlertController, private userProvider: UserData) { } ngOnInit() { @@ -36,10 +38,10 @@ export class LoginPage implements OnInit { this.userData.login(user); this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } else { - alert('Invalid password. Try again.'); + this.onError('Invalid password. Try again.'); } } else { - alert('User not found. Try again.'); + this.onError('User not found. Try again.'); } } } @@ -54,4 +56,21 @@ export class LoginPage implements OnInit { onSignup() { this.router.navigateByUrl('/signup'); } + + async onError(message: string) { + const alert = await this.alertCtrl.create({ + header: 'Confirm Login', + message: message, + buttons: [ + { + text: 'ok', + role: 'cancel', + handler: () => { + } + } + ], + backdropDismiss: false + }); + await alert.present(); + } } diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 627623bc4..5ee593e4d 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -5,6 +5,7 @@ import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { ConferenceData } from '../../providers/conference-data'; import { User, Track } from '../../models'; +import { AlertController } from '@ionic/angular'; @Component({ selector: 'page-signup', @@ -22,6 +23,7 @@ export class SignupPage implements OnInit { submitted = false; constructor(public router: Router, + private alertCtrl: AlertController, public userProvider: UserData, public dataProvider: ConferenceData) {} @@ -38,9 +40,9 @@ export class SignupPage implements OnInit { this.submitted = true; if (form.valid && this.signup.password === this.confirmPassword) { if (this.isNameUsed(this.signup.username)) { - alert('Name is already taken.'); + this.onError('Name is already taken.'); } else if (this.isEmailUsed(this.signup.email)) { - alert('Email is already taken.'); + this.onError('Email is already taken.'); } else { this.setTrackFilter(); this.userProvider.signup(this.signup); @@ -62,4 +64,21 @@ export class SignupPage implements OnInit { isEmailUsed(email) { return this.users.find(ur => ur.email.toLowerCase() === email.toLowerCase()); } + + async onError(message: string) { + const alert = await this.alertCtrl.create({ + header: 'Confirm Signup', + message: message, + buttons: [ + { + text: 'ok', + role: 'cancel', + handler: () => { + } + } + ], + backdropDismiss: false + }); + await alert.present(); + } } diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index dc8816c89..f7609ebfd 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -5,7 +5,7 @@ import { Injectable } from '@angular/core'; }) export class FunctionlData { - getDateFormat(date: Date) { + getDateFormat(date?: Date) { if (!date) { date = new Date(); } @@ -15,6 +15,15 @@ export class FunctionlData { this.reform2digits(dateArray[1]); } + // change date format : USA <-> EU + changeDateFormat(date: string) { + const arr = date.split('-'); + if (arr[0].length > 3) { + return `${arr[1]}-${arr[2]}-${arr[0]}`; + } + return `${arr[2]}-${arr[0]}-${arr[1]}`; + } + getAmPmTimeFormat(time: string): string { if (!time) { return '00:00 am' ; } let t = +time.split(':')[0]; diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts b/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts new file mode 100644 index 000000000..af79c06dd --- /dev/null +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PickSpeakersPage } from './pick-speakers.page'; + +const routes: Routes = [ + { + path: '', + component: PickSpeakersPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [PickSpeakersPage] +}) +export class PickSpeakersPageModule {} diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.html b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html new file mode 100644 index 000000000..03dafaf20 --- /dev/null +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html @@ -0,0 +1,36 @@ + + + + Cancel + + + Select Speakers + + + Save + + + + + + + + + + + + Speaker + + + + {{ spk.name }} ( {{ spk.phone }} ) + + + + + + + Unselect All Speakers + + + diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.scss b/src/app/setup/sessions/pick-speakers/pick-speakers.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts b/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts new file mode 100644 index 000000000..d28ca3e68 --- /dev/null +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts @@ -0,0 +1,54 @@ +import { Component, OnInit } from '@angular/core'; +import { NavParams, ModalController } from '@ionic/angular'; +import { Speaker } from '../../../models'; + +@Component({ + selector: 'pick-speakers', + templateUrl: './pick-speakers.page.html', + styleUrls: ['./pick-speakers.page.scss'], +}) +export class PickSpeakersPage implements OnInit { + + queryText = ''; + s_speakers: { + id: string, name: string, phone: string, + isChecked: boolean + }[] = []; + + constructor(private navParams: NavParams, + private modalCtrl: ModalController) { } + + ngOnInit() { + const spks = this.navParams.get('speakers'); + const IDs = this.navParams.get('ids'); + spks.forEach(spk => { + const idx = IDs.findIndex(id => id === spk.id); + if (idx > -1) { + this.s_speakers.push({ isChecked: true, id: spk.id, name: spk.name, phone: spk.phone }); + } else { + this.s_speakers.push({ isChecked: false, id: spk.id, name: spk.name, phone: spk.phone }); + } + }); + } + + unselectAll() { + this.s_speakers.forEach(spk => { spk.isChecked = false; }); + } + + applySelection() { + const IDs = []; + this.s_speakers.forEach(spk => { + if (spk.isChecked) { + IDs.push(spk.id); + } + }); + this.dismiss(IDs); + } + + dismiss(data: any) { + // using the injected ModalController this page + // can "dismiss" itself and pass back data + this.modalCtrl.dismiss(data); + } + +} diff --git a/src/app/setup/sessions/session-edit/session-edit.module.ts b/src/app/setup/sessions/session-edit/session-edit.module.ts index 4f04e0e6a..2666de60c 100644 --- a/src/app/setup/sessions/session-edit/session-edit.module.ts +++ b/src/app/setup/sessions/session-edit/session-edit.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Routes, RouterModule } from '@angular/router'; - import { IonicModule } from '@ionic/angular'; import { SessionEditPage } from './session-edit.page'; @@ -21,6 +20,8 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [SessionEditPage] + declarations: [ + SessionEditPage + ] }) export class SessionEditPageModule {} diff --git a/src/app/setup/sessions/session-edit/session-edit.page.html b/src/app/setup/sessions/session-edit/session-edit.page.html index 78b0c327b..86e85be51 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.html +++ b/src/app/setup/sessions/session-edit/session-edit.page.html @@ -12,5 +12,62 @@ + + + Title: + + + + Date: + + + + From: + + To : + + + + Location: + + + + Description + + + + + + Speakers: + + + + + + + {{ s.name }} ( {{ s.phone }} ) + + + + + + + + Tracks: + + + + + + + {{ t.name }} + + + + + + diff --git a/src/app/setup/sessions/session-edit/session-edit.page.scss b/src/app/setup/sessions/session-edit/session-edit.page.scss index e69de29bb..7284b7b90 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.scss +++ b/src/app/setup/sessions/session-edit/session-edit.page.scss @@ -0,0 +1,11 @@ +.get-time { + width: 100px; +} + +.get-date { + margin-right: 30px; +} + +ion-textarea { + height: 210px; +} diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts index 9fb141b34..fdfaae1dd 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.ts +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -1,7 +1,13 @@ import { Component, OnInit } from '@angular/core'; -import { Session } from '../../../models'; + +import { Session, Track, Speaker } from '../../../models'; import { SessionData } from '../../../providers/session-data'; import { Router, ActivatedRoute } from '@angular/router'; +import { FunctionlData } from '../../../providers/function-data'; +import { SpeakerData } from '../../../providers/speaker-data'; +import { ConferenceData } from '../../../providers/conference-data'; +import { ModalController } from '@ionic/angular'; +import { PickSpeakersPage } from '../pick-speakers/pick-speakers.page'; @Component({ selector: 'session-edit', @@ -13,17 +19,30 @@ export class SessionEditPage implements OnInit { mode: string; id: string; session: Session; + minYear: string; + maxYear: string; + tracks: Track[]; + speakers: Speaker[]; + s_tracks: { name: string, isChecked: boolean }[] = []; + moreSpeakers = false; constructor(private activatedRoute: ActivatedRoute, + private modalCtrl: ModalController, private sessionProvider: SessionData, + private speakerProvider: SpeakerData, + private confProvider: ConferenceData, + private funProvider: FunctionlData, private router: Router) { } ngOnInit() { this.mode = this.activatedRoute.snapshot.paramMap.get('id'); if (this.mode === 'New') { + const today = new Date(); + this.minYear = '' + (today.getFullYear() - 20); + this.maxYear = '' + (+this.minYear + 40); this.session = { name: '', - date: '', // 2018-12-06 + date: this.funProvider.getDateFormat(), // 2018-12-06 timeStart: '', // 15:30 for 3:30pm timeEnd: '', location: '', @@ -36,8 +55,58 @@ export class SessionEditPage implements OnInit { this.sessionProvider.getSession(this.id).then(data => { this.session = data; this.session.id = this.id; + this.minYear = '' + (+data.date.slice(0, 4) - 5); + this.maxYear = '' + (+this.minYear + 15); }); } + this.getSpeakersTracks(); + } + + getSpeakersTracks() { + this.speakerProvider.getSpeakers().subscribe(data => { + this.speakers = data; + }); + + this.confProvider.getTracks().subscribe(data => { + this.tracks = data; + }); + } + + isInSession(key: string, type: string): any { + if (type === 'Speaker') { + return this.session.speakerIDs.find(id => id === key); + } + return this.session.tracks.find(name => name === key); + } + + onRemoveSpeaker(s_id) { + const idx = this.session.speakerIDs.findIndex(id => id === s_id); + if (idx > -1) { + this.session.speakerIDs.splice(idx, 1); + } + } + + async selectSpeakers() { + const modal = await this.modalCtrl.create({ + component: PickSpeakersPage, + componentProps: { speakers: this.speakers, ids: this.session.speakerIDs } + }); + await modal.present(); + + const { data } = await modal.onWillDismiss(); + if (data) { + this.session.speakerIDs = data; + } + } + + onSubmit() { + if (this.mode === 'New') { + console.log('saved', this.session.date); + } else { + console.log('updated', this.session.date); + } + console.log(typeof this.session.date); + this.onExit(); } onExit() { diff --git a/src/app/setup/sessions/sessions-setup.ts b/src/app/setup/sessions/sessions-setup.ts index bf7402ac4..242f1966c 100644 --- a/src/app/setup/sessions/sessions-setup.ts +++ b/src/app/setup/sessions/sessions-setup.ts @@ -4,10 +4,8 @@ import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { SessionData } from '../../providers/session-data'; -import { SpeakerData } from '../../providers/speaker-data'; -import { ConferenceData } from '../../providers/conference-data'; -import { Session, Speaker, Track } from '../../models'; +import { Session } from '../../models'; @Component({ selector: 'sessions', @@ -20,13 +18,9 @@ export class SessionsSetup implements OnInit { endDate = '2019-01-31'; queryText = ''; sessions: Session[]; - speakers: Speaker[]; - tracks: Track[]; constructor(private userProvider: UserData, private sessionProvider: SessionData, - private speakerProvider: SpeakerData, - private confProvider: ConferenceData, private alertCtrl: AlertController, private router: Router) { } @@ -39,12 +33,6 @@ export class SessionsSetup implements OnInit { .subscribe(data => { this.sessions = data; }); - this.speakerProvider.getSpeakers().subscribe(data => { - this.speakers = data; - }); - this.confProvider.getTracks().subscribe(data => { - this.tracks = data; - }); } }); } diff --git a/src/app/setup/sessions/sessions.module.ts b/src/app/setup/sessions/sessions.module.ts index e61aa20ca..f6c885911 100644 --- a/src/app/setup/sessions/sessions.module.ts +++ b/src/app/setup/sessions/sessions.module.ts @@ -6,6 +6,7 @@ import { Routes, RouterModule } from '@angular/router'; import { IonicModule } from '@ionic/angular'; import { SessionsSetup } from './sessions-setup'; +import { PickSpeakersPage } from './pick-speakers/pick-speakers.page'; const routes: Routes = [ { @@ -21,6 +22,7 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [SessionsSetup] + declarations: [SessionsSetup, PickSpeakersPage], + entryComponents: [PickSpeakersPage] }) export class SessionsSetupModule {} From fee6b6047bcf427b734f8eee93211fb615bc2e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 11:16:22 -0500 Subject: [PATCH 37/44] updated 'check validation of input' to session-edit --- src/app/providers/function-data.ts | 7 +++ .../part-of-day-new/part-of-day-new.page.ts | 13 ++--- .../session-edit/session-edit.page.html | 8 +++- .../session-edit/session-edit.page.ts | 48 +++++++++++++++---- 4 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index f7609ebfd..c81273222 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -51,4 +51,11 @@ export class FunctionlData { value = +value; return ((value < 10) ? '0' : '') + value ; } + + addMinute(time) { + const [h, m] = time.split(':'); + const hour = this.reform2digits((m === '59') ? +h + 1 : +h); + const min = this.reform2digits((m === '59') ? 0 : +m + 1); + return (hour === '24') ? null : hour + ':' + min ; + } } diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts index e9b8b1c86..9e6343cf4 100644 --- a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts @@ -44,16 +44,9 @@ export class PartOfDayNewPage implements OnInit { if (this.len === 0) { this.timeFrom = '00:00'; } else { - this.timeFrom = this.getNextTime(this.newPODs[this.len - 1].timeTo); + this.timeFrom = this.funProvider.addMinute(this.newPODs[this.len - 1].timeTo); } - this.timeTo = this.getNextTime(this.timeFrom); - } - - getNextTime(time) { - const [h, m] = time.split(':'); - const hour = this.funProvider.reform2digits((m === '59') ? +h + 1 : +h); - const min = this.funProvider.reform2digits((m === '59') ? 0 : +m + 1); - return (hour === '24') ? null : hour + ':' + min ; + this.timeTo = this.funProvider.addMinute(this.timeFrom); } cancelInput() { @@ -91,7 +84,7 @@ export class PartOfDayNewPage implements OnInit { this.cdRef.detectChanges(); if (value <= this.timeFrom) { alert('Wrong time for To. Try again.'); - this.timeTo = this.getNextTime(this.timeFrom); + this.timeTo = this.funProvider.addMinute(this.timeFrom); } } diff --git a/src/app/setup/sessions/session-edit/session-edit.page.html b/src/app/setup/sessions/session-edit/session-edit.page.html index 86e85be51..53199cd6d 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.html +++ b/src/app/setup/sessions/session-edit/session-edit.page.html @@ -25,9 +25,13 @@ From: - + To : - + Location: diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts index fdfaae1dd..7aee51569 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.ts +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; import { Session, Track, Speaker } from '../../../models'; import { SessionData } from '../../../providers/session-data'; @@ -27,6 +27,7 @@ export class SessionEditPage implements OnInit { moreSpeakers = false; constructor(private activatedRoute: ActivatedRoute, + private cdRef: ChangeDetectorRef, private modalCtrl: ModalController, private sessionProvider: SessionData, private speakerProvider: SpeakerData, @@ -43,8 +44,8 @@ export class SessionEditPage implements OnInit { this.session = { name: '', date: this.funProvider.getDateFormat(), // 2018-12-06 - timeStart: '', // 15:30 for 3:30pm - timeEnd: '', + timeStart: '10:00', // 15:30 for 3:30pm + timeEnd: '10:00', location: '', description: '', speakerIDs: [], // speaker's id @@ -99,18 +100,47 @@ export class SessionEditPage implements OnInit { } } + changeTimeEnd(value) { + this.cdRef.detectChanges(); + if (value > this.session.timeEnd) { + this.session.timeEnd = this.funProvider.addMinute(value); + } + } + + confirmTimeEnd(value) { + this.cdRef.detectChanges(); + if (value <= this.session.timeStart) { + alert('Wrong time for To. Try again.'); + this.session.timeEnd = this.funProvider.addMinute(this.session.timeStart); + } + } + onSubmit() { - if (this.mode === 'New') { - console.log('saved', this.session.date); - } else { - console.log('updated', this.session.date); + this.session.name = this.session.name.trim(); + this.session.location = this.session.location.trim(); + if (this.isValidAll()) { + if (this.mode === 'New') { + console.log('saved', this.session); + } else { + console.log('updated', this.session); + } + this.onExit(); } - console.log(typeof this.session.date); - this.onExit(); } onExit() { this.router.navigateByUrl('/setup/tabs/(sessions:sessions)'); } + isValidAll() { + if (this.session.name.length === 0) { + alert('Need a Title for the session. Try again.'); + return false; + } else if (this.session.timeEnd <= this.session.timeStart) { + alert('TimeTo has to be later than TimeFrom. Try again.'); + return false; + } + return true; + } + } From f6f1276577ab18537d7a38cc9598fc4a354026fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 12:15:42 -0500 Subject: [PATCH 38/44] Fixed a bug and updated 'alert mode' in account.ts --- src/app/pages/account/account.ts | 51 ++++++++++++++++++------------ src/app/pages/login/login.ts | 25 +++------------ src/app/providers/function-data.ts | 20 ++++++++++++ 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/app/pages/account/account.ts b/src/app/pages/account/account.ts index 581b04229..e3b732ffc 100644 --- a/src/app/pages/account/account.ts +++ b/src/app/pages/account/account.ts @@ -4,6 +4,7 @@ import { AlertController } from '@ionic/angular'; import { UserData } from '../../providers/user-data'; import { User } from '../../models'; +import { FunctionlData } from '../../providers/function-data'; @Component({ selector: 'page-account', @@ -12,6 +13,7 @@ import { User } from '../../models'; encapsulation: ViewEncapsulation.None }) export class AccountPage implements AfterViewInit { + header = `User's Info`; users: User[]; user: User; succeed: boolean; @@ -20,7 +22,8 @@ export class AccountPage implements AfterViewInit { constructor(public alertCtrl: AlertController, public router: Router, - public userProvider: UserData) {} + public userProvider: UserData, + private funProvider: FunctionlData) {} ngAfterViewInit() { this.userProvider.getUsers().subscribe( @@ -60,17 +63,21 @@ export class AccountPage implements AfterViewInit { { text: 'Ok', handler: (data: any) => { - if (this.isTheValueUsed(data.username)) { - alert(data.username + ' was used already. Try another.'); + if (data.username.trim().length < 4) { + this.funProvider.onError(this.header, 'Username should has more then 3 letters. Try again.'); } else { - // update after getter user's avatar as string. - this.userProvider.getUser().then(user => { - user.username = data.username; - this.updateUserData(user); - }); - this.user.username = data.username; - this.succeed = true; - this.jobDescription = 'Username has been changed.'; + if (this.isTheValueUsed(data.username)) { + this.funProvider.onError(this.header, data.username + ' was used already. Try another.'); + } else { + // update after getter user's avatar as string. + this.userProvider.getUser().then(user => { + user.username = data.username; + this.updateUserData(user); + }); + this.user.username = data.username; + this.succeed = true; + this.jobDescription = 'Username has been changed.'; + } } } } @@ -98,15 +105,16 @@ export class AccountPage implements AfterViewInit { text: 'Ok', handler: (data: any) => { if (this.isTheValueUsed(data.email)) { - alert(data.email + ' was used already. Try another.'); + this.funProvider.onError(this.header, data.email + ' was used already. Try another.'); } else { // update after getter user's avatar as string. this.userProvider.getUser().then(user => { - this.user.email = data.email; + user.email = data.email; this.updateUserData(user); + this.user.email = data.email; + this.succeed = true; + this.jobDescription = 'Email has been changed.'; }); - this.succeed = true; - this.jobDescription = 'Email has been changed.'; } } } @@ -134,19 +142,20 @@ export class AccountPage implements AfterViewInit { text: 'Ok', handler: (data: any) => { if (this.user.password !== data.currentPW) { - alert('Current password does not match your password.'); + this.funProvider.onError(this.header, 'Current password does not match your password.'); } else if (data.newPW.length < 4) { - alert('Password should be more than 3 characters.'); + this.funProvider.onError(this.header, 'Password should be more than 3 characters.'); } else if (data.newPW !== data.confirmPW) { - alert('New password does not match Confirm password.'); + this.funProvider.onError(this.header, 'New password does not match Confirm password.'); } else { // update after getter user's avatar as string. this.userProvider.getUser().then(user => { - this.user.password = data.newPW; + user.password = data.newPW; this.updateUserData(user); + this.user.password = data.newPW; + this.succeed = true; + this.jobDescription = 'Password has been changed.'; }); - this.succeed = true; - this.jobDescription = 'Password has been changed.'; } } } diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 885bc2c87..a4f37f53b 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -4,7 +4,7 @@ import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { User } from '../../models'; -import { AlertController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; @Component({ selector: 'page-login', @@ -20,7 +20,7 @@ export class LoginPage implements OnInit { constructor(public userData: UserData, public router: Router, - private alertCtrl: AlertController, + private funProvider: FunctionlData, private userProvider: UserData) { } ngOnInit() { @@ -38,10 +38,10 @@ export class LoginPage implements OnInit { this.userData.login(user); this.router.navigateByUrl('/app/tabs/(schedule:schedule)'); } else { - this.onError('Invalid password. Try again.'); + this.funProvider.onError('Confirm Login', 'Invalid password. Try again.'); } } else { - this.onError('User not found. Try again.'); + this.funProvider.onError('Confirm Login', 'User not found. Try again.'); } } } @@ -56,21 +56,4 @@ export class LoginPage implements OnInit { onSignup() { this.router.navigateByUrl('/signup'); } - - async onError(message: string) { - const alert = await this.alertCtrl.create({ - header: 'Confirm Login', - message: message, - buttons: [ - { - text: 'ok', - role: 'cancel', - handler: () => { - } - } - ], - backdropDismiss: false - }); - await alert.present(); - } } diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index c81273222..f11850b39 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -1,10 +1,30 @@ import { Injectable } from '@angular/core'; +import { AlertController } from '@ionic/angular'; @Injectable({ providedIn: 'root' }) export class FunctionlData { + constructor(private alertCtrl: AlertController) {} + + async onError(header: string, message: string) { + const alert = await this.alertCtrl.create({ + header: header, + message: message, + buttons: [ + { + text: 'ok', + role: 'cancel', + handler: () => { + } + } + ], + backdropDismiss: false + }); + await alert.present(); + } + getDateFormat(date?: Date) { if (!date) { date = new Date(); From 077831a7d0a0eaaa581abfaa169bfb9b3fe0c913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 12:40:09 -0500 Subject: [PATCH 39/44] updated all alert to the provided function 'onError()'. --- src/app/pages/signup/signup.ts | 30 +++++-------------- .../part-of-day-new/part-of-day-new.page.ts | 6 ++-- .../setup/part-of-day/part-of-day-setup.ts | 4 ++- .../session-edit/session-edit.page.ts | 6 ++-- .../speaker-edit/speaker-edit.page.ts | 21 +++++++------ src/app/setup/tracks/tracks-setup.ts | 7 +++-- 6 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/app/pages/signup/signup.ts b/src/app/pages/signup/signup.ts index 5ee593e4d..17cc556d9 100644 --- a/src/app/pages/signup/signup.ts +++ b/src/app/pages/signup/signup.ts @@ -5,7 +5,7 @@ import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { ConferenceData } from '../../providers/conference-data'; import { User, Track } from '../../models'; -import { AlertController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; @Component({ selector: 'page-signup', @@ -14,6 +14,7 @@ import { AlertController } from '@ionic/angular'; encapsulation: ViewEncapsulation.None }) export class SignupPage implements OnInit { + header = 'Confirm Signup'; users: User[]; signup: User = { username: '', password: '', email: '', favorites: [], trackFilter: [] @@ -23,8 +24,8 @@ export class SignupPage implements OnInit { submitted = false; constructor(public router: Router, - private alertCtrl: AlertController, public userProvider: UserData, + private funProvider: FunctionlData, public dataProvider: ConferenceData) {} ngOnInit() { @@ -39,10 +40,12 @@ export class SignupPage implements OnInit { onSignup(form: NgForm) { this.submitted = true; if (form.valid && this.signup.password === this.confirmPassword) { - if (this.isNameUsed(this.signup.username)) { - this.onError('Name is already taken.'); + if (this.signup.username.trim().length < 4) { + this.funProvider.onError(this.header, 'Name should has more then 3 letters. Try again.'); + } else if (this.isNameUsed(this.signup.username)) { + this.funProvider.onError(this.header, 'Name is already taken. Try another.'); } else if (this.isEmailUsed(this.signup.email)) { - this.onError('Email is already taken.'); + this.funProvider.onError(this.header, 'Email is already taken. Try another.'); } else { this.setTrackFilter(); this.userProvider.signup(this.signup); @@ -64,21 +67,4 @@ export class SignupPage implements OnInit { isEmailUsed(email) { return this.users.find(ur => ur.email.toLowerCase() === email.toLowerCase()); } - - async onError(message: string) { - const alert = await this.alertCtrl.create({ - header: 'Confirm Signup', - message: message, - buttons: [ - { - text: 'ok', - role: 'cancel', - handler: () => { - } - } - ], - backdropDismiss: false - }); - await alert.present(); - } } diff --git a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts index 9e6343cf4..fa9b58c08 100644 --- a/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts +++ b/src/app/setup/part-of-day/part-of-day-new/part-of-day-new.page.ts @@ -12,7 +12,7 @@ import { UserData } from '../../../providers/user-data'; styleUrls: ['./part-of-day-new.page.scss'], }) export class PartOfDayNewPage implements OnInit { - + header = 'Part Of Day'; PODs: PartOfDay[] = []; newPODs: PartOfDay[] = []; title = ''; @@ -55,7 +55,7 @@ export class PartOfDayNewPage implements OnInit { saveInput() { if (this.isTheValueUsed()) { - alert('Description is not valid. Try again'); + this.funProvider.onError(this.header, 'Description is not valid. Try again'); } else { const newPOD = { indexKey: this.newPODs.length + 1, @@ -83,7 +83,7 @@ export class PartOfDayNewPage implements OnInit { checkTimeTo(value) { this.cdRef.detectChanges(); if (value <= this.timeFrom) { - alert('Wrong time for To. Try again.'); + this.funProvider.onError(this.header, 'Wrong time for To. Try again.'); this.timeTo = this.funProvider.addMinute(this.timeFrom); } } diff --git a/src/app/setup/part-of-day/part-of-day-setup.ts b/src/app/setup/part-of-day/part-of-day-setup.ts index 0d1e1a330..a773951da 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.ts +++ b/src/app/setup/part-of-day/part-of-day-setup.ts @@ -3,6 +3,7 @@ import { PartOfDay } from '../../models'; import { ConferenceData } from '../../providers/conference-data'; import { Router } from '@angular/router'; import { AlertController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; @Component({ selector: 'part-of-day', @@ -15,6 +16,7 @@ export class PartOfDaySetup implements OnInit { constructor(private confData: ConferenceData, private alertCtrl: AlertController, + private funProvider: FunctionlData, private router: Router) { } ngOnInit() { @@ -38,7 +40,7 @@ export class PartOfDaySetup implements OnInit { handler: (data: any) => { data.newName = data.newName.trim(); if (this.isTheValueUsed(data.newName)) { - alert(data.newName + ' was used already. Try another.'); + this.funProvider.onError('Part Of Day', data.newName + ' was used already. Try another.'); } else { pod.name = data.newName; this.confData.updatePartOfDay(pod); diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts index 7aee51569..53632a575 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.ts +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -110,7 +110,7 @@ export class SessionEditPage implements OnInit { confirmTimeEnd(value) { this.cdRef.detectChanges(); if (value <= this.session.timeStart) { - alert('Wrong time for To. Try again.'); + this.funProvider.onError('Confirm Time', 'Wrong time for To. Try again.'); this.session.timeEnd = this.funProvider.addMinute(this.session.timeStart); } } @@ -134,10 +134,10 @@ export class SessionEditPage implements OnInit { isValidAll() { if (this.session.name.length === 0) { - alert('Need a Title for the session. Try again.'); + this.funProvider.onError('Confirm Title', 'Need a Title for the session. Try again.'); return false; } else if (this.session.timeEnd <= this.session.timeStart) { - alert('TimeTo has to be later than TimeFrom. Try again.'); + this.funProvider.onError('Confirm Time', 'TimeTo has to be later than TimeFrom. Try again.'); return false; } return true; diff --git a/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts index 4134fa5da..77fa9f988 100644 --- a/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts +++ b/src/app/setup/speakers/speaker-edit/speaker-edit.page.ts @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Speaker } from '../../../models'; import { SpeakerData } from '../../../providers/speaker-data'; +import { FunctionlData } from '../../../providers/function-data'; @Component({ selector: 'speaker-edit', @@ -11,6 +12,7 @@ import { SpeakerData } from '../../../providers/speaker-data'; }) export class SpeakerEditPage implements OnInit { + header = `Speaker's Info`; mode: string; id: string; speaker: Speaker; @@ -18,7 +20,8 @@ export class SpeakerEditPage implements OnInit { currentUrl = ''; constructor(private activatedRoute: ActivatedRoute, - private speakerData: SpeakerData, + private speakerProvider: SpeakerData, + private funProvider: FunctionlData, private router: Router) { } ngOnInit() { @@ -38,7 +41,7 @@ export class SpeakerEditPage implements OnInit { }; } else { [this.id, this.mode] = [this.mode, 'Edit']; - this.speakerData.getSpeaker(this.id).then(data => { + this.speakerProvider.getSpeaker(this.id).then(data => { this.speaker = data; this.speaker.id = this.id; // to keep profile's path as string. @@ -50,11 +53,11 @@ export class SpeakerEditPage implements OnInit { onSubmit() { if (this.verifiedInput()) { if (this.mode === 'New') { - this.speakerData.addNewSpeaker(this.speaker); + this.speakerProvider.addNewSpeaker(this.speaker); } else { // to reassign it's origin path as string. this.speaker.profilePic = this.currentUrl; - this.speakerData.updateSpeaker(this.speaker); + this.speakerProvider.updateSpeaker(this.speaker); } this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); } @@ -71,13 +74,13 @@ export class SpeakerEditPage implements OnInit { this.speaker.twitter = this.speaker.twitter.trim() ; this.speaker.about = this.speaker.about.trim() ; if (this.speaker.name.length < 4) { - alert('Name should be more than 4 digits.'); + this.funProvider.onError(this.header, 'Name should be more than 3 digits.'); } if (this.isNameUsed()) { - alert('Name already exist. Try another.'); + this.funProvider.onError(this.header, 'Name already exist. Try another.'); } if (this.isEmailUsed()) { - alert('Email is not valid. Try another.'); + this.funProvider.onError(this.header, 'Email is not valid. Try another.'); } if (this.speaker.phone.length < 10) { - alert('Phone number is not valid. Try again.'); + this.funProvider.onError(this.header, 'Phone number is not valid. Try again.'); } else { return true; } @@ -102,7 +105,7 @@ export class SpeakerEditPage implements OnInit { const oldUrl = this.speaker.profilePic; const id = this.speaker.id; this.speaker.profilePic = path; - this.speakerData.updateSpeaker(this.speaker); + this.speakerProvider.updateSpeaker(this.speaker); this.loadImage = false; this.router.navigateByUrl('/setup/tabs/(speaker:speaker)'); } diff --git a/src/app/setup/tracks/tracks-setup.ts b/src/app/setup/tracks/tracks-setup.ts index bd20d25b0..de8b8f1ec 100644 --- a/src/app/setup/tracks/tracks-setup.ts +++ b/src/app/setup/tracks/tracks-setup.ts @@ -5,6 +5,7 @@ import { Track, Session } from '../../models'; import { SessionData } from '../../providers/session-data'; import { ConferenceData } from '../../providers/conference-data'; import { AlertController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; @Component({ selector: 'tracks', @@ -13,6 +14,7 @@ import { AlertController } from '@ionic/angular'; }) export class TracksSetup implements OnInit { + header = `Track's Info`; tracks: Track[]; sessions: Session[]; newName: string; @@ -22,6 +24,7 @@ export class TracksSetup implements OnInit { constructor(private userProvider: UserData, private sessionProvider: SessionData, private confProvider: ConferenceData, + private funProvider: FunctionlData, private router: Router, private alertCtrl: AlertController) { } @@ -50,7 +53,7 @@ export class TracksSetup implements OnInit { handler: (data: any) => { data.newName = data.newName.trim(); if (this.isTheValueUsed(data.newName)) { - alert(data.newName + ' was used already. Try another.'); + this.funProvider.onError(this.header, data.newName + ' was used already. Try another.'); } else { this.confProvider.addTrack({ name: data.newName }); this.succeed = true; @@ -83,7 +86,7 @@ export class TracksSetup implements OnInit { handler: (data: any) => { data.newName = data.newName.trim(); if (this.isTheValueUsed(data.newName)) { - alert(data.newName + ' was used already. Try another.'); + this.funProvider.onError(this.header, data.newName + ' was used already. Try another.'); } else { this.confProvider.updateTrack(track, data.newName ); this.succeed = true; From 9419033837df04a412ba196600115b1b1a96075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 13:04:41 -0500 Subject: [PATCH 40/44] added search bar for 'Speaker-list'. --- src/app/pages/speaker-list/speaker-list.html | 8 ++++++-- src/app/pages/speaker-list/speaker-list.module.ts | 2 ++ src/app/pages/speaker-list/speaker-list.ts | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/pages/speaker-list/speaker-list.html b/src/app/pages/speaker-list/speaker-list.html index 89bdf002e..ee839b0c7 100644 --- a/src/app/pages/speaker-list/speaker-list.html +++ b/src/app/pages/speaker-list/speaker-list.html @@ -5,6 +5,9 @@ Speakers + + + @@ -12,9 +15,10 @@ - + - + Speaker profile pic diff --git a/src/app/pages/speaker-list/speaker-list.module.ts b/src/app/pages/speaker-list/speaker-list.module.ts index c99e4bcbf..b4c75b330 100644 --- a/src/app/pages/speaker-list/speaker-list.module.ts +++ b/src/app/pages/speaker-list/speaker-list.module.ts @@ -4,11 +4,13 @@ import { IonicModule } from '@ionic/angular'; import { SpeakerListPage } from './speaker-list'; import { SpeakerListPageRoutingModule } from './speaker-list-routing.module'; +import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ CommonModule, IonicModule, + FormsModule, SpeakerListPageRoutingModule ], declarations: [SpeakerListPage], diff --git a/src/app/pages/speaker-list/speaker-list.ts b/src/app/pages/speaker-list/speaker-list.ts index 280878d39..de568d846 100644 --- a/src/app/pages/speaker-list/speaker-list.ts +++ b/src/app/pages/speaker-list/speaker-list.ts @@ -14,6 +14,8 @@ import { UserData } from '../../providers/user-data'; encapsulation: ViewEncapsulation.None }) export class SpeakerListPage { + + queryText = ''; speakers: Speaker[]; constructor( From 647953d3097756b2bd1949530833d8e618f80559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 14:53:47 -0500 Subject: [PATCH 41/44] added 'pick-tracks mode' to the session-edit. --- src/app/app-routing.module.ts | 3 +- .../setup/part-of-day/part-of-day-setup.html | 2 +- .../pick-speakers/pick-speakers.page.html | 11 ++--- .../pick-speakers/pick-speakers.page.ts | 1 - .../pick-tracks/pick-tracks.module.ts | 26 ++++++++++ .../pick-tracks/pick-tracks.page.html | 36 ++++++++++++++ .../pick-tracks/pick-tracks.page.scss | 0 .../sessions/pick-tracks/pick-tracks.page.ts | 49 +++++++++++++++++++ .../session-edit/session-edit.page.html | 2 +- .../session-edit/session-edit.page.ts | 21 ++++++++ src/app/setup/sessions/sessions-setup.html | 2 +- src/app/setup/sessions/sessions.module.ts | 5 +- src/app/setup/speakers/speakers-setup.html | 2 +- src/app/setup/tracks/tracks-setup.html | 2 +- 14 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 src/app/setup/sessions/pick-tracks/pick-tracks.module.ts create mode 100644 src/app/setup/sessions/pick-tracks/pick-tracks.page.html create mode 100644 src/app/setup/sessions/pick-tracks/pick-tracks.page.scss create mode 100644 src/app/setup/sessions/pick-tracks/pick-tracks.page.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index fdf06b630..10c0413f7 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -36,7 +36,8 @@ const routes: Routes = [ loadChildren: './setup/tabs-setup/tabs-setup.module#TabsSetupPageModule' }, { path: 'session-edit', loadChildren: './setup/sessions/session-edit/session-edit.module#SessionEditPageModule' }, - { path: 'pick-speakers', loadChildren: './setup/sessions/pick-speakers/pick-speakers.module#PickSpeakersPageModule' } + // { path: 'pick-speakers', loadChildren: './setup/sessions/pick-speakers/pick-speakers.module#PickSpeakersPageModule' }, + // { path: 'pick-track', loadChildren: './setup/sessions/pick-track/pick-track.module#PickTrackPageModule' } ]; @NgModule({ diff --git a/src/app/setup/part-of-day/part-of-day-setup.html b/src/app/setup/part-of-day/part-of-day-setup.html index cd23966aa..3f5b99a4a 100644 --- a/src/app/setup/part-of-day/part-of-day-setup.html +++ b/src/app/setup/part-of-day/part-of-day-setup.html @@ -5,7 +5,7 @@ Part of Day - Create a New Set + Create New Set diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.html b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html index 03dafaf20..c5018b63f 100644 --- a/src/app/setup/sessions/pick-speakers/pick-speakers.page.html +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html @@ -1,12 +1,9 @@ - - Cancel - - Select Speakers + Cancel Save @@ -19,7 +16,9 @@ - Speaker + + Speakers + @@ -29,7 +28,7 @@ - + Unselect All Speakers diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts b/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts index d28ca3e68..1b85edc22 100644 --- a/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.page.ts @@ -1,6 +1,5 @@ import { Component, OnInit } from '@angular/core'; import { NavParams, ModalController } from '@ionic/angular'; -import { Speaker } from '../../../models'; @Component({ selector: 'pick-speakers', diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts b/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts new file mode 100644 index 000000000..e1a8aa36b --- /dev/null +++ b/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PickTracksPage } from './pick-tracks.page'; + +const routes: Routes = [ + { + path: '', + component: PickTracksPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [PickTracksPage] +}) +export class PickTracksPageModule {} diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.page.html b/src/app/setup/sessions/pick-tracks/pick-tracks.page.html new file mode 100644 index 000000000..28e9a243f --- /dev/null +++ b/src/app/setup/sessions/pick-tracks/pick-tracks.page.html @@ -0,0 +1,36 @@ + + + Select Tracks + + + Cancel + Save + + + + + + + + + + + + + Tracks + + + + + {{ tk.name }} + + + + + + + Unselect All Tracks + + + + \ No newline at end of file diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.page.scss b/src/app/setup/sessions/pick-tracks/pick-tracks.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.page.ts b/src/app/setup/sessions/pick-tracks/pick-tracks.page.ts new file mode 100644 index 000000000..ec0950da0 --- /dev/null +++ b/src/app/setup/sessions/pick-tracks/pick-tracks.page.ts @@ -0,0 +1,49 @@ +import { Component, OnInit } from '@angular/core'; +import { NavParams, ModalController } from '@ionic/angular'; + +@Component({ + selector: 'pick-tracks', + templateUrl: './pick-tracks.page.html', + styleUrls: ['./pick-tracks.page.scss'], +}) +export class PickTracksPage implements OnInit { + + queryText = ''; + s_tracks: { name: string, isChecked: boolean }[] = []; + + constructor(private navParams: NavParams, + private modalCtrl: ModalController) { } + + ngOnInit() { + const tks = this.navParams.get('tracks'); + const names = this.navParams.get('names'); + tks.forEach(tk => { + const idx = names.findIndex(name => name === tk.name); + if (idx > -1) { + this.s_tracks.push({ isChecked: true, name: tk.name }); + } else { + this.s_tracks.push({ isChecked: false, name: tk.name }); + } + }); + } + + unselectAll() { + this.s_tracks.forEach(tk => { tk.isChecked = false; }); + } + + applySelection() { + const selected = []; + this.s_tracks.forEach(tk => { + if (tk.isChecked) { + selected.push(tk.name); + } + }); + this.dismiss(selected); + } + + dismiss(data: any) { + // using the injected ModalController this page + // can "dismiss" itself and pass back data + this.modalCtrl.dismiss(data); + } +} diff --git a/src/app/setup/sessions/session-edit/session-edit.page.html b/src/app/setup/sessions/session-edit/session-edit.page.html index 53199cd6d..5e452b5ba 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.html +++ b/src/app/setup/sessions/session-edit/session-edit.page.html @@ -62,7 +62,7 @@ Tracks: - + diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts index 53632a575..383183908 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.ts +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -8,6 +8,7 @@ import { SpeakerData } from '../../../providers/speaker-data'; import { ConferenceData } from '../../../providers/conference-data'; import { ModalController } from '@ionic/angular'; import { PickSpeakersPage } from '../pick-speakers/pick-speakers.page'; +import { PickTracksPage } from '../pick-tracks/pick-tracks.page'; @Component({ selector: 'session-edit', @@ -100,6 +101,26 @@ export class SessionEditPage implements OnInit { } } + onRemoveTrack(s_name) { + const idx = this.session.tracks.findIndex(name => name === s_name); + if (idx > -1) { + this.session.tracks.splice(idx, 1); + } + } + + async selectTracks() { + const modal = await this.modalCtrl.create({ + component: PickTracksPage, + componentProps: { tracks: this.tracks, names: this.session.tracks } + }); + await modal.present(); + + const { data } = await modal.onWillDismiss(); + if (data) { + this.session.tracks = data; + } + } + changeTimeEnd(value) { this.cdRef.detectChanges(); if (value > this.session.timeEnd) { diff --git a/src/app/setup/sessions/sessions-setup.html b/src/app/setup/sessions/sessions-setup.html index f64b89537..9c31f7b2d 100644 --- a/src/app/setup/sessions/sessions-setup.html +++ b/src/app/setup/sessions/sessions-setup.html @@ -5,7 +5,7 @@ Sessions - Add a New + Add New diff --git a/src/app/setup/sessions/sessions.module.ts b/src/app/setup/sessions/sessions.module.ts index f6c885911..09fb8ad53 100644 --- a/src/app/setup/sessions/sessions.module.ts +++ b/src/app/setup/sessions/sessions.module.ts @@ -7,6 +7,7 @@ import { IonicModule } from '@ionic/angular'; import { SessionsSetup } from './sessions-setup'; import { PickSpeakersPage } from './pick-speakers/pick-speakers.page'; +import { PickTracksPage } from './pick-tracks/pick-tracks.page'; const routes: Routes = [ { @@ -22,7 +23,7 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [SessionsSetup, PickSpeakersPage], - entryComponents: [PickSpeakersPage] + declarations: [SessionsSetup, PickSpeakersPage, PickTracksPage], + entryComponents: [PickSpeakersPage, PickTracksPage] }) export class SessionsSetupModule {} diff --git a/src/app/setup/speakers/speakers-setup.html b/src/app/setup/speakers/speakers-setup.html index 90448aa43..3641bedd3 100644 --- a/src/app/setup/speakers/speakers-setup.html +++ b/src/app/setup/speakers/speakers-setup.html @@ -5,7 +5,7 @@ Speakers - Add a New + Add New diff --git a/src/app/setup/tracks/tracks-setup.html b/src/app/setup/tracks/tracks-setup.html index 42953f0a7..59d4b0e26 100644 --- a/src/app/setup/tracks/tracks-setup.html +++ b/src/app/setup/tracks/tracks-setup.html @@ -5,7 +5,7 @@ Tracks - Add a New + Add New From 54476ba1735a80d8e0216ce7694439f407f45081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 15:12:29 -0500 Subject: [PATCH 42/44] complited all of setup of the session: add, edit, remove. --- src/app/pages/schedule/schedule.ts | 4 ++-- src/app/setup/sessions/session-edit/session-edit.page.ts | 2 ++ src/app/setup/sessions/sessions-setup.ts | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index 16f362f22..e5c0c4f0f 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -24,8 +24,8 @@ export class SchedulePage implements OnInit { segment = ''; excludeTracks: any[] = []; - start = '2019-01-10'; - end = '2019-01-15'; + start = '2019-01-01'; + end = '2019-12-31'; changePeriod = true; partsOfDay: PartOfDay[]; diff --git a/src/app/setup/sessions/session-edit/session-edit.page.ts b/src/app/setup/sessions/session-edit/session-edit.page.ts index 383183908..3daaa1a6d 100644 --- a/src/app/setup/sessions/session-edit/session-edit.page.ts +++ b/src/app/setup/sessions/session-edit/session-edit.page.ts @@ -142,8 +142,10 @@ export class SessionEditPage implements OnInit { if (this.isValidAll()) { if (this.mode === 'New') { console.log('saved', this.session); + this.sessionProvider.addNewSession(this.session); } else { console.log('updated', this.session); + this.sessionProvider.updateSession(this.session); } this.onExit(); } diff --git a/src/app/setup/sessions/sessions-setup.ts b/src/app/setup/sessions/sessions-setup.ts index 242f1966c..1f648f480 100644 --- a/src/app/setup/sessions/sessions-setup.ts +++ b/src/app/setup/sessions/sessions-setup.ts @@ -15,7 +15,7 @@ import { Session } from '../../models'; export class SessionsSetup implements OnInit { startDate = '2000-01-01'; - endDate = '2019-01-31'; + endDate = '2100-12-31'; queryText = ''; sessions: Session[]; @@ -52,7 +52,7 @@ export class SessionsSetup implements OnInit { { text: 'Remove', handler: () => { - // this.sessionProvider.removeSession(session); + this.sessionProvider.removeSession(session); this.router.navigateByUrl('setup/tabs/(sessions:sessions)'); } } From 24418276a065927698c4f7d2e66a473a831bfecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Tue, 15 Jan 2019 16:28:18 -0500 Subject: [PATCH 43/44] Fixed bugs: missing parameter, declarations of 2 modules --- config.xml | 2 +- package.json | 14 ++++++++------ src/app/pages/schedule-filter/schedule-filter.html | 2 +- src/app/pages/schedule-track/schedule-track.html | 2 +- .../sessions/pick-speakers/pick-speakers.module.ts | 1 - .../sessions/pick-speakers/pick-speakers.page.html | 2 +- .../sessions/pick-tracks/pick-tracks.module.ts | 1 - .../sessions/pick-tracks/pick-tracks.page.html | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config.xml b/config.xml index 4d82fb364..2be19fd7f 100644 --- a/config.xml +++ b/config.xml @@ -84,5 +84,5 @@ - + diff --git a/package.json b/package.json index cce7076b4..bda635f49 100644 --- a/package.json +++ b/package.json @@ -34,15 +34,15 @@ "@ionic/angular": "^4.0.0-beta.16", "@ionic/storage": "^2.1.3", "angularfire2": "^5.1.1", - "cordova-android": "^7.0.0", + "cordova-android": "7.1.4", "cordova-ios": "^4.5.5", "cordova-plugin-device": "^2.0.2", "cordova-plugin-inappbrowser": "^3.0.0", - "cordova-plugin-ionic-keyboard": "^2.1.2", - "cordova-plugin-ionic-webview": "^2.0.0", + "cordova-plugin-ionic-keyboard": "^2.1.3", + "cordova-plugin-ionic-webview": "^2.3.1", "cordova-plugin-splashscreen": "^5.0.2", "cordova-plugin-statusbar": "^2.4.2", - "cordova-plugin-whitelist": "^1.3.2", + "cordova-plugin-whitelist": "^1.3.3", "core-js": "^2.5.7", "firebase": "^5.7.2", "rxjs": "6.3.3", @@ -88,9 +88,11 @@ "cordova-plugin-inappbrowser": {}, "cordova-plugin-splashscreen": {}, "cordova-plugin-whitelist": {}, - "cordova-plugin-ionic-webview": {}, + "cordova-plugin-ionic-webview": { + "ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+" + }, "cordova-plugin-statusbar": {}, "cordova-plugin-ionic-keyboard": {} } } -} +} \ No newline at end of file diff --git a/src/app/pages/schedule-filter/schedule-filter.html b/src/app/pages/schedule-filter/schedule-filter.html index 4bb361d3c..a306b6e94 100644 --- a/src/app/pages/schedule-filter/schedule-filter.html +++ b/src/app/pages/schedule-filter/schedule-filter.html @@ -1,7 +1,7 @@ - Cancel + Cancel diff --git a/src/app/pages/schedule-track/schedule-track.html b/src/app/pages/schedule-track/schedule-track.html index a499c53c6..d4b1570ed 100644 --- a/src/app/pages/schedule-track/schedule-track.html +++ b/src/app/pages/schedule-track/schedule-track.html @@ -5,7 +5,7 @@ - Cancel + Cancel diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts b/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts index af79c06dd..d2da49881 100644 --- a/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.module.ts @@ -21,6 +21,5 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [PickSpeakersPage] }) export class PickSpeakersPageModule {} diff --git a/src/app/setup/sessions/pick-speakers/pick-speakers.page.html b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html index c5018b63f..cc94c465a 100644 --- a/src/app/setup/sessions/pick-speakers/pick-speakers.page.html +++ b/src/app/setup/sessions/pick-speakers/pick-speakers.page.html @@ -3,7 +3,7 @@ Select Speakers - Cancel + Cancel Save diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts b/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts index e1a8aa36b..6f2983d1f 100644 --- a/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts +++ b/src/app/setup/sessions/pick-tracks/pick-tracks.module.ts @@ -21,6 +21,5 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [PickTracksPage] }) export class PickTracksPageModule {} diff --git a/src/app/setup/sessions/pick-tracks/pick-tracks.page.html b/src/app/setup/sessions/pick-tracks/pick-tracks.page.html index 28e9a243f..87a6029b8 100644 --- a/src/app/setup/sessions/pick-tracks/pick-tracks.page.html +++ b/src/app/setup/sessions/pick-tracks/pick-tracks.page.html @@ -3,7 +3,7 @@ Select Tracks - Cancel + Cancel Save From c9ae1b70fac391b2d662af0ad54df50e2585b26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CYoung?= <“hogusong1@gmail.com”> Date: Wed, 16 Jan 2019 12:28:16 -0500 Subject: [PATCH 44/44] added 'date-period mode' to 'schedule.ts and sessions-setup.ts --- src/app/app-routing.module.ts | 2 - .../pages/date-period/date-period.module.ts | 26 ++++++ .../pages/date-period/date-period.page.html | 34 ++++++++ .../pages/date-period/date-period.page.scss | 0 src/app/pages/date-period/date-period.page.ts | 57 +++++++++++++ src/app/pages/schedule/schedule.html | 9 +++ src/app/pages/schedule/schedule.module.ts | 7 +- src/app/pages/schedule/schedule.ts | 79 +++++++++++++------ src/app/providers/conference-data.ts | 10 +++ src/app/providers/function-data.ts | 14 ++++ src/app/setup/period/period.module.ts | 26 ++++++ src/app/setup/period/period.page.html | 31 ++++++++ src/app/setup/period/period.page.scss | 0 src/app/setup/period/period.page.ts | 57 +++++++++++++ src/app/setup/sessions/sessions-setup.html | 10 +++ src/app/setup/sessions/sessions-setup.ts | 44 +++++++++-- src/app/setup/sessions/sessions.module.ts | 14 +++- 17 files changed, 385 insertions(+), 35 deletions(-) create mode 100644 src/app/pages/date-period/date-period.module.ts create mode 100644 src/app/pages/date-period/date-period.page.html create mode 100644 src/app/pages/date-period/date-period.page.scss create mode 100644 src/app/pages/date-period/date-period.page.ts create mode 100644 src/app/setup/period/period.module.ts create mode 100644 src/app/setup/period/period.page.html create mode 100644 src/app/setup/period/period.page.scss create mode 100644 src/app/setup/period/period.page.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 10c0413f7..23fdf7927 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -36,8 +36,6 @@ const routes: Routes = [ loadChildren: './setup/tabs-setup/tabs-setup.module#TabsSetupPageModule' }, { path: 'session-edit', loadChildren: './setup/sessions/session-edit/session-edit.module#SessionEditPageModule' }, - // { path: 'pick-speakers', loadChildren: './setup/sessions/pick-speakers/pick-speakers.module#PickSpeakersPageModule' }, - // { path: 'pick-track', loadChildren: './setup/sessions/pick-track/pick-track.module#PickTrackPageModule' } ]; @NgModule({ diff --git a/src/app/pages/date-period/date-period.module.ts b/src/app/pages/date-period/date-period.module.ts new file mode 100644 index 000000000..8ab388201 --- /dev/null +++ b/src/app/pages/date-period/date-period.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { DatePeriodPage } from './date-period.page'; + +const routes: Routes = [ + { + path: '', + component: DatePeriodPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [DatePeriodPage] +}) +export class DatePeriodPageModule {} diff --git a/src/app/pages/date-period/date-period.page.html b/src/app/pages/date-period/date-period.page.html new file mode 100644 index 000000000..8f9d2db25 --- /dev/null +++ b/src/app/pages/date-period/date-period.page.html @@ -0,0 +1,34 @@ + + + + Date Period + + Cancel + Save Period + + + + + +
+ Enter new Period to make Schedule. +
+ + + From : + + + + To : + + + +
diff --git a/src/app/pages/date-period/date-period.page.scss b/src/app/pages/date-period/date-period.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/pages/date-period/date-period.page.ts b/src/app/pages/date-period/date-period.page.ts new file mode 100644 index 000000000..9c8b905b8 --- /dev/null +++ b/src/app/pages/date-period/date-period.page.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { NavParams, ModalController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; + +@Component({ + selector: 'date-period', + templateUrl: './date-period.page.html', + styleUrls: ['./date-period.page.scss'], +}) +export class DatePeriodPage implements OnInit { + + start: string; + end: string; + minYear: string; + maxYear: string; + + constructor(private navParams: NavParams, + private modalCtrl: ModalController, + private cdRef: ChangeDetectorRef, + private funProvider: FunctionlData) { } + + ngOnInit() { + this.start = this.navParams.get('start'); + this.end = this.navParams.get('end'); + this.minYear = '' + (+this.start.substring(0, 4) - 20); + this.maxYear = '' + (+this.end.substring(0, 4) + 20); + } + + checkStartDate(value) { + this.cdRef.detectChanges(); + if (this.funProvider.checkDateValidation(value)) { + this.end = (this.end < value) ? value : this.end; + } else { + this.funProvider.onError('Confirm Date', 'The date is not valid. Try again.'); + this.start = this.navParams.get('start'); + } + } + + checkEndDate(value) { + this.cdRef.detectChanges(); + if (!this.funProvider.checkDateValidation(value)) { + this.funProvider.onError('Confirm Date', 'The date is not valid. Try again.'); + this.end = this.start; + } else if (this.start > value) { + this.funProvider.onError('Confirm Date', 'The end of period is wrong. Try again.'); + this.end = this.start; + } + } + + applySelection() { + this.modalCtrl.dismiss({ start: this.start, end: this.end }); + } + + onExit() { + this.modalCtrl.dismiss(null); + } +} diff --git a/src/app/pages/schedule/schedule.html b/src/app/pages/schedule/schedule.html index a78a59da9..ec9ddc4ce 100644 --- a/src/app/pages/schedule/schedule.html +++ b/src/app/pages/schedule/schedule.html @@ -59,6 +59,15 @@

{{session.name}}

+ + Period + + {{ endDate }} + {{ startDate }} + New + + + diff --git a/src/app/pages/schedule/schedule.module.ts b/src/app/pages/schedule/schedule.module.ts index 90f545e15..c4f745bc9 100644 --- a/src/app/pages/schedule/schedule.module.ts +++ b/src/app/pages/schedule/schedule.module.ts @@ -7,6 +7,7 @@ import { SchedulePage } from './schedule'; import { ScheduleFilterPage } from '../schedule-filter/schedule-filter'; import { ScheduleTrackPage } from '../schedule-track/schedule-track'; import { SchedulePageRoutingModule } from './schedule-routing.module'; +import { DatePeriodPage } from '../date-period/date-period.page'; @NgModule({ imports: [ @@ -18,11 +19,13 @@ import { SchedulePageRoutingModule } from './schedule-routing.module'; declarations: [ SchedulePage, ScheduleFilterPage, - ScheduleTrackPage + ScheduleTrackPage, + DatePeriodPage ], entryComponents: [ ScheduleFilterPage, - ScheduleTrackPage + ScheduleTrackPage, + DatePeriodPage ] }) export class ScheduleModule { } diff --git a/src/app/pages/schedule/schedule.ts b/src/app/pages/schedule/schedule.ts index e5c0c4f0f..4caf0c2d6 100644 --- a/src/app/pages/schedule/schedule.ts +++ b/src/app/pages/schedule/schedule.ts @@ -8,6 +8,8 @@ import { ConferenceData } from '../../providers/conference-data'; import { UserData } from '../../providers/user-data'; import { User, Session, PartOfDay } from '../../models'; import { SessionData } from '../../providers/session-data'; +import { FunctionlData } from '../../providers/function-data'; +import { DatePeriodPage } from '../date-period/date-period.page'; @Component({ selector: 'page-schedule', @@ -24,8 +26,8 @@ export class SchedulePage implements OnInit { segment = ''; excludeTracks: any[] = []; - start = '2019-01-01'; - end = '2019-12-31'; + startDate: string; + endDate: string; changePeriod = true; partsOfDay: PartOfDay[]; @@ -47,41 +49,70 @@ export class SchedulePage implements OnInit { public modalCtrl: ModalController, public router: Router, public toastCtrl: ToastController, - public userProvider: UserData + public userProvider: UserData, + private funProvider: FunctionlData ) { } ngOnInit() { - // this.app.setTitle('Schedule'); this.userProvider.isLoggedIn().then(loggedIn => { if (loggedIn) { - this.userProvider.getUser().then(user => { - user.trackFilter.forEach(track => { - if (!track.isChecked) { this.excludeTracks.push(track.name); } - }); - this.user = user; - this.dataProvider.getPartsOfDay().subscribe( - response => { this.partsOfDay = response ; } - ); - this.updateSchedule(); + this.dataProvider.getPeriod().then(period => { + if (period) { + this.startDate = period.start; + this.endDate = period.end; + this.updateSchedule(); + } else { + this.getDatePeriod(); + } }); } }); } - updateSchedule() { - // Close any open sliding items when the schedule updates - if (this.scheduleList) { - this.scheduleList.closeSlidingItems(); + async getDatePeriod() { + const start = this.startDate ? this.startDate : this.funProvider.getDateFormat(); + const end = this.endDate ? this.endDate : start ; + const modal = await this.modalCtrl.create({ + component: DatePeriodPage, + componentProps: { start, end } + }); + await modal.present(); + + const { data } = await modal.onWillDismiss(); + if (data) { + this.startDate = data.start; + this.endDate = data.end; + this.schedule = []; + this.changePeriod = true; + this.dataProvider.setPeriod({ start: this.startDate, end: this.endDate }); + this.updateSchedule(); } + } - if (this.schedule.length === 0 || this.changePeriod) { - this.changePeriod = false; - this.sessionProvider.getSessionsInPeriod(this.start, this.end).subscribe( - (response: Session[]) => { - this.sessions = response; - this.buildSchedule(); + updateSchedule() { + this.userProvider.getUser().then(user => { + user.trackFilter.forEach(track => { + if (!track.isChecked) { this.excludeTracks.push(track.name); } }); - } + this.user = user; + this.dataProvider.getPartsOfDay().subscribe( + response => { this.partsOfDay = response ; } + ); + + // Close any open sliding items when the schedule updates + if (this.scheduleList) { + this.scheduleList.closeSlidingItems(); + } + + if (this.schedule.length === 0 || this.changePeriod) { + this.changePeriod = false; + this.sessionProvider.getSessionsInPeriod(this.startDate, this.endDate).subscribe( + (response: Session[]) => { + this.sessions = response; + this.buildSchedule(); + }); + } + }); } getFilterOption() { diff --git a/src/app/providers/conference-data.ts b/src/app/providers/conference-data.ts index 1f5293b2f..e366ae67a 100644 --- a/src/app/providers/conference-data.ts +++ b/src/app/providers/conference-data.ts @@ -8,6 +8,7 @@ import { map } from 'rxjs/operators'; import { UserData } from './user-data'; import { Track, Session, PartOfDay, Map } from '../models'; import { SessionData } from './session-data'; +import { Storage } from '@ionic/storage'; @Injectable({ providedIn: 'root' @@ -33,6 +34,7 @@ export class ConferenceData { constructor( public http: HttpClient, + public storage: Storage, public userProvider: UserData, public sessionProvider: SessionData, private afs: AngularFirestore) { @@ -166,6 +168,14 @@ export class ConferenceData { }); } + getPeriod(): Promise { + return this.storage.get('period'); + } + + setPeriod(date: any): Promise { + return this.storage.set('period', date); + } + getMap() { this.maps = this.mapsCollection.snapshotChanges() .pipe(map(response => { diff --git a/src/app/providers/function-data.ts b/src/app/providers/function-data.ts index f11850b39..e07459138 100644 --- a/src/app/providers/function-data.ts +++ b/src/app/providers/function-data.ts @@ -78,4 +78,18 @@ export class FunctionlData { const min = this.reform2digits((m === '59') ? 0 : +m + 1); return (hour === '24') ? null : hour + ':' + min ; } + + checkDateValidation(s_date: string): boolean { + const months = [1, 3, 5, 7, 8, 10, 12]; + const arr = s_date.split('-'); + const year = +arr[0]; + const month = +arr[1]; + const date = +arr[2]; + if (months.find(num => num === month)) { return date < 32; } + if (month > 2) { return date < 31; } + if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) { + return date < 30; + } + return date < 29; + } } diff --git a/src/app/setup/period/period.module.ts b/src/app/setup/period/period.module.ts new file mode 100644 index 000000000..754aec4db --- /dev/null +++ b/src/app/setup/period/period.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { Routes, RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { PeriodPage } from './period.page'; + +const routes: Routes = [ + { + path: '', + component: PeriodPage + } +]; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + RouterModule.forChild(routes) + ], + declarations: [PeriodPage] +}) +export class PeriodPageModule {} diff --git a/src/app/setup/period/period.page.html b/src/app/setup/period/period.page.html new file mode 100644 index 000000000..bea46c525 --- /dev/null +++ b/src/app/setup/period/period.page.html @@ -0,0 +1,31 @@ + + + Date Period + + Cancel + Save Period + + + + + +
+ Enter new Period to make Schedule. +
+ + + From : + + + + To : + + + +
diff --git a/src/app/setup/period/period.page.scss b/src/app/setup/period/period.page.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/setup/period/period.page.ts b/src/app/setup/period/period.page.ts new file mode 100644 index 000000000..e9201b65e --- /dev/null +++ b/src/app/setup/period/period.page.ts @@ -0,0 +1,57 @@ +import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; +import { NavParams, ModalController } from '@ionic/angular'; +import { FunctionlData } from '../../providers/function-data'; + +@Component({ + selector: 'period', + templateUrl: './period.page.html', + styleUrls: ['./period.page.scss'], +}) +export class PeriodPage implements OnInit { + + start: string; + end: string; + minYear: string; + maxYear: string; + + constructor(private navParams: NavParams, + private modalCtrl: ModalController, + private cdRef: ChangeDetectorRef, + private funProvider: FunctionlData) { } + + ngOnInit() { + this.start = this.navParams.get('start'); + this.end = this.navParams.get('end'); + this.minYear = '' + (+this.start.substring(0, 4) - 20); + this.maxYear = '' + (+this.end.substring(0, 4) + 20); + } + + checkStartDate(value) { + this.cdRef.detectChanges(); + if (this.funProvider.checkDateValidation(value)) { + this.end = (this.end < value) ? value : this.end; + } else { + this.funProvider.onError('Confirm Date', 'The date is not valid. Try again.'); + this.start = this.navParams.get('start'); + } + } + + checkEndDate(value) { + this.cdRef.detectChanges(); + if (!this.funProvider.checkDateValidation(value)) { + this.funProvider.onError('Confirm Date', 'The date is not valid. Try again.'); + this.end = this.start; + } else if (this.start > value) { + this.funProvider.onError('Confirm Date', 'The end of period is wrong. Try again.'); + this.end = this.start; + } + } + + applySelection() { + this.modalCtrl.dismiss({ start: this.start, end: this.end }); + } + + onExit() { + this.modalCtrl.dismiss(null); + } +} diff --git a/src/app/setup/sessions/sessions-setup.html b/src/app/setup/sessions/sessions-setup.html index 9c31f7b2d..7921311b0 100644 --- a/src/app/setup/sessions/sessions-setup.html +++ b/src/app/setup/sessions/sessions-setup.html @@ -23,4 +23,14 @@ + + + Period + + {{ endDate }} + {{ startDate }} + New + + +
diff --git a/src/app/setup/sessions/sessions-setup.ts b/src/app/setup/sessions/sessions-setup.ts index 1f648f480..22a19079a 100644 --- a/src/app/setup/sessions/sessions-setup.ts +++ b/src/app/setup/sessions/sessions-setup.ts @@ -1,11 +1,14 @@ import { Component, OnInit } from '@angular/core'; -import { AlertController } from '@ionic/angular'; +import { AlertController, ModalController } from '@ionic/angular'; import { Router } from '@angular/router'; import { UserData } from '../../providers/user-data'; import { SessionData } from '../../providers/session-data'; import { Session } from '../../models'; +import { ConferenceData } from '../../providers/conference-data'; +import { FunctionlData } from '../../providers/function-data'; +import { PeriodPage } from '../../setup/period/period.page'; @Component({ selector: 'sessions', @@ -21,7 +24,10 @@ export class SessionsSetup implements OnInit { constructor(private userProvider: UserData, private sessionProvider: SessionData, + private dataProvider: ConferenceData, + private funProvider: FunctionlData, private alertCtrl: AlertController, + private modalCtrl: ModalController, private router: Router) { } ngOnInit() { @@ -29,14 +35,42 @@ export class SessionsSetup implements OnInit { if ( !user || user.username !== 'admin') { this.router.navigateByUrl('/tutorial'); } else { - this.sessionProvider.getSessionsInPeriod(this.startDate, this.endDate) - .subscribe(data => { - this.sessions = data; - }); + this.dataProvider.getPeriod().then(period => { + if (period) { + this.startDate = period.start; + this.endDate = period.end; + this.getSessions(); + } else { + this.getDatePeriod(); + } + }); } }); } + getSessions() { + this.sessionProvider.getSessionsInPeriod(this.startDate, this.endDate) + .subscribe(data => { this.sessions = data; }); + } + + async getDatePeriod() { + const start = this.startDate ? this.startDate : this.funProvider.getDateFormat(); + const end = this.endDate ? this.endDate : start ; + const modal = await this.modalCtrl.create({ + component: PeriodPage, + componentProps: { start, end } + }); + await modal.present(); + + const { data } = await modal.onWillDismiss(); + if (data) { + this.startDate = data.start; + this.endDate = data.end; + this.dataProvider.setPeriod({ start: this.startDate, end: this.endDate }); + this.getSessions(); + } + } + async onConfirmToRemove(session: Session) { const alert = await this.alertCtrl.create({ header: 'Confirm Remove', diff --git a/src/app/setup/sessions/sessions.module.ts b/src/app/setup/sessions/sessions.module.ts index 09fb8ad53..1d3fcdeeb 100644 --- a/src/app/setup/sessions/sessions.module.ts +++ b/src/app/setup/sessions/sessions.module.ts @@ -8,6 +8,7 @@ import { IonicModule } from '@ionic/angular'; import { SessionsSetup } from './sessions-setup'; import { PickSpeakersPage } from './pick-speakers/pick-speakers.page'; import { PickTracksPage } from './pick-tracks/pick-tracks.page'; +import { PeriodPage } from '../../setup/period/period.page'; const routes: Routes = [ { @@ -23,7 +24,16 @@ const routes: Routes = [ IonicModule, RouterModule.forChild(routes) ], - declarations: [SessionsSetup, PickSpeakersPage, PickTracksPage], - entryComponents: [PickSpeakersPage, PickTracksPage] + declarations: [ + SessionsSetup, + PickSpeakersPage, + PickTracksPage, + PeriodPage + ], + entryComponents: [ + PickSpeakersPage, + PickTracksPage, + PeriodPage + ] }) export class SessionsSetupModule {}