diff --git a/angular.json b/angular.json index bd7d5cee1..c606df973 100644 --- a/angular.json +++ b/angular.json @@ -46,7 +46,8 @@ "glob": "**/*", "input": "./node_modules/@igo2/geo/assets/", "output": "./assets/igo2/geo/" - } + }, + "src/manifest.webmanifest" ], "styles": ["src/styles.scss"], "scripts": [], @@ -124,7 +125,8 @@ "aot": true, "extractLicenses": true, "vendorChunk": true, - "buildOptimizer": false + "buildOptimizer": false, + "serviceWorker": false }, "developpement": { "buildOptimizer": false, @@ -154,7 +156,32 @@ "aot": true, "extractLicenses": true, "vendorChunk": true, - "buildOptimizer": false + "buildOptimizer": false, + "serviceWorker": false + }, + "pwa": { + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "12kb" + } + ], + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.pwa.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": true, + "buildOptimizer": false, + "serviceWorker": true, + "ngswConfigPath": "ngsw-config.json" } } }, @@ -191,14 +218,18 @@ "karmaConfig": "src/karma.conf.js", "styles": ["src/styles.scss"], "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets", + "src/manifest.webmanifest" + ], "stylePreprocessorOptions": { "includePaths": [ "src/style/partial", "src/app/pages/portal", "node_modules" ] - }, - "assets": ["src/favicon.ico", "src/assets"] + } } }, "lint": { diff --git a/gulpfile.js b/gulpfile.js index bddd82866..1cc0f4e92 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,7 @@ /*jshint esversion: 6 */ -var gulp = require('gulp'); +const gulp = require('gulp'); +const bump = require('gulp-bump'); +const package = require('./package.json') gulp.task('copyLocaleFromLib', done => { gulp @@ -13,5 +15,9 @@ gulp.task('watch:locale', function () { gulp.watch('./node_modules/@igo2/core/locale/*.json', gulp.series('copyLocaleFromLib')); }); - - +gulp.task('bumpPwaVersionDev', done => { + gulp.src(['./ngsw-config.json']) + .pipe(bump({ type: 'prerelease' })) + .pipe(gulp.dest('./')); + done(); +}); diff --git a/ngsw-config.json b/ngsw-config.json new file mode 100644 index 000000000..b293a963e --- /dev/null +++ b/ngsw-config.json @@ -0,0 +1,56 @@ +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "appData": { + "changelog": "Initial version", + "version": "1.13.4" + }, + "assetGroups": [ + { + "name": "data", + "installMode": "prefetch", + "updateMode": "prefetch", + "resources": { + "files": [ + "/data/**" + ] + } + }, + { + "name": "contexts", + "installMode": "prefetch", + "updateMode": "prefetch", + "resources": { + "files": [ + "/contexts/**" + ] + } + }, + { + "name": "app", + "installMode": "prefetch", + "updateMode": "prefetch", + "resources": { + "files": [ + "/favicon.ico", + "/index.html", + "/manifest.webmanifest", + "/*.css", + "/*.js", + "/locale/**", + "/config/**" + ] + } + }, { + "name": "assets", + "installMode": "prefetch", + "updateMode": "prefetch", + "resources": { + "files": [ + "/assets/**", + "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)" + ] + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index d1dd42d37..9eab16097 100644 --- a/package-lock.json +++ b/package-lock.json @@ -833,6 +833,14 @@ "tslib": "^2.3.0" } }, + "@angular/service-worker": { + "version": "14.2.7", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-14.2.7.tgz", + "integrity": "sha512-QS6iK14QVUi/5enXoPpfXn9Rm4wbub+7QWTUeVk+ADSdq9+sOCMtfw3WUFaJkNVgTbPm1fTExrZlVo1ehwtCQw==", + "requires": { + "tslib": "^2.3.0" + } + }, "@assemblyscript/loader": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", @@ -4891,6 +4899,12 @@ "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -5669,6 +5683,23 @@ "semver": "^7.0.0" } }, + "bump-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bump-regex/-/bump-regex-4.1.0.tgz", + "integrity": "sha512-75Kr/Iw6lqnOKF/7YpE0WyOMBaaSpdrXTquIxR0qbTgZxwJos6563zNSn+w/LPJUoL4DXq20QX9AQy4+UJbyhw==", + "dev": true, + "requires": { + "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -6873,6 +6904,23 @@ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, + "postcss": { + "version": "8.3.11", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.11.tgz", + "integrity": "sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==", + "dev": true, + "requires": { + "nanoid": "^3.1.30", + "picocolors": "^1.0.0", + "source-map-js": "^0.6.2" + } + }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6912,17 +6960,6 @@ "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", "dev": true }, - "css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - } - }, "css-blank-pseudo": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", @@ -6982,6 +7019,19 @@ "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" + }, + "dependencies": { + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + } } }, "css-what": { @@ -7013,10 +7063,19 @@ "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", "dev": true }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", "dev": true }, "d": { @@ -7304,7 +7363,7 @@ "di": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", "dev": true }, "diff": { @@ -7349,7 +7408,7 @@ "dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { "custom-event": "~1.0.0", @@ -7367,6 +7426,14 @@ "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + } } }, "domelementtype": { @@ -7382,6 +7449,14 @@ "dev": true, "requires": { "domelementtype": "^2.2.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + } } }, "dommatrix": { @@ -7396,17 +7471,6 @@ "integrity": "sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==", "optional": true }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, "dot": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", @@ -7699,7 +7763,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, "entities": { @@ -8421,9 +8485,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -8455,7 +8519,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", "dev": true }, "event-emitter": { @@ -8972,7 +9036,7 @@ "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", "dev": true }, "filenamify": { @@ -9284,7 +9348,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "dev": true }, "from": { @@ -9509,6 +9573,12 @@ } } }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "dev": true + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -9542,7 +9612,7 @@ "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { "array-uniq": "^1.0.1" @@ -9562,7 +9632,7 @@ "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { "array-union": "^1.0.1", @@ -9575,7 +9645,7 @@ "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -9584,7 +9654,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "universalify": { @@ -10375,6 +10445,27 @@ "vinyl-sourcemaps-apply": "^0.2.0" } }, + "gulp-bump": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/gulp-bump/-/gulp-bump-3.2.0.tgz", + "integrity": "sha512-j3Yvi0QQZEN1HsXArQCBMdX5jedQZ1Cul3W1VZrvKal/Z4Slb6Z7UQLQyPaLm0heNdJKCjpKHgkYSR8VhfPlTA==", + "dev": true, + "requires": { + "bump-regex": "^4.1.0", + "plugin-error": "^1.0.1", + "plugin-log": "^0.1.0", + "semver": "^5.3.0", + "through2": "^2.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "gulp-concat": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", @@ -11332,6 +11423,12 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -11974,9 +12071,9 @@ } }, "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, "requires": { "readable-stream": "^2.0.5" @@ -12273,6 +12370,16 @@ "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", "dev": true }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -12718,7 +12825,7 @@ "mgrs": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz", - "integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA==" + "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk=" }, "micromatch": { "version": "4.0.4", @@ -13055,7 +13162,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "needle": { @@ -18117,7 +18224,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-copy": { @@ -18841,6 +18948,254 @@ } } }, + "plugin-log": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/plugin-log/-/plugin-log-0.1.0.tgz", + "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "dateformat": "^1.0.11" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + } + } + }, "png-js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", @@ -20099,6 +20454,15 @@ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, "replace-ext": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", @@ -20327,6 +20691,18 @@ "requires": { "@rollup/pluginutils": "^3.0.9", "source-map-resolve": "^0.6.0" + }, + "dependencies": { + "source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + } } }, "run-async": { @@ -20880,19 +21256,6 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } } } }, @@ -21103,13 +21466,16 @@ } }, "source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-support": { @@ -21510,11 +21876,40 @@ "source-map": "^0.7.3" }, "dependencies": { + "css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true + }, + "source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } } } }, @@ -21755,7 +22150,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "textextensions": { @@ -21920,7 +22315,7 @@ "trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", "dev": true, "requires": { "escape-string-regexp": "^1.0.2" @@ -22542,7 +22937,7 @@ "void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, "watchpack": { diff --git a/package.json b/package.json index 523bd21fd..d7f34b1e4 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,17 @@ "scripts": { "ng": "ng", "start": "gulp watch:locale | ng serve --host 0.0.0.0 --port 4201 --proxy-config proxy.conf.json", + "start-pwa": "gulp bumpPwaVersionDev && ng build --configuration pwa --output-path ./dist/pwa && npm run serve.pwa", "build": "ng build", "lint": "ng lint", "lint.fix": "ng lint --fix", "e2e": "ng e2e --port 4300", "postinstall": "ngcc --tsconfig src/tsconfig.app.json && gulp copyLocaleFromLib", "build.prod": "ng build --configuration production", - "serve.prod": "http-server ./dist/igo2/ --port=4200 --no-browser", + "build.github": "npm build --configuration=github --output-path ./dist/ghpages --base-href /igo2/", + "build.pwa": "ng build --configuration pwa --output-path ./dist/pwa", + "serve.prod": "http-server ./dist/igo2/ --port 4201 --no-browser", + "serve.pwa": "http-server ./dist/pwa/ --port 4201 --no-browser", "doc": "compodoc -p src/tsconfig.app.json -s --port 4220", "build.doc": "compodoc -p src/tsconfig.app.json", "serve.doc": "compodoc -s --port 4220", @@ -31,16 +35,16 @@ "clean": "rimraf ./dist && rimraf ./node_modules && npm cache clean --force && git checkout -- package.json && git checkout -- package-lock.json", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", "changelog-current": "conventional-changelog -p angular -r 2", - "preversion.linux": "npm run test.all && rimraf ./dist && npm run build.prod", + "preversion.linux": "npm run pwaBumpVersion.prod && npm run test.all && rimraf ./dist && npm run build.prod", "version.linux": "npm run changelog && git add -A CHANGELOG.md", "postversion.linux": "git push && git push --tags && npm run ghpages", - "preversion": "npm run test.all && rimraf ./dist && npm run build.prod", + "preversion": "npm run pwaBumpVersion.prod && npm run test.all && rimraf ./dist && npm run build.prod", "version": "npm run changelog && git add -A CHANGELOG.md", "postversion": "git push && git push --tags && npm run ghpages.win", - "preghpages": "npm run build -- --configuration=github --output-path ./dist/ghpages --base-href /igo2/ && echo \"include: ['_default.json', '_contexts.json', '_base.json']\" > dist/ghpages/_config.yml", + "preghpages": "npm run build.github && echo \"include: ['_default.json', '_contexts.json', '_base.json']\" > dist/ghpages/_config.yml", "ghpages": "VERSION=$(node -p -e \"require('./package.json').version\") && npx ngh --dir=dist/ghpages --no-silent=false --message=$VERSION", "postghpages": "rimraf ./dist/ghpages", - "preghpages.win": "npm run build -- --configuration=github --output-path ./dist/ghpages --base-href /igo2/ && echo include: ['_default.json', '_contexts.json', '_base.json'] > dist/ghpages/_config.yml", + "preghpages.win": "npm run build.github && echo include: ['_default.json', '_contexts.json', '_base.json'] > dist/ghpages/_config.yml", "ghpages.win": "npx ngh --dir=dist/ghpages --no-silent=false --message=%npm_package_version%" }, "private": true, @@ -55,6 +59,7 @@ "@angular/platform-browser": "^14.1.2", "@angular/platform-browser-dynamic": "^14.1.2", "@angular/router": "^14.1.2", + "@angular/service-worker": "^14.1.2", "@azure/msal-angular": "^2.4.1", "@azure/msal-browser": "^2.28.1", "@igo2/auth": "1.13.4", @@ -123,6 +128,7 @@ "gulp-concat": "^2.6.1", "gulp-replace": "^1.1.3", "http-server": "^13.1.0", + "gulp-bump": "^3.2.0", "jasmine-core": "~3.8.0", "jasmine-spec-reporter": "~5.0.0", "karma": "^6.4.0", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index cc353eef4..b7e4335aa 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -10,6 +10,7 @@ import { } from '@igo2/core'; import { AuthOptions } from '@igo2/auth'; import { AnalyticsListenerService } from '@igo2/integration'; +import { PwaService } from './services/pwa.service'; @Component({ selector: 'app-root', @@ -29,9 +30,11 @@ export class AppComponent { private renderer: Renderer2, private titleService: Title, private metaService: Meta, - private messageService: MessageService + private messageService: MessageService, + private pwaService: PwaService ) { - this.languageService.translate.getTranslation(this.languageService.getLanguage()).subscribe(); + this.pwaService.checkForUpdates(); + this.languageService.translate.getTranslation(this.languageService.getLanguage()).subscribe(); this.authConfig = this.configService.getConfig('auth'); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d2f108efe..5197fbe31 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,13 +1,16 @@ import { BrowserModule, HammerModule } from '@angular/platform-browser'; -import { NgModule } from '@angular/core'; +import { APP_INITIALIZER, InjectionToken, NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; - import { provideConfigOptions, IgoMessageModule, IgoGestureModule, - RouteService + RouteService, + LanguageService, + ConfigService, + ConfigOptions, + CONFIG_OPTIONS } from '@igo2/core'; import { IgoSpinnerModule, IgoStopPropagationModule } from '@igo2/common'; import { IgoAuthModule } from '@igo2/auth'; @@ -24,11 +27,27 @@ import { provideStyleListOptions } from '@igo2/geo'; +import { PwaService } from './services/pwa.service'; + import { environment } from '../environments/environment'; import { PortalModule } from './pages'; import { AppComponent } from './app.component'; import { HeaderModule } from './pages/header/header.module'; import { FooterModule } from './pages/footer/footer.module'; +import { ServiceWorkerModule } from '@angular/service-worker'; + +export let CONFIG_LOADER = new InjectionToken>('Config Loader'); + +function configLoader( + configService: ConfigService, + configOptions: ConfigOptions, +): Promise { + const promiseOrTrue = configService.load(configOptions); + if (promiseOrTrue instanceof Promise) { + return promiseOrTrue; + } + return Promise.resolve(); +} import { MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipDefaultOptions } from '@angular/material/tooltip'; export const defaultTooltipOptions: MatTooltipDefaultOptions = { @@ -52,13 +71,19 @@ export const defaultTooltipOptions: MatTooltipDefaultOptions = { PortalModule, HammerModule, HeaderModule, - FooterModule + FooterModule, + ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production, registrationStrategy: 'registerWithDelay:5000' }) ], providers: [ provideConfigOptions({ default: environment.igo, path: './config/config.json' }), + { + provide: CONFIG_LOADER, + useFactory: configLoader, + deps: [ConfigService, CONFIG_OPTIONS], + }, RouteService, provideNominatimSearchSource(), provideIChercheSearchSource(), @@ -69,6 +94,13 @@ export const defaultTooltipOptions: MatTooltipDefaultOptions = { provideOsrmDirectionsSource(), provideOptionsApi(), provideCadastreSearchSource(), + + { + provide: APP_INITIALIZER, + useFactory: appInitializerFactory, + deps: [CONFIG_LOADER, LanguageService, PwaService], + multi: true + }, provideStyleListOptions({ path: './assets/list-style.json' }), @@ -77,3 +109,19 @@ export const defaultTooltipOptions: MatTooltipDefaultOptions = { bootstrap: [AppComponent] }) export class AppModule {} + +function appInitializerFactory( + configLoader: Promise, + languageService: LanguageService, + pwaService: PwaService +) { + return () => new Promise((resolve: any) => { + configLoader.then(() => { + const secondPromises = [languageService.translate.getTranslation(languageService.getLanguage())]; + Promise.all(secondPromises).then(() => { + const thirdPromises = [pwaService.initPwaPrompt()]; + Promise.all(thirdPromises).then(() => resolve()); + }); + }); + }); +} diff --git a/src/app/pages/portal/portal.component.html b/src/app/pages/portal/portal.component.html index acb98906f..aabdc74f0 100644 --- a/src/app/pages/portal/portal.component.html +++ b/src/app/pages/portal/portal.component.html @@ -36,6 +36,7 @@ { + console.log('Service Worker Ready'); + this.http.get('ngsw.json').pipe( + concatMap((ngsw: any) => { + const datas$ = []; + let hasDataInDataDir: boolean = false; + if (ngsw) { + // IF FILE NOT IN THIS LIST... DELETE? + currentVersion = ngsw.appData.version; + const cachedDataVersion = this.storageService.get('cachedDataVersion'); + if (currentVersion !== cachedDataVersion && dataLoadSource === 'pending') { + this.pwaService.updates.checkForUpdate(); + } + if (dataLoadSource === 'newVersion' || !dataLoadSource) { + ((ngsw as any).assetGroups as any).map((assetGroup) => { + if (assetGroup.name === 'contexts') { + const elemToDownload = assetGroup.urls.concat(assetGroup.files).filter(f => f); + elemToDownload.map((url, i) => datas$.push(this.http.get(url).pipe(delay(750)))); + } + }); + if (hasDataInDataDir) { + const message = this.languageService.translate.instant('pwa.data-download-start'); + downloadMessage = this.messageService + .info(message, undefined, { disableTimeOut: true, progressBar: false, closeButton: true, tapToDismiss: false }); + this.storageService.set('cachedDataVersion', currentVersion); + } + return zip(...datas$); + } + + } + return zip(...datas$); + }) + ) + .pipe(delay(1000)) + .subscribe(() => { + if (downloadMessage) { + this.messageService.remove((downloadMessage as any).toastId); + const message = this.languageService.translate.instant('pwa.data-download-completed'); + this.messageService.success(message, undefined, { timeOut: 40000 }); + if (currentVersion) { + this.storageService.set('dataLoadSource', 'pending'); + this.storageService.set('cachedDataVersion', currentVersion); + } + } + }); + + }); + } } setToastPanelHtmlDisplay(value) { diff --git a/src/app/services/pwa.service.ts b/src/app/services/pwa.service.ts new file mode 100644 index 000000000..db795e7fa --- /dev/null +++ b/src/app/services/pwa.service.ts @@ -0,0 +1,77 @@ +import { Injectable } from '@angular/core'; +import { Platform } from '@angular/cdk/platform'; +import { ConfigService, LanguageService } from '@igo2/core'; +import { SwUpdate, VersionDetectedEvent } from '@angular/service-worker'; +import { interval } from 'rxjs'; +import { ConfirmDialogService } from '@igo2/common'; +import { filter } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) +export class PwaService { + promptEvent: any; + constructor( + private platform: Platform, + public updates: SwUpdate, + public languageService: LanguageService, + private configService: ConfigService, + private confirmDialogService: ConfirmDialogService + ) { + if (updates.isEnabled) { + interval(60 * 1000 * 2).subscribe(() => updates.checkForUpdate()); + } + } + + private modalUpdatePWA() { + const title = this.languageService.translate.instant('pwa.new-version-title'); + const body = this.languageService.translate.instant('pwa.new-version'); + const message = `${title} ${body}`; + this.confirmDialogService.open(message).subscribe((confirm) => { + if (confirm) { + this.updates.activateUpdate().then(() => { + if (window.navigator.onLine) { + document.location.reload(); + } else { + alert(`Hors-ligne / Offline. Vous devez être en ligne pour mettre à jour l\'application. You must be online to update the application.`); + setTimeout(() => { + this.modalUpdatePWA(); + }, 900000); + } + }); + } + }); + } + + public checkForUpdates(): void { + if (this.updates.isEnabled) { + this.updates.versionUpdates.pipe( + filter((evt): evt is VersionDetectedEvent => evt.type === 'VERSION_DETECTED')) + .subscribe(() => { + this.modalUpdatePWA(); + }); + } + } + + public async initPwaPrompt(): Promise { + if (this.configService.getConfig('app') && this.configService.getConfig('app.promotePwa')) { + if (!this.platform.IOS) { + window.addEventListener('beforeinstallprompt', (event: any) => { + event.preventDefault(); + this.promptEvent = event; + this.listenToUserAction(); + }, { once: true }); + } + } + } + + private listenToUserAction() { + window.addEventListener('click', () => { this.showPrompt(); }, { once: true }); + } + + private async showPrompt() { + this.promptEvent.prompt(); + const outcome = await this.promptEvent.userChoice; + this.promptEvent = undefined; + } +} diff --git a/src/assets/icons/icon-128x128.png b/src/assets/icons/icon-128x128.png new file mode 100644 index 000000000..4160237d0 Binary files /dev/null and b/src/assets/icons/icon-128x128.png differ diff --git a/src/assets/icons/icon-144x144.png b/src/assets/icons/icon-144x144.png new file mode 100644 index 000000000..d2fd53f50 Binary files /dev/null and b/src/assets/icons/icon-144x144.png differ diff --git a/src/assets/icons/icon-152x152.png b/src/assets/icons/icon-152x152.png new file mode 100644 index 000000000..80242eba7 Binary files /dev/null and b/src/assets/icons/icon-152x152.png differ diff --git a/src/assets/icons/icon-192x192-full.png b/src/assets/icons/icon-192x192-full.png new file mode 100644 index 000000000..044bdea63 Binary files /dev/null and b/src/assets/icons/icon-192x192-full.png differ diff --git a/src/assets/icons/icon-192x192.png b/src/assets/icons/icon-192x192.png new file mode 100644 index 000000000..044bdea63 Binary files /dev/null and b/src/assets/icons/icon-192x192.png differ diff --git a/src/assets/icons/icon-384x384.png b/src/assets/icons/icon-384x384.png new file mode 100644 index 000000000..eb52da354 Binary files /dev/null and b/src/assets/icons/icon-384x384.png differ diff --git a/src/assets/icons/icon-512x512.png b/src/assets/icons/icon-512x512.png new file mode 100644 index 000000000..c16470795 Binary files /dev/null and b/src/assets/icons/icon-512x512.png differ diff --git a/src/assets/icons/icon-72x72.png b/src/assets/icons/icon-72x72.png new file mode 100644 index 000000000..0e1af7248 Binary files /dev/null and b/src/assets/icons/icon-72x72.png differ diff --git a/src/assets/icons/icon-96x96.png b/src/assets/icons/icon-96x96.png new file mode 100644 index 000000000..4f2fcb6b7 Binary files /dev/null and b/src/assets/icons/icon-96x96.png differ diff --git a/src/assets/icons/icon.svg b/src/assets/icons/icon.svg new file mode 100644 index 000000000..fd3046fb1 --- /dev/null +++ b/src/assets/icons/icon.svg @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IGO + + diff --git a/src/environments/environment.github.ts b/src/environments/environment.github.ts index 325ad4dfa..47b5d59ed 100644 --- a/src/environments/environment.github.ts +++ b/src/environments/environment.github.ts @@ -12,6 +12,7 @@ interface Environment { igo: { app: { forceCoordsNA: boolean; + promotePwa?: boolean; }; catalog?: CatalogServiceOptions; importExport?: ImportExportServiceOptions; diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 049a5fb3d..5c50b4671 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -8,7 +8,7 @@ import { CommonVectorStyleOptions } from '@igo2/geo'; -interface Environment { +export interface Environment { production: boolean; igo: { app: { diff --git a/src/environments/environment.pwa.ts b/src/environments/environment.pwa.ts new file mode 100644 index 000000000..237722c96 --- /dev/null +++ b/src/environments/environment.pwa.ts @@ -0,0 +1,4 @@ +import { environment as prodEnv } from './environment.github'; + +prodEnv.igo.app.promotePwa = true; +export const environment = prodEnv; diff --git a/src/environments/index.ts b/src/environments/index.ts new file mode 100644 index 000000000..46cbbfee4 --- /dev/null +++ b/src/environments/index.ts @@ -0,0 +1 @@ +export * from './environment.prod'; diff --git a/src/index.html b/src/index.html index 845a382e1..956cb8ffe 100644 --- a/src/index.html +++ b/src/index.html @@ -64,7 +64,10 @@ } - + + + +
@@ -74,5 +77,6 @@
- + + diff --git a/src/locale/en.json b/src/locale/en.json index 6dfacf623..b84eb1be4 100644 --- a/src/locale/en.json +++ b/src/locale/en.json @@ -243,6 +243,13 @@ "legend-tab-description": "This tab can be used to display all layer's legend. By default, only visible layers at active scale will have their legend displayed.", "legend-tab-all": "Allow to also display non visible layer's legend at active scale." }, + "pwa": { + "new-version-title": "New version available. ", + "new-version": "Do you want to reload the app?", + "data-download-start": "Downloading data for offline use. Please don't leave the current app.", + "data-download-completed": "Offline data download completed" + + }, "messages": { "title": "Title from a translation.", "message": "Message from a translation - no icon -
Message at the context level
Open the layer 'MSP Tel. Urgence' to see messages at the layer level. {{content}}", diff --git a/src/locale/fr.json b/src/locale/fr.json index 0aea20618..8cf464b86 100644 --- a/src/locale/fr.json +++ b/src/locale/fr.json @@ -242,9 +242,15 @@ "legend-tab-all": "Permet de visualiser aussi l'ensemble des légendes des couches non visibles à l'échelle active." } }, + "pwa": { + "new-version-title": "Une nouvelle version de l'application est disponible. ", + "new-version": "Voulez-vous recharger l'application?", + "data-download-start": "Téléchargement des données pour utilisation hors-ligne. Veuillez ne pas quitter.", + "data-download-completed": "Téléchargement des données hors-ligne terminé" + }, "messages": { "title": "Titre provenant d'une traduction.", "message": "Message provenant d'une traduction - **Config sans icône-
Message provenant du contexte
Ouvrez lea couche 'MSP Tel. Urgence' pour voir les messages liés. {{content}}", "content": "Du contenu dynamique peut également être ajouté au message" } -} +} \ No newline at end of file diff --git a/src/manifest.webmanifest b/src/manifest.webmanifest new file mode 100644 index 000000000..33c4ee456 --- /dev/null +++ b/src/manifest.webmanifest @@ -0,0 +1,61 @@ +{ + "name": "IGO2 - PWA APP", + "short_name": "IGO", + "description": "IGO2 as a Progressive Web App", + "theme_color": "#1976d2", + "background_color": "#fafafa", + "display": "standalone", + "scope": "./", + "start_url": "./", + "orientation": "any", + "icons": [ + { + "src": "assets/icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ] +}