mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-03-15 03:02:11 +00:00
feat: offline notice
This commit is contained in:
committed by
Rainer Killinger
parent
11d1ac3f7c
commit
9b4caf526f
177
package-lock.json
generated
177
package-lock.json
generated
@@ -28,6 +28,23 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "13.3.9",
|
"@angular-devkit/core": "13.3.9",
|
||||||
"rxjs": "6.6.7"
|
"rxjs": "6.6.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/build-angular": {
|
"@angular-devkit/build-angular": {
|
||||||
@@ -240,6 +257,23 @@
|
|||||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||||
@@ -292,6 +326,23 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/architect": "0.1303.9",
|
"@angular-devkit/architect": "0.1303.9",
|
||||||
"rxjs": "6.6.7"
|
"rxjs": "6.6.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/core": {
|
"@angular-devkit/core": {
|
||||||
@@ -319,6 +370,21 @@
|
|||||||
"require-from-string": "^2.0.2",
|
"require-from-string": "^2.0.2",
|
||||||
"uri-js": "^4.2.2"
|
"uri-js": "^4.2.2"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -340,6 +406,21 @@
|
|||||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
|
||||||
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
|
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2594,6 +2675,21 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^8.0.0"
|
"ajv": "^8.0.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2970,6 +3066,23 @@
|
|||||||
"string-width": "^4.1.0",
|
"string-width": "^4.1.0",
|
||||||
"strip-ansi": "^6.0.0",
|
"strip-ansi": "^6.0.0",
|
||||||
"through": "^2.3.6"
|
"through": "^2.3.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3774,6 +3887,23 @@
|
|||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.4",
|
"version": "7.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
||||||
@@ -3841,6 +3971,23 @@
|
|||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.4",
|
"version": "7.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
|
||||||
@@ -15378,18 +15525,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rxjs": {
|
"rxjs": {
|
||||||
"version": "6.6.7",
|
"version": "7.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
|
||||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^1.9.0"
|
"tslib": "^2.1.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rxjs-for-await": {
|
"rxjs-for-await": {
|
||||||
@@ -16651,6 +16791,15 @@
|
|||||||
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
|
"integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"rxjs": {
|
||||||
|
"version": "6.6.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||||
|
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^1.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||||
@@ -16741,6 +16890,12 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||||
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
"ngx-markdown": "13.1.0",
|
"ngx-markdown": "13.1.0",
|
||||||
"ngx-moment": "6.0.2",
|
"ngx-moment": "6.0.2",
|
||||||
"opening_hours": "3.8.0",
|
"opening_hours": "3.8.0",
|
||||||
"rxjs": "6.6.7",
|
"rxjs": "7.8.0",
|
||||||
"swiper": "8.4.5",
|
"swiper": "8.4.5",
|
||||||
"tslib": "2.4.1",
|
"tslib": "2.4.1",
|
||||||
"zone.js": "0.12.0"
|
"zone.js": "0.12.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ import {DefaultAuthService} from './default-auth.service';
|
|||||||
import {Browser} from 'ionic-appauth';
|
import {Browser} from 'ionic-appauth';
|
||||||
import {nowInSeconds, Requestor, StorageBackend} from '@openid/appauth';
|
import {nowInSeconds, Requestor, StorageBackend} from '@openid/appauth';
|
||||||
import {TranslateService} from '@ngx-translate/core';
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
import {LoggerConfig, LoggerModule, NGXLogger} from 'ngx-logger';
|
import {LoggerConfig, LoggerModule, NGXLogger, NgxLoggerLevel} from 'ngx-logger';
|
||||||
import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider';
|
import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider';
|
||||||
import {HttpClientModule} from '@angular/common/http';
|
import {HttpClientModule} from '@angular/common/http';
|
||||||
import {IonicStorage} from 'ionic-appauth/lib';
|
import {IonicStorage} from 'ionic-appauth/lib';
|
||||||
|
import {RouterModule} from '@angular/router';
|
||||||
|
|
||||||
describe('AuthService', () => {
|
describe('AuthService', () => {
|
||||||
let defaultAuthService: DefaultAuthService;
|
let defaultAuthService: DefaultAuthService;
|
||||||
@@ -34,7 +35,11 @@ describe('AuthService', () => {
|
|||||||
storageBackendSpy = jasmine.createSpyObj('StorageBackend', ['getItem']);
|
storageBackendSpy = jasmine.createSpyObj('StorageBackend', ['getItem']);
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [HttpClientModule, LoggerModule],
|
imports: [
|
||||||
|
HttpClientModule,
|
||||||
|
LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}),
|
||||||
|
RouterModule.forRoot([]),
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
NGXLogger,
|
NGXLogger,
|
||||||
StAppsWebHttpClient,
|
StAppsWebHttpClient,
|
||||||
|
|||||||
@@ -1,8 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {Requestor} from '@openid/appauth';
|
import {Requestor} from '@openid/appauth';
|
||||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||||
import {XhrSettings} from 'ionic-appauth/lib/cordova';
|
import {XhrSettings} from 'ionic-appauth/lib/cordova';
|
||||||
import {Observable} from 'rxjs';
|
import {firstValueFrom, Observable} from 'rxjs';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
@@ -40,7 +55,7 @@ export class NgHttpService implements Requestor {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return observable.toPromise();
|
return firstValueFrom(observable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -215,14 +215,12 @@ export class ScheduleProvider implements OnDestroy {
|
|||||||
if (from || to) {
|
if (from || to) {
|
||||||
const bounds: Bounds<string> = {};
|
const bounds: Bounds<string> = {};
|
||||||
if (from) {
|
if (from) {
|
||||||
console.log(from);
|
|
||||||
bounds.lowerBound = {
|
bounds.lowerBound = {
|
||||||
limit: from,
|
limit: from,
|
||||||
mode: 'inclusive',
|
mode: 'inclusive',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (to) {
|
if (to) {
|
||||||
console.log(to);
|
|
||||||
bounds.upperBound = {
|
bounds.upperBound = {
|
||||||
limit: to,
|
limit: to,
|
||||||
mode: 'inclusive',
|
mode: 'inclusive',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -31,6 +31,8 @@ import {StorageProvider} from '../storage/storage.provider';
|
|||||||
import {DataModule} from './data.module';
|
import {DataModule} from './data.module';
|
||||||
import {DataProvider, DataScope} from './data.provider';
|
import {DataProvider, DataScope} from './data.provider';
|
||||||
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';
|
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';
|
||||||
|
import {LoggerModule, NgxLoggerLevel} from 'ngx-logger';
|
||||||
|
import {RouterModule} from '@angular/router';
|
||||||
|
|
||||||
describe('DataProvider', () => {
|
describe('DataProvider', () => {
|
||||||
let dataProvider: DataProvider;
|
let dataProvider: DataProvider;
|
||||||
@@ -82,7 +84,7 @@ describe('DataProvider', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [DataModule],
|
imports: [DataModule, LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}), RouterModule.forRoot([])],
|
||||||
providers: [DataProvider, StAppsWebHttpClient],
|
providers: [DataProvider, StAppsWebHttpClient],
|
||||||
});
|
});
|
||||||
storageProvider = TestBed.inject(StorageProvider);
|
storageProvider = TestBed.inject(StorageProvider);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -27,6 +27,7 @@ import {DataDetailComponent} from './data-detail.component';
|
|||||||
import {By} from '@angular/platform-browser';
|
import {By} from '@angular/platform-browser';
|
||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import {StorageProvider} from '../../storage/storage.provider';
|
import {StorageProvider} from '../../storage/storage.provider';
|
||||||
|
import {LoggerModule, NgxLoggerLevel} from 'ngx-logger';
|
||||||
|
|
||||||
const translations: any = {data: {detail: {TITLE: 'Foo'}}};
|
const translations: any = {data: {detail: {TITLE: 'Foo'}}};
|
||||||
|
|
||||||
@@ -70,6 +71,7 @@ describe('DataDetailComponent', () => {
|
|||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
loader: {provide: TranslateLoader, useClass: TranslateFakeLoader},
|
loader: {provide: TranslateLoader, useClass: TranslateFakeLoader},
|
||||||
}),
|
}),
|
||||||
|
LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -229,13 +229,7 @@ export class SearchPageComponent implements OnInit, OnDestroy {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const alert: HTMLIonAlertElement = await this.alertController.create({
|
this.logger.error(error);
|
||||||
buttons: ['Dismiss'],
|
|
||||||
header: 'Error',
|
|
||||||
subHeader: (error as Error).message,
|
|
||||||
});
|
|
||||||
|
|
||||||
await alert.present();
|
|
||||||
} finally {
|
} finally {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -15,6 +15,17 @@
|
|||||||
import {HttpClient, HttpResponse} from '@angular/common/http';
|
import {HttpClient, HttpResponse} from '@angular/common/http';
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {HttpClientInterface, HttpClientRequest} from '@openstapps/api/lib/http-client-interface';
|
import {HttpClientInterface, HttpClientRequest} from '@openstapps/api/lib/http-client-interface';
|
||||||
|
import {map, retry} from 'rxjs/operators';
|
||||||
|
import {lastValueFrom, Observable} from 'rxjs';
|
||||||
|
import {InternetConnectionService} from '../../util/internet-connection.service';
|
||||||
|
|
||||||
|
type HttpRequestFunctions = InstanceType<typeof HttpClient>['request'];
|
||||||
|
type HttpRequestFunction<T extends ReturnType<HttpRequestFunctions>> = Extract<
|
||||||
|
HttpRequestFunctions,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
(...parameters: any[]) => T
|
||||||
|
>;
|
||||||
|
type HttpRequestParameters<T extends ReturnType<HttpRequestFunctions>> = Parameters<HttpRequestFunction<T>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HttpClient that is based on the Angular HttpClient (@TODO: move it to provider or independent package)
|
* HttpClient that is based on the Angular HttpClient (@TODO: move it to provider or independent package)
|
||||||
@@ -23,9 +34,11 @@ import {HttpClientInterface, HttpClientRequest} from '@openstapps/api/lib/http-c
|
|||||||
export class StAppsWebHttpClient implements HttpClientInterface {
|
export class StAppsWebHttpClient implements HttpClientInterface {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param http TODO
|
|
||||||
*/
|
*/
|
||||||
constructor(private readonly http: HttpClient) {}
|
constructor(
|
||||||
|
private readonly http: HttpClient,
|
||||||
|
private readonly connectionService: InternetConnectionService,
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a request
|
* Make a request
|
||||||
@@ -33,42 +46,30 @@ export class StAppsWebHttpClient implements HttpClientInterface {
|
|||||||
* @param requestConfig Configuration of the request
|
* @param requestConfig Configuration of the request
|
||||||
*/
|
*/
|
||||||
async request<TYPE_OF_BODY>(requestConfig: HttpClientRequest): Promise<Response<TYPE_OF_BODY>> {
|
async request<TYPE_OF_BODY>(requestConfig: HttpClientRequest): Promise<Response<TYPE_OF_BODY>> {
|
||||||
const options: {
|
const request: HttpRequestParameters<Observable<HttpResponse<TYPE_OF_BODY>>> = [
|
||||||
/**
|
requestConfig.method || 'GET',
|
||||||
* TODO
|
requestConfig.url.toString(),
|
||||||
*/
|
{
|
||||||
[key: string]: unknown;
|
body: (requestConfig.body || {}) as TYPE_OF_BODY,
|
||||||
/**
|
headers: requestConfig.headers,
|
||||||
* TODO
|
observe: 'response',
|
||||||
*/
|
responseType: 'json',
|
||||||
observe: 'response';
|
},
|
||||||
} = {
|
];
|
||||||
body: {},
|
// TODO: cache requests by hashing the parameters.
|
||||||
observe: 'response',
|
|
||||||
responseType: 'json',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof requestConfig.body !== 'undefined') {
|
const response: Observable<Response<TYPE_OF_BODY>> = this.http.request(...request).pipe(
|
||||||
options.body = requestConfig.body;
|
retry(this.connectionService.retryConfig),
|
||||||
}
|
map(
|
||||||
|
response =>
|
||||||
|
Object.assign(response, {
|
||||||
|
statusCode: response.status,
|
||||||
|
body: response.body || {},
|
||||||
|
}) as Response<TYPE_OF_BODY>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (typeof requestConfig.headers !== 'undefined') {
|
return lastValueFrom(response);
|
||||||
options.headers = requestConfig.headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response: HttpResponse<TYPE_OF_BODY> = await this.http
|
|
||||||
.request<TYPE_OF_BODY>(requestConfig.method || 'GET', requestConfig.url.toString(), options)
|
|
||||||
.toPromise();
|
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-object-spread
|
|
||||||
return Object.assign(response, {
|
|
||||||
statusCode: response.status,
|
|
||||||
body: response.body || {},
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
throw new Error(error as string);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -28,6 +28,7 @@ import {Observable, of} from 'rxjs';
|
|||||||
import {StorageProvider} from '../../storage/storage.provider';
|
import {StorageProvider} from '../../storage/storage.provider';
|
||||||
import {IonicModule} from '@ionic/angular';
|
import {IonicModule} from '@ionic/angular';
|
||||||
import {IonIconModule} from '../../../util/ion-icon/ion-icon.module';
|
import {IonIconModule} from '../../../util/ion-icon/ion-icon.module';
|
||||||
|
import {LoggerModule, NgxLoggerLevel} from 'ngx-logger';
|
||||||
|
|
||||||
const translations: any = {data: {detail: {TITLE: 'Foo'}}};
|
const translations: any = {data: {detail: {TITLE: 'Foo'}}};
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ describe('HebisDetailComponent', () => {
|
|||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
loader: {provide: TranslateLoader, useClass: TranslateFakeLoader},
|
loader: {provide: TranslateLoader, useClass: TranslateFakeLoader},
|
||||||
}),
|
}),
|
||||||
|
LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019-2021 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -20,9 +20,10 @@ import {HttpClientModule} from '@angular/common/http';
|
|||||||
import {StorageProvider} from '../storage/storage.provider';
|
import {StorageProvider} from '../storage/storage.provider';
|
||||||
import {MapModule} from './map.module';
|
import {MapModule} from './map.module';
|
||||||
import {StorageModule} from '../storage/storage.module';
|
import {StorageModule} from '../storage/storage.module';
|
||||||
import {LoggerConfig, LoggerModule, NGXLogger} from 'ngx-logger';
|
import {LoggerModule, NGXLogger, NgxLoggerLevel} from 'ngx-logger';
|
||||||
import {ConfigProvider} from '../config/config.provider';
|
import {ConfigProvider} from '../config/config.provider';
|
||||||
import {sampleDefaultPolygon} from '../../_helpers/data/sample-configuration';
|
import {sampleDefaultPolygon} from '../../_helpers/data/sample-configuration';
|
||||||
|
import {RouterModule} from '@angular/router';
|
||||||
|
|
||||||
describe('MapProvider', () => {
|
describe('MapProvider', () => {
|
||||||
let provider: MapProvider;
|
let provider: MapProvider;
|
||||||
@@ -31,7 +32,13 @@ describe('MapProvider', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
configProvider = jasmine.createSpyObj('ConfigProvider', ['getValue']);
|
configProvider = jasmine.createSpyObj('ConfigProvider', ['getValue']);
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [MapModule, HttpClientModule, StorageModule, LoggerModule],
|
imports: [
|
||||||
|
MapModule,
|
||||||
|
HttpClientModule,
|
||||||
|
StorageModule,
|
||||||
|
LoggerModule.forRoot({level: NgxLoggerLevel.TRACE}),
|
||||||
|
RouterModule.forRoot([]),
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: ConfigProvider,
|
provide: ConfigProvider,
|
||||||
@@ -40,7 +47,6 @@ describe('MapProvider', () => {
|
|||||||
StAppsWebHttpClient,
|
StAppsWebHttpClient,
|
||||||
StorageProvider,
|
StorageProvider,
|
||||||
NGXLogger,
|
NGXLogger,
|
||||||
LoggerConfig,
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -40,7 +40,7 @@ export class ContextMenuService {
|
|||||||
/**
|
/**
|
||||||
* Container for the filter query (SCSearchFilter)
|
* Container for the filter query (SCSearchFilter)
|
||||||
*/
|
*/
|
||||||
filterQuery = new Subject<SCSearchFilter>();
|
filterQuery = new Subject<SCSearchFilter | undefined>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable filterContext streams
|
* Observable filterContext streams
|
||||||
@@ -65,7 +65,7 @@ export class ContextMenuService {
|
|||||||
/**
|
/**
|
||||||
* Container for the sort query
|
* Container for the sort query
|
||||||
*/
|
*/
|
||||||
sortQuery = new Subject<SCSearchSort[]>();
|
sortQuery = new Subject<SCSearchSort[] | undefined>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observable SortContext streams
|
* Observable SortContext streams
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018, 2019 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<stapps-offline-notice></stapps-offline-notice>
|
||||||
<ion-split-pane contentId="main" when="lg">
|
<ion-split-pane contentId="main" when="lg">
|
||||||
<ion-menu menuId="main" contentId="main" type="overlay" side="start" swipe-gesture="false">
|
<ion-menu menuId="main" contentId="main" type="overlay" side="start" swipe-gesture="false">
|
||||||
<ion-header>
|
<ion-header>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -21,9 +21,10 @@ import {IonicModule} from '@ionic/angular';
|
|||||||
import {IonIconModule} from '../../../util/ion-icon/ion-icon.module';
|
import {IonIconModule} from '../../../util/ion-icon/ion-icon.module';
|
||||||
import {TranslateModule} from '@ngx-translate/core';
|
import {TranslateModule} from '@ngx-translate/core';
|
||||||
import {RouterModule} from '@angular/router';
|
import {RouterModule} from '@angular/router';
|
||||||
|
import {OfflineNoticeComponent} from './offline-notice.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [RootLinkDirective, NavigationComponent, TabsComponent],
|
declarations: [RootLinkDirective, NavigationComponent, TabsComponent, OfflineNoticeComponent],
|
||||||
imports: [CommonModule, IonicModule, IonIconModule, TranslateModule, RouterModule],
|
imports: [CommonModule, IonicModule, IonIconModule, TranslateModule, RouterModule],
|
||||||
exports: [TabsComponent, RootLinkDirective, NavigationComponent],
|
exports: [TabsComponent, RootLinkDirective, NavigationComponent],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
* Copyright (C) 2022 StApps
|
* Copyright (C) 2023 StApps
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
* Software Foundation, version 3.
|
* Software Foundation, version 3.
|
||||||
@@ -21,8 +21,14 @@ stapps-navigation-tabs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stapps-offline-notice.has-error ~ ion-split-pane,
|
||||||
|
stapps-offline-notice.is-offline ~ ion-split-pane {
|
||||||
|
margin-top: calc(var(--font-size-md) + 2 * var(--spacing-sm));
|
||||||
|
}
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
ion-split-pane {
|
ion-split-pane {
|
||||||
|
transition: margin-top 150ms ease;
|
||||||
--side-max-width: 256px;
|
--side-max-width: 256px;
|
||||||
margin-bottom: calc(var(--ion-tabbar-height) + env(safe-area-inset-bottom));
|
margin-bottom: calc(var(--ion-tabbar-height) + env(safe-area-inset-bottom));
|
||||||
|
|
||||||
|
|||||||
63
src/app/modules/menu/navigation/offline-notice.component.ts
Normal file
63
src/app/modules/menu/navigation/offline-notice.component.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Component, ElementRef, HostBinding, OnDestroy, ViewChild} from '@angular/core';
|
||||||
|
import {InternetConnectionService} from '../../../util/internet-connection.service';
|
||||||
|
import {Subscription} from 'rxjs';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
import {NGXLogger} from 'ngx-logger';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'stapps-offline-notice',
|
||||||
|
templateUrl: 'offline-notice.html',
|
||||||
|
styleUrls: ['offline-notice.scss'],
|
||||||
|
})
|
||||||
|
export class OfflineNoticeComponent implements OnDestroy {
|
||||||
|
@HostBinding('class.is-offline') isOffline = false;
|
||||||
|
|
||||||
|
@HostBinding('class.has-error') hasError = false;
|
||||||
|
|
||||||
|
@ViewChild('spinIcon', {read: ElementRef}) spinIcon: ElementRef;
|
||||||
|
|
||||||
|
readonly subscriptions: Subscription[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly offlineProvider: InternetConnectionService,
|
||||||
|
readonly router: Router,
|
||||||
|
readonly logger: NGXLogger,
|
||||||
|
) {
|
||||||
|
this.subscriptions = [
|
||||||
|
this.offlineProvider.offline$.subscribe(isOffline => {
|
||||||
|
this.isOffline = isOffline;
|
||||||
|
}),
|
||||||
|
this.offlineProvider.error$.subscribe(hasError => {
|
||||||
|
this.hasError = hasError;
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
retry() {
|
||||||
|
this.spinIcon.nativeElement.classList.remove('spin');
|
||||||
|
this.spinIcon.nativeElement.offsetWidth;
|
||||||
|
this.spinIcon.nativeElement.classList.add('spin');
|
||||||
|
this.offlineProvider.retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
for (const subscription of this.subscriptions) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/app/modules/menu/navigation/offline-notice.html
Normal file
25
src/app/modules/menu/navigation/offline-notice.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2023 StApps
|
||||||
|
~ This program is free software: you can redistribute it and/or modify it
|
||||||
|
~ under the terms of the GNU General Public License as published by the Free
|
||||||
|
~ Software Foundation, version 3.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
~ more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License along with
|
||||||
|
~ this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
<ion-button class="offline-button" color="warning">
|
||||||
|
<ion-icon slot="start" size="16" weight="800" name="cloud_off"></ion-icon>
|
||||||
|
<ion-label>{{ 'app.errors.OFFLINE' | translate }}</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
<ion-button class="error-button" color="danger" (click)="retry()">
|
||||||
|
<ion-icon #spinIcon slot="start" size="16" weight="800" name="refresh"></ion-icon>
|
||||||
|
<ion-label>{{ 'app.errors.CONNECTION_ERROR' | translate }}</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
<ion-button class="close" fill="clear" color="light" (click)="offlineProvider.dismissError()"
|
||||||
|
><ion-icon size="16" weight="800" name="close" slot="icon-only"></ion-icon
|
||||||
|
></ion-button>
|
||||||
77
src/app/modules/menu/navigation/offline-notice.scss
Normal file
77
src/app/modules/menu/navigation/offline-notice.scss
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*!
|
||||||
|
* Copyright (C) 2023 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
:host {
|
||||||
|
display: grid;
|
||||||
|
$height: calc(var(--font-size-md) + 2 * var(--spacing-sm));
|
||||||
|
|
||||||
|
height: $height;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
line-height: var(--font-size-md);
|
||||||
|
font-size: var(--font-size-md);
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
transform: translateY(calc(-1 * $height));
|
||||||
|
|
||||||
|
transition: all 150ms ease;
|
||||||
|
|
||||||
|
&.is-offline,
|
||||||
|
&.has-error {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
> ion-button {
|
||||||
|
grid-row: 1;
|
||||||
|
grid-column: 1;
|
||||||
|
margin: 0;
|
||||||
|
--border-radius: 0;
|
||||||
|
opacity: 0;
|
||||||
|
--padding-top: 0;
|
||||||
|
--padding-bottom: 0;
|
||||||
|
transition: all 150ms ease;
|
||||||
|
z-index: 0;
|
||||||
|
|
||||||
|
&.close {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
z-index: 1;
|
||||||
|
color: var(--ion-color-danger-contrast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-offline > .offline-button,
|
||||||
|
&.has-error > .close,
|
||||||
|
&.has-error > .error-button {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spin {
|
||||||
|
animation: loading 1s ease running 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes loading {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
import {Injectable} from '@angular/core';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MenuService provides bidirectional communication of context menu options and search queries
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class ScheduleService {}
|
|
||||||
106
src/app/util/internet-connection.service.ts
Normal file
106
src/app/util/internet-connection.service.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 StApps
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import {fromEvent, merge, ObservableInput, of, race, RetryConfig, share, Subject, takeUntil} from 'rxjs';
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {filter, map, startWith, take, tap} from 'rxjs/operators';
|
||||||
|
import {NGXLogger} from 'ngx-logger';
|
||||||
|
import {Router} from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class InternetConnectionService {
|
||||||
|
private readonly manualRetry$ = new Subject<void>();
|
||||||
|
|
||||||
|
private readonly abortRetry$ = new Subject<void>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits whenever the browser goes online or offline.
|
||||||
|
*/
|
||||||
|
readonly offline$ = window
|
||||||
|
? merge(
|
||||||
|
fromEvent(window, 'online').pipe(map(() => false)),
|
||||||
|
fromEvent(window, 'offline').pipe(map(() => true)),
|
||||||
|
).pipe(startWith(!window.navigator.onLine), share())
|
||||||
|
: of(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits whenever http requests should be retried
|
||||||
|
*
|
||||||
|
* Also keeps track of when a retry is needed, automatically
|
||||||
|
* registering itself.
|
||||||
|
*/
|
||||||
|
readonly retryConfig: RetryConfig = {
|
||||||
|
delay: this.doRetry.bind(this),
|
||||||
|
};
|
||||||
|
|
||||||
|
private doRetry(error: unknown, retryCount: number): ObservableInput<unknown> {
|
||||||
|
return race(
|
||||||
|
this.offline$.pipe(
|
||||||
|
tap(it => console.log(it)),
|
||||||
|
filter(it => !it),
|
||||||
|
take(1),
|
||||||
|
),
|
||||||
|
this.manualRetry$,
|
||||||
|
).pipe(
|
||||||
|
tap({
|
||||||
|
subscribe: () => {
|
||||||
|
this.errors.add(error);
|
||||||
|
if (this.errors.size > 0) {
|
||||||
|
this.error$.next(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
next: () => {
|
||||||
|
this.logger.error(`${retryCount}x`, error);
|
||||||
|
},
|
||||||
|
unsubscribe: () => {
|
||||||
|
this.errors.delete(error);
|
||||||
|
if (this.errors.size === 0) {
|
||||||
|
this.error$.next(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
takeUntil(
|
||||||
|
merge(
|
||||||
|
this.abortRetry$.pipe(tap(() => this.logger.warn('HTTP Request retry aborted manually'))),
|
||||||
|
this.router.events.pipe(tap(() => this.logger.warn('HTTP Request retry aborted by routing'))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits when there are errors
|
||||||
|
*/
|
||||||
|
readonly error$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
private readonly errors = new Set<unknown>();
|
||||||
|
|
||||||
|
constructor(private readonly logger: NGXLogger, private readonly router: Router) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retry all failed http requests
|
||||||
|
*/
|
||||||
|
retry() {
|
||||||
|
this.manualRetry$.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abandon all failed http requests
|
||||||
|
*/
|
||||||
|
dismissError() {
|
||||||
|
this.abortRetry$.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,9 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"SERVICE": "Fehler bei Dienstausführung.",
|
"SERVICE": "Fehler bei Dienstausführung.",
|
||||||
"UNKNOWN": "Unbekannter Fehler."
|
"UNKNOWN": "Unbekannter Fehler.",
|
||||||
|
"OFFLINE": "Keine Internetverbindung",
|
||||||
|
"CONNECTION_ERROR": "Verbindungsfehler"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"assessments": {
|
"assessments": {
|
||||||
|
|||||||
@@ -27,7 +27,9 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"SERVICE": "Service error.",
|
"SERVICE": "Service error.",
|
||||||
"UNKNOWN": "Unknown problem."
|
"UNKNOWN": "Unknown problem.",
|
||||||
|
"OFFLINE": "No internet connection",
|
||||||
|
"CONNECTION_ERROR": "Connection error"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"assessments": {
|
"assessments": {
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user