mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-10-03 16:22:05 +00:00
fix: update core and apply stricter tslint rules
This commit is contained in:
@@ -1,3 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 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/>.
|
||||||
|
*/
|
||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
export const sampleResources = [{
|
export const sampleResources = [{
|
||||||
'errorNames': [],
|
'errorNames': [],
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ import {SCAcademicEvent, SCArticle, SCBook, SCBuilding, SCCatalog,
|
|||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import {sampleResources} from './resources/test-resources';
|
import {sampleResources} from './resources/test-resources';
|
||||||
|
|
||||||
|
// tslint:disable:no-magic-numbers
|
||||||
const sampleMessages: SCMessage[] = [
|
const sampleMessages: SCMessage[] = [
|
||||||
{
|
{
|
||||||
audiences: ['students'],
|
audiences: ['students'],
|
||||||
message: 'Foo Message Text',
|
messageBody: 'Foo Message Text',
|
||||||
name: 'Foo Message',
|
name: 'Foo Message',
|
||||||
origin: {
|
origin: {
|
||||||
indexed: 'SOME-DATE',
|
indexed: 'SOME-DATE',
|
||||||
@@ -35,7 +36,7 @@ const sampleMessages: SCMessage[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
audiences: ['employees'],
|
audiences: ['employees'],
|
||||||
message: 'Bar Message Text',
|
messageBody: 'Bar Message Text',
|
||||||
name: 'Bar Message',
|
name: 'Bar Message',
|
||||||
origin: {
|
origin: {
|
||||||
indexed: 'SOME-DATE',
|
indexed: 'SOME-DATE',
|
||||||
@@ -363,13 +364,19 @@ export const sampleThingsMap: {[key in SCThingType | string]: SCThing[]} = {
|
|||||||
tour: [],
|
tour: [],
|
||||||
video: [],
|
video: [],
|
||||||
};
|
};
|
||||||
|
// tslint:enable:no-magic-numbers
|
||||||
|
|
||||||
// provides all or certain sample things to be used in tests or backendless development
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* provides all or certain sample things to be used in tests or backendless development
|
||||||
|
*/
|
||||||
export function getSampleThings(...uids: string[]): SCThing[] {
|
export function getSampleThings(...uids: string[]): SCThing[] {
|
||||||
const sampleThings: SCThing[] = [];
|
const sampleThings: SCThing[] = [];
|
||||||
if (typeof uids !== 'undefined' && uids.length > 0) {
|
if (typeof uids !== 'undefined' && uids.length > 0) {
|
||||||
uids.forEach((uid) => {
|
uids.forEach((uid) => {
|
||||||
Object.keys(sampleThingsMap).forEach((key) => {
|
Object.keys(sampleThingsMap)
|
||||||
|
.forEach((key) => {
|
||||||
sampleThingsMap[key].forEach((thing) => {
|
sampleThingsMap[key].forEach((thing) => {
|
||||||
if (thing.uid === uid) {
|
if (thing.uid === uid) {
|
||||||
sampleThings.push(thing);
|
sampleThings.push(thing);
|
||||||
@@ -378,16 +385,25 @@ export function getSampleThings(...uids: string[]): SCThing[] {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.keys(sampleThingsMap).forEach((key) => {
|
Object.keys(sampleThingsMap)
|
||||||
|
.forEach((key) => {
|
||||||
sampleThings.push(...sampleThingsMap[key]);
|
sampleThings.push(...sampleThingsMap[key]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return sampleThings;
|
return sampleThings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SampleThings {
|
export class SampleThings {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
http: HttpClient;
|
http: HttpClient;
|
||||||
|
|
||||||
constructor(http: HttpClient) {
|
constructor(http: HttpClient) {
|
||||||
this.http = http;
|
this.http = http;
|
||||||
}
|
}
|
||||||
@@ -396,6 +412,28 @@ export class SampleThings {
|
|||||||
// // return of(sampleDishes[0]);
|
// // return of(sampleDishes[0]);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
|
getSampleThing(uid: string): Observable<any[]> {
|
||||||
|
// const jsonContent: any[] = await this.http.get('http://localhost:8100/assets/json/joined.json').toPromise();
|
||||||
|
const sampleThings: any[] = [];
|
||||||
|
for (const resource of sampleResources) {
|
||||||
|
if (resource.instance.uid as SCThingType === uid) {
|
||||||
|
sampleThings.push(resource.instance);
|
||||||
|
|
||||||
|
return of(sampleThings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return of(sampleThings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
getSampleThings(): Observable<any[]> {
|
getSampleThings(): Observable<any[]> {
|
||||||
// const jsonContent: any[] = await this.http.get('http://localhost:8100/assets/json/joined.json').toPromise();
|
// const jsonContent: any[] = await this.http.get('http://localhost:8100/assets/json/joined.json').toPromise();
|
||||||
const sampleThings: any[] = [];
|
const sampleThings: any[] = [];
|
||||||
@@ -405,18 +443,7 @@ export class SampleThings {
|
|||||||
sampleThings.push(resource.instance);
|
sampleThings.push(resource.instance);
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
return of(sampleThings);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSampleThing(uid: string): Observable<any[]> {
|
|
||||||
// const jsonContent: any[] = await this.http.get('http://localhost:8100/assets/json/joined.json').toPromise();
|
|
||||||
const sampleThings: any[] = [];
|
|
||||||
for (const resource of sampleResources) {
|
|
||||||
if (resource.instance.uid as SCThingType === uid) {
|
|
||||||
sampleThings.push(resource.instance);
|
|
||||||
return of(sampleThings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return of(sampleThings);
|
return of(sampleThings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,12 @@
|
|||||||
import {HTTP_INTERCEPTORS, HttpClient,
|
import {HTTP_INTERCEPTORS, HttpClient,
|
||||||
HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
|
HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {SCIndexResponse, SCThingOriginType, SCThingType} from '@openstapps/core';
|
import {SCIndexResponse, SCSettingInputType, SCThingOriginType, SCThingType} from '@openstapps/core';
|
||||||
import {Observable, of} from 'rxjs';
|
import {Observable, of} from 'rxjs';
|
||||||
import {map, delay} from 'rxjs/operators';
|
import {delay, map} from 'rxjs/operators';
|
||||||
import {SampleThings} from './data/sample-things';
|
import {SampleThings} from './data/sample-things';
|
||||||
|
|
||||||
|
// tslint:disable:no-magic-numbers
|
||||||
const sampleIndexResponse: SCIndexResponse = {
|
const sampleIndexResponse: SCIndexResponse = {
|
||||||
app: {
|
app: {
|
||||||
campusPolygon: {
|
campusPolygon: {
|
||||||
@@ -58,12 +59,9 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
categories: ['profile'],
|
categories: ['profile'],
|
||||||
description: '',
|
|
||||||
input: {
|
|
||||||
defaultValue: 'student',
|
defaultValue: 'student',
|
||||||
inputType: 'singleChoice',
|
description: '',
|
||||||
values: ['student', 'employee', 'guest'],
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
},
|
|
||||||
name: 'group',
|
name: 'group',
|
||||||
order: 1,
|
order: 1,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -87,15 +85,13 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: ['student', 'employee', 'guest'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
categories: ['profile'],
|
categories: ['profile'],
|
||||||
description: '',
|
|
||||||
input: {
|
|
||||||
defaultValue: 'en',
|
defaultValue: 'en',
|
||||||
inputType: 'singleChoice',
|
description: '',
|
||||||
values: ['en', 'de'],
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
},
|
|
||||||
name: 'language',
|
name: 'language',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -117,15 +113,13 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: ['en', 'de'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
categories: ['privacy'],
|
categories: ['privacy'],
|
||||||
description: '',
|
|
||||||
input: {
|
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
inputType: 'singleChoice',
|
description: '',
|
||||||
values: [true, false],
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
},
|
|
||||||
name: 'geoLocation',
|
name: 'geoLocation',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -149,6 +143,7 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: [true, false],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -226,20 +221,33 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// tslint:enable:no-magic-numbers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FakeBackendInterceptor implements HttpInterceptor {
|
export class FakeBackendInterceptor implements HttpInterceptor {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
sampleFetcher: SampleThings;
|
sampleFetcher: SampleThings;
|
||||||
|
|
||||||
constructor(http: HttpClient) {
|
constructor(http: HttpClient) {
|
||||||
this.sampleFetcher = new SampleThings(http);
|
this.sampleFetcher = new SampleThings(http);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
if (request.method === 'POST') {
|
if (request.method === 'POST') {
|
||||||
if (request.url.endsWith('/') && request.method === 'POST') {
|
if (request.url.endsWith('/') && request.method === 'POST') {
|
||||||
// respond with expected (faked) index response
|
// respond with expected (faked) index response
|
||||||
return of(new HttpResponse({status: 200, body: sampleIndexResponse}));
|
return of(new HttpResponse({status: 200, body: sampleIndexResponse}));
|
||||||
// respond with a search response with sample data
|
// respond with a search response with sample data
|
||||||
} else if (request.url.endsWith('/search')) {
|
}
|
||||||
|
if (request.url.endsWith('/search')) {
|
||||||
if (typeof request.body.filter !== 'undefined' && typeof request.body.filter.arguments !== 'undefined') {
|
if (typeof request.body.filter !== 'undefined' && typeof request.body.filter.arguments !== 'undefined') {
|
||||||
if (request.body.filter.arguments.field === 'uid') {
|
if (request.body.filter.arguments.field === 'uid') {
|
||||||
return this.sampleFetcher.getSampleThing(request.body.filter.arguments.value)
|
return this.sampleFetcher.getSampleThing(request.body.filter.arguments.value)
|
||||||
@@ -248,11 +256,14 @@ export class FakeBackendInterceptor implements HttpInterceptor {
|
|||||||
}), delay(1000)); // add delay for skeleton screens to be seen (see !16)
|
}), delay(1000)); // add delay for skeleton screens to be seen (see !16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.sampleFetcher.getSampleThings().pipe(map((sampleData: any) => {
|
|
||||||
|
return this.sampleFetcher.getSampleThings()
|
||||||
|
.pipe(map((sampleData: any) => {
|
||||||
return new HttpResponse({status: 200, body: {data: sampleData}});
|
return new HttpResponse({status: 200, body: {data: sampleData}});
|
||||||
}), delay(1000)); // add delay for skeleton screens to be seen (see !16)
|
}), delay(1000)); // add delay for skeleton screens to be seen (see !16)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return next.handle(request);
|
return next.handle(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -16,11 +16,14 @@ import {NgModule} from '@angular/core';
|
|||||||
import {RouterModule, Routes} from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: '', redirectTo: '/search', pathMatch: 'full'}
|
{path: '', redirectTo: '/search', pathMatch: 'full'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
exports: [RouterModule],
|
exports: [RouterModule],
|
||||||
imports: [RouterModule.forRoot(routes)]
|
imports: [RouterModule.forRoot(routes)],
|
||||||
})
|
})
|
||||||
export class AppRoutingModule {}
|
export class AppRoutingModule {}
|
||||||
|
|||||||
+38
-13
@@ -21,30 +21,55 @@ import {Logger} from '@openstapps/logger';
|
|||||||
import {ConfigProvider} from './modules/config/config.provider';
|
import {ConfigProvider} from './modules/config/config.provider';
|
||||||
import {SettingsProvider} from './modules/settings/settings.provider';
|
import {SettingsProvider} from './modules/settings/settings.provider';
|
||||||
|
|
||||||
const logger: Logger = new Logger();
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: 'app.component.html',
|
templateUrl: 'app.component.html',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
logger: Logger = new Logger();
|
/**
|
||||||
pages: Array<{ component: any, title: string }>;
|
* TODO
|
||||||
|
*/
|
||||||
|
pages: Array<{
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
component: any;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
constructor(private platform: Platform,
|
/**
|
||||||
private statusBar: StatusBar,
|
*
|
||||||
private splashScreen: SplashScreen,
|
* @param platform TODO
|
||||||
private translateService: TranslateService,
|
* @param statusBar TODO
|
||||||
private settingsProvider: SettingsProvider,
|
* @param splashScreen TODO
|
||||||
private configProvider: ConfigProvider) {
|
* @param translateService TODO
|
||||||
|
* @param settingsProvider TODO
|
||||||
|
* @param configProvider TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly platform: Platform,
|
||||||
|
private readonly statusBar: StatusBar,
|
||||||
|
private readonly splashScreen: SplashScreen,
|
||||||
|
private readonly translateService: TranslateService,
|
||||||
|
private readonly settingsProvider: SettingsProvider,
|
||||||
|
private readonly configProvider: ConfigProvider) {
|
||||||
this.initializeApp();
|
this.initializeApp();
|
||||||
|
|
||||||
// this language will be used as a fallback when a translation isn't found in the current language
|
// this language will be used as a fallback when a translation isn't found in the current language
|
||||||
translateService.setDefaultLang('en');
|
translateService.setDefaultLang('en');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
initializeApp() {
|
initializeApp() {
|
||||||
this.platform.ready().then(async () => {
|
this.platform.ready()
|
||||||
|
.then(async () => {
|
||||||
// Okay, so the platform is ready and our plugins are available.
|
// Okay, so the platform is ready and our plugins are available.
|
||||||
// Here you can do any higher level native things you might need.
|
// Here you can do any higher level native things you might need.
|
||||||
this.statusBar.styleDefault();
|
this.statusBar.styleDefault();
|
||||||
@@ -59,7 +84,7 @@ export class AppComponent {
|
|||||||
// @TODO: Issue #43 handle initialisation error and inform user
|
// @TODO: Issue #43 handle initialisation error and inform user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.error(error);
|
await Logger.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set order of categories in settings
|
// set order of categories in settings
|
||||||
@@ -75,7 +100,7 @@ export class AppComponent {
|
|||||||
const languageCode = await this.settingsProvider.getValue('profile', 'language');
|
const languageCode = await this.settingsProvider.getValue('profile', 'language');
|
||||||
this.translateService.use(languageCode);
|
this.translateService.use(languageCode);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.warn(error);
|
Logger.warn(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-3
@@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {CommonModule, registerLocaleData, LocationStrategy, HashLocationStrategy} from '@angular/common';
|
import {CommonModule, HashLocationStrategy, LocationStrategy, registerLocaleData} from '@angular/common';
|
||||||
import {HttpClient} from '@angular/common/http';
|
import {HttpClient} from '@angular/common/http';
|
||||||
import localeDe from '@angular/common/locales/de';
|
import localeDe from '@angular/common/locales/de';
|
||||||
import {NgModule} from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
@@ -34,10 +34,18 @@ import {StorageModule} from './modules/storage/storage.module';
|
|||||||
|
|
||||||
registerLocaleData(localeDe);
|
registerLocaleData(localeDe);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @param http TODO
|
||||||
|
*/
|
||||||
export function createTranslateLoader(http: HttpClient) {
|
export function createTranslateLoader(http: HttpClient) {
|
||||||
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
@@ -66,11 +74,11 @@ export function createTranslateLoader(http: HttpClient) {
|
|||||||
SplashScreen,
|
SplashScreen,
|
||||||
{
|
{
|
||||||
provide: RouteReuseStrategy,
|
provide: RouteReuseStrategy,
|
||||||
useClass: IonicRouteStrategy
|
useClass: IonicRouteStrategy,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: LocationStrategy,
|
provide: LocationStrategy,
|
||||||
useClass: HashLocationStrategy
|
useClass: HashLocationStrategy,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import {DataModule} from '../data/data.module';
|
|||||||
import {StorageModule} from '../storage/storage.module';
|
import {StorageModule} from '../storage/storage.module';
|
||||||
import {ConfigProvider} from './config.provider';
|
import {ConfigProvider} from './config.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
StorageModule,
|
StorageModule,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {SCIndexResponse, SCThingOriginType, SCThingType} from '@openstapps/core';
|
import {SCIndexResponse, SCThingOriginType, SCThingType, SCSettingInputType} from '@openstapps/core';
|
||||||
import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider';
|
import {StAppsWebHttpClient} from '../data/stapps-web-http-client.provider';
|
||||||
import {StorageProvider} from '../storage/storage.provider';
|
import {StorageProvider} from '../storage/storage.provider';
|
||||||
import {ConfigProvider, STORAGE_KEY_CONFIG} from './config.provider';
|
import {ConfigProvider, STORAGE_KEY_CONFIG} from './config.provider';
|
||||||
@@ -207,10 +207,8 @@ const sampleIndexResponse: SCIndexResponse = {
|
|||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
categories: ['credentials'],
|
categories: ['credentials'],
|
||||||
input: {
|
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
inputType: 'text',
|
inputType: SCSettingInputType.Text,
|
||||||
},
|
|
||||||
name: 'username',
|
name: 'username',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
|
|||||||
@@ -39,12 +39,25 @@ export const STORAGE_KEY_CONFIG = 'stapps.config';
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConfigProvider {
|
export class ConfigProvider {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
client: Client;
|
client: Client;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
config: SCIndexResponse;
|
config: SCIndexResponse;
|
||||||
initialised: boolean = false;
|
/**
|
||||||
logger: Logger = new Logger();
|
* TODO
|
||||||
|
*/
|
||||||
|
initialised = false;
|
||||||
|
|
||||||
constructor(private storageProvider: StorageProvider, swHttpClient: StAppsWebHttpClient) {
|
/**
|
||||||
|
*
|
||||||
|
* @param storageProvider TODO
|
||||||
|
* @param swHttpClient TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly storageProvider: StorageProvider, swHttpClient: StAppsWebHttpClient) {
|
||||||
this.client = new Client(swHttpClient, environment.backend_url, environment.backend_version);
|
this.client = new Client(swHttpClient, environment.backend_url, environment.backend_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +90,8 @@ export class ConfigProvider {
|
|||||||
}
|
}
|
||||||
if (typeof this.config.app[attribute] !== 'undefined') {
|
if (typeof this.config.app[attribute] !== 'undefined') {
|
||||||
return this.config.app[attribute];
|
return this.config.app[attribute];
|
||||||
} else {
|
|
||||||
throw new ConfigValueNotAvailable(attribute);
|
|
||||||
}
|
}
|
||||||
|
throw new ConfigValueNotAvailable(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,10 +108,10 @@ export class ConfigProvider {
|
|||||||
try {
|
try {
|
||||||
this.config = await this.loadLocal();
|
this.config = await this.loadLocal();
|
||||||
this.initialised = true;
|
this.initialised = true;
|
||||||
this.logger.log(`initialised configuration from storage: ${JSON.stringify(this.config)}`);
|
Logger.log(`initialised configuration from storage: ${JSON.stringify(this.config)}`);
|
||||||
if (this.config.backend.SCVersion !== environment.backend_version) {
|
if (this.config.backend.SCVersion !== environment.backend_version) {
|
||||||
loadError = new WrongConfigVersionInStorage(environment.backend_version, this.config.backend.SCVersion);
|
loadError = new WrongConfigVersionInStorage(environment.backend_version, this.config.backend.SCVersion);
|
||||||
this.logger.warn(loadError);
|
Logger.warn(loadError);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
loadError = error;
|
loadError = error;
|
||||||
@@ -109,16 +121,18 @@ export class ConfigProvider {
|
|||||||
const fetchedConfig: SCIndexResponse = await this.fetch();
|
const fetchedConfig: SCIndexResponse = await this.fetch();
|
||||||
await this.set(fetchedConfig);
|
await this.set(fetchedConfig);
|
||||||
this.initialised = true;
|
this.initialised = true;
|
||||||
this.logger.log(`initialised configuration from remote: ${JSON.stringify(this.config)}`);
|
Logger.log(`initialised configuration from remote: ${JSON.stringify(this.config)}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
fetchError = error;
|
fetchError = error;
|
||||||
}
|
}
|
||||||
// check for occurred errors and throw them
|
// check for occurred errors and throw them
|
||||||
if (typeof loadError !== 'undefined' && typeof fetchError !== 'undefined') {
|
if (typeof loadError !== 'undefined' && typeof fetchError !== 'undefined') {
|
||||||
throw new ConfigInitError();
|
throw new ConfigInitError();
|
||||||
} else if (typeof loadError !== 'undefined') {
|
}
|
||||||
|
if (typeof loadError !== 'undefined') {
|
||||||
throw loadError;
|
throw loadError;
|
||||||
} else if (typeof fetchError !== 'undefined') {
|
}
|
||||||
|
if (typeof fetchError !== 'undefined') {
|
||||||
throw fetchError;
|
throw fetchError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,7 +146,7 @@ export class ConfigProvider {
|
|||||||
await this.storageProvider.init();
|
await this.storageProvider.init();
|
||||||
// get local configuration
|
// get local configuration
|
||||||
if (await this.storageProvider.has(STORAGE_KEY_CONFIG)) {
|
if (await this.storageProvider.has(STORAGE_KEY_CONFIG)) {
|
||||||
return await this.storageProvider.get<SCIndexResponse>(STORAGE_KEY_CONFIG);
|
return this.storageProvider.get<SCIndexResponse>(STORAGE_KEY_CONFIG);
|
||||||
}
|
}
|
||||||
throw new SavedConfigNotAvailable();
|
throw new SavedConfigNotAvailable();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,11 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {SCBackendAggregationConfiguration, SCFacet, SCThing, SCFacetBucket} from '@openstapps/core';
|
import {SCBackendAggregationConfiguration, SCFacet, SCFacetBucket, SCThing} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DataFacetsProvider {
|
export class DataFacetsProvider {
|
||||||
// tslint:disable-next-line:no-empty
|
// tslint:disable-next-line:no-empty
|
||||||
@@ -29,7 +32,8 @@ export class DataFacetsProvider {
|
|||||||
* @param bucketsMap Buckets array transformed into a map
|
* @param bucketsMap Buckets array transformed into a map
|
||||||
* @param fields A field that should be added to buckets (its map)
|
* @param fields A field that should be added to buckets (its map)
|
||||||
*/
|
*/
|
||||||
addBuckets(bucketsMap: {[key: string]: number}, fields: string[]): {[key: string]: number} {
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
|
addBuckets(bucketsMap: {[key: string]: number; }, fields: string[]): {[key: string]: number; } {
|
||||||
fields.forEach((field) => {
|
fields.forEach((field) => {
|
||||||
if (typeof bucketsMap[field] !== 'undefined') {
|
if (typeof bucketsMap[field] !== 'undefined') {
|
||||||
bucketsMap[field] = bucketsMap[field] + 1;
|
bucketsMap[field] = bucketsMap[field] + 1;
|
||||||
@@ -37,6 +41,7 @@ export class DataFacetsProvider {
|
|||||||
bucketsMap[field] = 1;
|
bucketsMap[field] = 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return bucketsMap;
|
return bucketsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,61 +50,16 @@ export class DataFacetsProvider {
|
|||||||
*
|
*
|
||||||
* @param buckets Buckets from a facet
|
* @param buckets Buckets from a facet
|
||||||
*/
|
*/
|
||||||
bucketsToMap(buckets: SCFacetBucket[]): {[key: string]: number} {
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
const bucketsMap: {[key: string]: number} = {};
|
bucketsToMap(buckets: SCFacetBucket[]): {[key: string]: number; } {
|
||||||
|
const bucketsMap: {[key: string]: number; } = {};
|
||||||
buckets.forEach((bucket) => {
|
buckets.forEach((bucket) => {
|
||||||
bucketsMap[bucket.key] = bucket.count;
|
bucketsMap[bucket.key] = bucket.count;
|
||||||
});
|
});
|
||||||
|
|
||||||
return bucketsMap;
|
return bucketsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a buckets map into buckets array (as it is inside of a facet)
|
|
||||||
*
|
|
||||||
* @param bucketsMap A map from a buckets array
|
|
||||||
*/
|
|
||||||
mapToBuckets(bucketsMap: {[key: string]: number}): SCFacetBucket[] {
|
|
||||||
const buckets: SCFacetBucket[] = [];
|
|
||||||
for (const key in bucketsMap) {
|
|
||||||
if (bucketsMap.hasOwnProperty(key)) {
|
|
||||||
const bucket: SCFacetBucket = {key: key, count: bucketsMap[key]};
|
|
||||||
buckets.push(bucket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buckets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts facets array into a map (for quicker operations with facets)
|
|
||||||
*
|
|
||||||
* @param facets Array of facets
|
|
||||||
*/
|
|
||||||
facetsToMap(facets: SCFacet[]): {[key: string]: {[key: string]: number}} {
|
|
||||||
const facetsMap: {[key: string]: {[key: string]: number}} = {};
|
|
||||||
facets.forEach((facet) => {
|
|
||||||
facetsMap[facet.field] = this.bucketsToMap(facet.buckets);
|
|
||||||
});
|
|
||||||
return facetsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts facets map into an array of facets (as they are provided by backend)
|
|
||||||
*
|
|
||||||
* @param facetsMap A map from facets array
|
|
||||||
*/
|
|
||||||
mapToFacets(facetsMap: {[key: string]: {[key: string]: number}}): SCFacet[] {
|
|
||||||
const facets: SCFacet[] = [];
|
|
||||||
for (const key in facetsMap) {
|
|
||||||
if (facetsMap.hasOwnProperty(key)) {
|
|
||||||
const facet: SCFacet = {buckets: [], field: ''};
|
|
||||||
facet.field = key;
|
|
||||||
facet.buckets = this.mapToBuckets(facetsMap[key]);
|
|
||||||
facets.push(facet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return facets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract facets from data items, optionally combine them with a list of existing facets
|
* Extract facets from data items, optionally combine them with a list of existing facets
|
||||||
*
|
*
|
||||||
@@ -114,12 +74,12 @@ export class DataFacetsProvider {
|
|||||||
if (items.length === 0) {
|
if (items.length === 0) {
|
||||||
if (facets.length === 0) {
|
if (facets.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
}
|
||||||
|
|
||||||
return facets;
|
return facets;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const combinedFacets: SCFacet[] = facets;
|
const combinedFacets: SCFacet[] = facets;
|
||||||
const combinedFacetsMap: {[key: string]: {[key: string]: number}} = this.facetsToMap(combinedFacets);
|
const combinedFacetsMap: {[key: string]: {[key: string]: number; }; } = this.facetsToMap(combinedFacets);
|
||||||
(items as any[]).forEach((item) => {
|
(items as any[]).forEach((item) => {
|
||||||
aggregations.forEach((aggregation) => {
|
aggregations.forEach((aggregation) => {
|
||||||
let fieldValues: string | string[] = item[aggregation.fieldName];
|
let fieldValues: string | string[] = item[aggregation.fieldName];
|
||||||
@@ -142,6 +102,58 @@ export class DataFacetsProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.mapToFacets(combinedFacetsMap);
|
return this.mapToFacets(combinedFacetsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts facets array into a map (for quicker operations with facets)
|
||||||
|
*
|
||||||
|
* @param facets Array of facets
|
||||||
|
*/
|
||||||
|
facetsToMap(facets: SCFacet[]): {[key: string]: {[key: string]: number; }; } {
|
||||||
|
const facetsMap: {[key: string]: {[key: string]: number; }; } = {};
|
||||||
|
facets.forEach((facet) => {
|
||||||
|
facetsMap[facet.field] = this.bucketsToMap(facet.buckets);
|
||||||
|
});
|
||||||
|
|
||||||
|
return facetsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a buckets map into buckets array (as it is inside of a facet)
|
||||||
|
*
|
||||||
|
* @param bucketsMap A map from a buckets array
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
|
mapToBuckets(bucketsMap: {[key: string]: number; }): SCFacetBucket[] {
|
||||||
|
const buckets: SCFacetBucket[] = [];
|
||||||
|
for (const key in bucketsMap) {
|
||||||
|
if (bucketsMap.hasOwnProperty(key)) {
|
||||||
|
const bucket: SCFacetBucket = {key: key, count: bucketsMap[key]};
|
||||||
|
buckets.push(bucket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts facets map into an array of facets (as they are provided by backend)
|
||||||
|
*
|
||||||
|
* @param facetsMap A map from facets array
|
||||||
|
*/
|
||||||
|
mapToFacets(facetsMap: {[key: string]: {[key: string]: number; }; }): SCFacet[] {
|
||||||
|
const facets: SCFacet[] = [];
|
||||||
|
for (const key in facetsMap) {
|
||||||
|
if (facetsMap.hasOwnProperty(key)) {
|
||||||
|
const facet: SCFacet = {buckets: [], field: ''};
|
||||||
|
facet.field = key;
|
||||||
|
facet.buckets = this.mapToBuckets(facetsMap[key]);
|
||||||
|
facets.push(facet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return facets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ const dataRoutes: Routes = [
|
|||||||
{path: 'data-detail/:uid', component: DataDetailComponent},
|
{path: 'data-detail/:uid', component: DataDetailComponent},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
exports: [
|
exports: [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ import {DataRoutingModule} from './data-routing.module';
|
|||||||
import {DataProvider} from './data.provider';
|
import {DataProvider} from './data.provider';
|
||||||
import {DataDetailContentComponent} from './detail/data-detail-content.component';
|
import {DataDetailContentComponent} from './detail/data-detail-content.component';
|
||||||
import {DataDetailComponent} from './detail/data-detail.component';
|
import {DataDetailComponent} from './detail/data-detail.component';
|
||||||
import {OffersDetailComponent} from './elements/offers-detail.component';
|
|
||||||
import {OffersInListComponent} from './elements/offers-in-list.component';
|
|
||||||
import {AddressDetailComponent} from './elements/address-detail.component';
|
import {AddressDetailComponent} from './elements/address-detail.component';
|
||||||
import {LongInlineText} from './elements/long-inline-text.component';
|
import {LongInlineText} from './elements/long-inline-text.component';
|
||||||
|
import {OffersDetailComponent} from './elements/offers-detail.component';
|
||||||
|
import {OffersInListComponent} from './elements/offers-in-list.component';
|
||||||
import {OriginDetailComponent} from './elements/origin-detail.component';
|
import {OriginDetailComponent} from './elements/origin-detail.component';
|
||||||
import {OriginInListComponent} from './elements/origin-in-list.component';
|
import {OriginInListComponent} from './elements/origin-in-list.component';
|
||||||
import {SimpleCardComponent} from './elements/simple-card.component';
|
import {SimpleCardComponent} from './elements/simple-card.component';
|
||||||
|
import {SkeletonListItem} from './elements/skeleton-list-item.component';
|
||||||
|
import {SkeletonSimpleCard} from './elements/skeleton-simple-card.component';
|
||||||
import {DataListItem} from './list/data-list-item.component';
|
import {DataListItem} from './list/data-list-item.component';
|
||||||
import {DataListComponent} from './list/data-list.component';
|
import {DataListComponent} from './list/data-list.component';
|
||||||
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';
|
import {StAppsWebHttpClient} from './stapps-web-http-client.provider';
|
||||||
@@ -60,9 +62,10 @@ import {SemesterDetailContentComponent} from './types/semester/semester-detail-c
|
|||||||
import {SemesterListItem} from './types/semester/semester-list-item.component';
|
import {SemesterListItem} from './types/semester/semester-list-item.component';
|
||||||
import {VideoDetailContentComponent} from './types/video/video-detail-content.component';
|
import {VideoDetailContentComponent} from './types/video/video-detail-content.component';
|
||||||
import {VideoListItem} from './types/video/video-list-item.component';
|
import {VideoListItem} from './types/video/video-list-item.component';
|
||||||
import {SkeletonListItem} from './elements/skeleton-list-item.component';
|
|
||||||
import {SkeletonSimpleCard} from './elements/skeleton-simple-card.component';
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
OffersDetailComponent,
|
OffersDetailComponent,
|
||||||
|
|||||||
@@ -24,41 +24,64 @@ export enum DataScope {
|
|||||||
Remote = 'remote',
|
Remote = 'remote',
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Generated class for the DataProvider provider.
|
* Generated class for the DataProvider provider.
|
||||||
|
*
|
||||||
See https://angular.io/guide/dependency-injection for more info on providers
|
* See https://angular.io/guide/dependency-injection for more info on providers
|
||||||
and Angular DI.
|
* and Angular DI.
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DataProvider {
|
export class DataProvider {
|
||||||
private _storagePrefix: string = 'stapps.data';
|
/**
|
||||||
// @TODO: get backendUrl and appVersion and storagePrefix from config (module)
|
* TODO
|
||||||
appVersion: string = '1.0.6';
|
*/
|
||||||
backendUrl: string = 'http://localhost:3000';
|
private _storagePrefix = 'stapps.data';
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @TODO: get backendUrl and appVersion and storagePrefix from config (module)
|
||||||
|
*/
|
||||||
|
appVersion = '1.0.6';
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
backendUrl = 'http://localhost:3000';
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
client: Client;
|
client: Client;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
storageProvider: StorageProvider;
|
storageProvider: StorageProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* @param stAppsWebHttpClient TODO
|
||||||
|
* @param storageProvider TODO
|
||||||
|
*/
|
||||||
constructor(stAppsWebHttpClient: StAppsWebHttpClient, storageProvider: StorageProvider) {
|
constructor(stAppsWebHttpClient: StAppsWebHttpClient, storageProvider: StorageProvider) {
|
||||||
this.client = new Client(stAppsWebHttpClient, this.backendUrl, this.appVersion);
|
this.client = new Client(stAppsWebHttpClient, this.backendUrl, this.appVersion);
|
||||||
this.storageProvider = storageProvider;
|
this.storageProvider = storageProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
get storagePrefix(): string {
|
/**
|
||||||
return this._storagePrefix;
|
* Delete a data item
|
||||||
}
|
*
|
||||||
|
* @param uid Unique identifier of the saved data item
|
||||||
set storagePrefix(storagePrefix) {
|
*/
|
||||||
this._storagePrefix = storagePrefix;
|
async delete(uid: string): Promise<void> {
|
||||||
|
return this.storageProvider.delete(this.getDataKey(uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides key for storing data into the local database
|
* Delete all the previously saved data items
|
||||||
*
|
|
||||||
* @param uid Unique identifier of a resource
|
|
||||||
*/
|
*/
|
||||||
getDataKey(uid: string): string {
|
async deleteAll(): Promise<void> {
|
||||||
return `${this.storagePrefix}.${uid}`;
|
const keys = Array.from((await this.getAll()).keys());
|
||||||
|
|
||||||
|
return this.storageProvider.delete(...keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +114,7 @@ export class DataProvider {
|
|||||||
const map: Map<DataScope, SCThings | SCSaveableThing<SCThings>> = new Map();
|
const map: Map<DataScope, SCThings | SCSaveableThing<SCThings>> = new Map();
|
||||||
map.set(DataScope.Local, await this.get(uid, DataScope.Local));
|
map.set(DataScope.Local, await this.get(uid, DataScope.Local));
|
||||||
map.set(DataScope.Remote, await this.get(uid, DataScope.Remote));
|
map.set(DataScope.Remote, await this.get(uid, DataScope.Remote));
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +125,24 @@ export class DataProvider {
|
|||||||
return this.storageProvider.search<SCSaveableThing<SCThings>>(this.storagePrefix);
|
return this.storageProvider.search<SCSaveableThing<SCThings>>(this.storagePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides key for storing data into the local database
|
||||||
|
*
|
||||||
|
* @param uid Unique identifier of a resource
|
||||||
|
*/
|
||||||
|
getDataKey(uid: string): string {
|
||||||
|
return `${this.storagePrefix}.${uid}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides information if something with an UID is saved as a data item
|
||||||
|
*
|
||||||
|
* @param uid Unique identifier of the saved data item
|
||||||
|
*/
|
||||||
|
async isSaved(uid: string): Promise<boolean> {
|
||||||
|
return this.storageProvider.has(this.getDataKey(uid));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a data item
|
* Save a data item
|
||||||
*
|
*
|
||||||
@@ -118,25 +160,9 @@ export class DataProvider {
|
|||||||
type: (typeof type === 'undefined') ? item.type : type,
|
type: (typeof type === 'undefined') ? item.type : type,
|
||||||
uid: item.uid,
|
uid: item.uid,
|
||||||
};
|
};
|
||||||
|
|
||||||
// @TODO: Implementation for saving item into the backend (user's account)
|
// @TODO: Implementation for saving item into the backend (user's account)
|
||||||
return (await this.storageProvider.put<SCSaveableThing<SCThings>>(this.getDataKey(item.uid), saveableItem));
|
return ( this.storageProvider.put<SCSaveableThing<SCThings>>(this.getDataKey(item.uid), saveableItem));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a data item
|
|
||||||
*
|
|
||||||
* @param uid Unique identifier of the saved data item
|
|
||||||
*/
|
|
||||||
async delete(uid: string): Promise<void> {
|
|
||||||
return this.storageProvider.delete(this.getDataKey(uid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete all the previously saved data items
|
|
||||||
*/
|
|
||||||
async deleteAll(): Promise<void> {
|
|
||||||
const keys = Array.from((await this.getAll()).keys());
|
|
||||||
return this.storageProvider.delete(...keys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,15 +171,20 @@ export class DataProvider {
|
|||||||
* @param query - query to send to the backend
|
* @param query - query to send to the backend
|
||||||
*/
|
*/
|
||||||
async search(query: SCSearchQuery): Promise<SCSearchResponse> {
|
async search(query: SCSearchQuery): Promise<SCSearchResponse> {
|
||||||
return (await this.client.search(query));
|
return (this.client.search(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides information if something with an UID is saved as a data item
|
* TODO
|
||||||
*
|
|
||||||
* @param uid Unique identifier of the saved data item
|
|
||||||
*/
|
*/
|
||||||
async isSaved(uid: string): Promise<boolean> {
|
get storagePrefix(): string {
|
||||||
return this.storageProvider.has(this.getDataKey(uid));
|
return this._storagePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
set storagePrefix(storagePrefix) {
|
||||||
|
this._storagePrefix = storagePrefix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCThings} from '@openstapps/core';
|
import {SCThings} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-data-detail-content',
|
selector: 'stapps-data-detail-content',
|
||||||
templateUrl: 'data-detail-content.html',
|
templateUrl: 'data-detail-content.html',
|
||||||
})
|
})
|
||||||
export class DataDetailContentComponent {
|
export class DataDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCThings;
|
@Input() item: SCThings;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,17 +19,35 @@ import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
|||||||
import {SCLanguageCode, SCThing, SCUuid} from '@openstapps/core';
|
import {SCLanguageCode, SCThing, SCUuid} from '@openstapps/core';
|
||||||
import {DataProvider, DataScope} from '../data.provider';
|
import {DataProvider, DataScope} from '../data.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-data-detail',
|
selector: 'stapps-data-detail',
|
||||||
styleUrls: ['data-detail.scss'],
|
styleUrls: ['data-detail.scss'],
|
||||||
templateUrl: 'data-detail.html',
|
templateUrl: 'data-detail.html',
|
||||||
})
|
})
|
||||||
export class DataDetailComponent {
|
export class DataDetailComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
dataProvider: DataProvider;
|
dataProvider: DataProvider;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
item: SCThing;
|
item: SCThing;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
language: SCLanguageCode;
|
language: SCLanguageCode;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, dataProvider: DataProvider, translateService: TranslateService) {
|
/**
|
||||||
|
*
|
||||||
|
* @param route TODO
|
||||||
|
* @param dataProvider TODO
|
||||||
|
* @param translateService TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly route: ActivatedRoute, dataProvider: DataProvider, translateService: TranslateService) {
|
||||||
this.dataProvider = dataProvider;
|
this.dataProvider = dataProvider;
|
||||||
this.language = translateService.currentLang as SCLanguageCode;
|
this.language = translateService.currentLang as SCLanguageCode;
|
||||||
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||||
@@ -43,11 +61,16 @@ export class DataDetailComponent {
|
|||||||
* @param uid Unique identifier of a thing
|
* @param uid Unique identifier of a thing
|
||||||
*/
|
*/
|
||||||
async getItem(uid: SCUuid): Promise<void> {
|
async getItem(uid: SCUuid): Promise<void> {
|
||||||
this.dataProvider.get(uid, DataScope.Remote).then((data) => {
|
await this.dataProvider.get(uid, DataScope.Remote)
|
||||||
|
.then((data) => {
|
||||||
this.item = data;
|
this.item = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.getItem(this.route.snapshot.paramMap.get('uid') || '');
|
this.getItem(this.route.snapshot.paramMap.get('uid') || '');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCPostalAddress} from '@openstapps/core';
|
import {SCPostalAddress} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-address-detail',
|
selector: 'stapps-address-detail',
|
||||||
templateUrl: 'address-detail.html',
|
templateUrl: 'address-detail.html',
|
||||||
})
|
})
|
||||||
export class AddressDetailComponent {
|
export class AddressDetailComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() address: SCPostalAddress;
|
@Input() address: SCPostalAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,20 @@
|
|||||||
*/
|
*/
|
||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-long-inline-text',
|
selector: 'stapps-long-inline-text',
|
||||||
templateUrl: 'long-inline-text.html',
|
templateUrl: 'long-inline-text.html',
|
||||||
})
|
})
|
||||||
export class LongInlineText {
|
export class LongInlineText {
|
||||||
@Input() text: string;
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() size: number;
|
@Input() size: number;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
@Input() text: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,20 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
|
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-offers-detail',
|
selector: 'stapps-offers-detail',
|
||||||
templateUrl: 'offers-detail.html',
|
templateUrl: 'offers-detail.html',
|
||||||
})
|
})
|
||||||
export class OffersDetailComponent {
|
export class OffersDetailComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>;
|
@Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
|
import {SCAcademicPriceGroup, SCThingThatCanBeOfferedOffer} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-offers-in-list',
|
selector: 'stapps-offers-in-list',
|
||||||
templateUrl: 'offers-in-list.html',
|
templateUrl: 'offers-in-list.html',
|
||||||
})
|
})
|
||||||
export class OffersInListComponent {
|
export class OffersInListComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>;
|
@Input() offers: Array<SCThingThatCanBeOfferedOffer<SCAcademicPriceGroup>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCThingOrigin} from '@openstapps/core';
|
import {SCThingOrigin} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-origin-detail',
|
selector: 'stapps-origin-detail',
|
||||||
templateUrl: 'origin-detail.html',
|
templateUrl: 'origin-detail.html',
|
||||||
})
|
})
|
||||||
export class OriginDetailComponent {
|
export class OriginDetailComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() origin: SCThingOrigin;
|
@Input() origin: SCThingOrigin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,16 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {SCThingOrigin} from '@openstapps/core';
|
import {SCThingOrigin} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-origin-in-list',
|
selector: 'stapps-origin-in-list',
|
||||||
templateUrl: 'origin-in-list.html',
|
templateUrl: 'origin-in-list.html',
|
||||||
})
|
})
|
||||||
export class OriginInListComponent {
|
export class OriginInListComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() origin: SCThingOrigin;
|
@Input() origin: SCThingOrigin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,41 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {isThing, SCThing} from '@openstapps/core';
|
import {isThing, SCThing} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-simple-card',
|
selector: 'stapps-simple-card',
|
||||||
templateUrl: 'simple-card.html',
|
templateUrl: 'simple-card.html',
|
||||||
})
|
})
|
||||||
export class SimpleCardComponent {
|
export class SimpleCardComponent {
|
||||||
areThings: boolean = false;
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
areThings = false;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() content: string | string[] | SCThing[];
|
@Input() content: string | string[] | SCThing[];
|
||||||
@Input() isMarkdown: boolean = false;
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
@Input() isMarkdown = false;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() title: string;
|
@Input() title: string;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
isString(data: any): data is string {
|
isString(data: any): data is string {
|
||||||
return typeof data === 'string';
|
return typeof data === 'string';
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
isThing(something: any): something is SCThing {
|
isThing(something: any): something is SCThing {
|
||||||
return isThing(something);
|
return isThing(something);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-skeleton-list-item',
|
selector: 'stapps-skeleton-list-item',
|
||||||
templateUrl: 'skeleton-list-item.html',
|
templateUrl: 'skeleton-list-item.html',
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
*/
|
*/
|
||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-skeleton-simple-card',
|
selector: 'stapps-skeleton-simple-card',
|
||||||
templateUrl: 'skeleton-simple-card.html',
|
templateUrl: 'skeleton-simple-card.html',
|
||||||
|
|||||||
@@ -15,19 +15,32 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {SCThings} from '@openstapps/core';
|
import {SCThings} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-data-list-item',
|
selector: 'stapps-data-list-item',
|
||||||
styleUrls: ['data-list-item.scss'],
|
styleUrls: ['data-list-item.scss'],
|
||||||
templateUrl: 'data-list-item.html',
|
templateUrl: 'data-list-item.html',
|
||||||
})
|
})
|
||||||
export class DataListItem implements OnInit {
|
export class DataListItem implements OnInit {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCThings;
|
@Input() item: SCThings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
// noop
|
// noop
|
||||||
// this.item is not available yet
|
// this.item is not available yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// noop
|
// noop
|
||||||
// this.item is available now - the template is loaded and compiled
|
// this.item is available now - the template is loaded and compiled
|
||||||
|
|||||||
@@ -19,24 +19,58 @@ import {Subject} from 'rxjs';
|
|||||||
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
|
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
|
||||||
import {DataProvider} from '../data.provider';
|
import {DataProvider} from '../data.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-data-list',
|
selector: 'stapps-data-list',
|
||||||
templateUrl: 'data-list.html',
|
templateUrl: 'data-list.html',
|
||||||
})
|
})
|
||||||
export class DataListComponent {
|
export class DataListComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
dataProvider: DataProvider;
|
dataProvider: DataProvider;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
from = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
items: SCThing[];
|
items: SCThing[];
|
||||||
selectedItem: any;
|
|
||||||
loaded: boolean = false;
|
|
||||||
|
|
||||||
size: number = 30;
|
/**
|
||||||
from: number = 0;
|
* TODO
|
||||||
|
*/
|
||||||
|
loaded = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
query: string;
|
query: string;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
queryChanged: Subject<string> = new Subject<string>();
|
queryChanged: Subject<string> = new Subject<string>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
selectedItem: any;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
size = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param alertController TODO
|
||||||
|
* @param dataProvider TODO
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private alertController: AlertController,
|
private readonly alertController: AlertController,
|
||||||
dataProvider: DataProvider,
|
dataProvider: DataProvider,
|
||||||
) {
|
) {
|
||||||
this.dataProvider = dataProvider;
|
this.dataProvider = dataProvider;
|
||||||
@@ -52,12 +86,16 @@ export class DataListComponent {
|
|||||||
this.fetchItems();
|
this.fetchItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
private async fetchItems(): Promise<any> {
|
private async fetchItems(): Promise<any> {
|
||||||
return this.dataProvider.search({
|
return this.dataProvider.search({
|
||||||
from: this.from,
|
from: this.from,
|
||||||
query: this.query,
|
query: this.query,
|
||||||
size: this.size,
|
size: this.size,
|
||||||
} as any).then((result) => {
|
} as any)
|
||||||
|
.then((result) => {
|
||||||
this.items = result.data;
|
this.items = result.data;
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
}, async (err) => {
|
}, async (err) => {
|
||||||
@@ -71,12 +109,18 @@ export class DataListComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
async loadMore(event: any): Promise<void> {
|
async loadMore(event: any): Promise<void> {
|
||||||
this.from += this.size;
|
this.from += this.size;
|
||||||
await this.fetchItems();
|
await this.fetchItems();
|
||||||
event.target.complete();
|
event.target.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
search(query: string) {
|
search(query: string) {
|
||||||
this.queryChanged.next(query);
|
this.queryChanged.next(query);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -14,15 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
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} from '@openstapps/api/lib/httpClientInterface';
|
import {HttpClientInterface, HttpClientRequest} from '@openstapps/api/lib/http-client-interface';
|
||||||
import {HttpClientRequest} from '@openstapps/api/lib/httpClientInterface';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HttpClient that is based on angular's HttpClient (@TODO: move it to provider or independent package)
|
* HttpClient that is based on angular's HttpClient (@TODO: move it to provider or independent package)
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StAppsWebHttpClient implements HttpClientInterface {
|
export class StAppsWebHttpClient implements HttpClientInterface {
|
||||||
constructor(private http: HttpClient) {
|
/**
|
||||||
|
*
|
||||||
|
* @param http TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly http: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +36,13 @@ export class StAppsWebHttpClient implements HttpClientInterface {
|
|||||||
requestConfig: HttpClientRequest,
|
requestConfig: HttpClientRequest,
|
||||||
): Promise<Response<TYPE_OF_BODY>> {
|
): Promise<Response<TYPE_OF_BODY>> {
|
||||||
const options: {
|
const options: {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
observe: 'response';
|
observe: 'response';
|
||||||
} = {
|
} = {
|
||||||
body: {},
|
body: {},
|
||||||
@@ -53,6 +62,7 @@ export class StAppsWebHttpClient implements HttpClientInterface {
|
|||||||
const response: HttpResponse<TYPE_OF_BODY> = await this.http.request<TYPE_OF_BODY>(
|
const response: HttpResponse<TYPE_OF_BODY> = await this.http.request<TYPE_OF_BODY>(
|
||||||
requestConfig.method || 'GET', requestConfig.url.toString(), options)
|
requestConfig.method || 'GET', requestConfig.url.toString(), options)
|
||||||
.toPromise();
|
.toPromise();
|
||||||
|
|
||||||
return Object.assign(response, {statusCode: response.status, body: response.body || {}});
|
return Object.assign(response, {statusCode: response.status, body: response.body || {}});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw Error(err);
|
throw Error(err);
|
||||||
@@ -64,6 +74,12 @@ export class StAppsWebHttpClient implements HttpClientInterface {
|
|||||||
* Response with generic for the type of body that is returned from the request
|
* Response with generic for the type of body that is returned from the request
|
||||||
*/
|
*/
|
||||||
export interface Response<TYPE_OF_BODY> extends HttpResponse<TYPE_OF_BODY> {
|
export interface Response<TYPE_OF_BODY> extends HttpResponse<TYPE_OF_BODY> {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
body: TYPE_OF_BODY;
|
body: TYPE_OF_BODY;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCArticle, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCArticle, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-article-detail-content',
|
selector: 'stapps-article-detail-content',
|
||||||
templateUrl: 'article-detail-content.html',
|
templateUrl: 'article-detail-content.html',
|
||||||
})
|
})
|
||||||
export class ArticleDetailContentComponent {
|
export class ArticleDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCArticle;
|
@Input() item: SCArticle;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCArticle} from '@openstapps/core';
|
import {SCArticle} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-article-list-item',
|
selector: 'stapps-article-list-item',
|
||||||
templateUrl: 'article-list-item.html',
|
templateUrl: 'article-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class ArticleListItem extends DataListItem {
|
export class ArticleListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCArticle;
|
@Input() item: SCArticle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCCatalog, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCCatalog, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-catalog-detail-content',
|
selector: 'stapps-catalog-detail-content',
|
||||||
templateUrl: 'catalog-detail-content.html',
|
templateUrl: 'catalog-detail-content.html',
|
||||||
})
|
})
|
||||||
export class CatalogDetailContentComponent {
|
export class CatalogDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCCatalog;
|
@Input() item: SCCatalog;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCCatalog} from '@openstapps/core';
|
import {SCCatalog} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-catalog-list-item',
|
selector: 'stapps-catalog-list-item',
|
||||||
templateUrl: 'catalog-list-item.html',
|
templateUrl: 'catalog-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class CatalogListItem extends DataListItem {
|
export class CatalogListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCCatalog;
|
@Input() item: SCCatalog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCDateSeries, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCDateSeries, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-date-series-detail-content',
|
selector: 'stapps-date-series-detail-content',
|
||||||
templateUrl: 'date-series-detail-content.html',
|
templateUrl: 'date-series-detail-content.html',
|
||||||
})
|
})
|
||||||
export class DateSeriesDetailContentComponent {
|
export class DateSeriesDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCDateSeries;
|
@Input() item: SCDateSeries;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCDateSeries} from '@openstapps/core';
|
import {SCDateSeries} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-date-series-list-item',
|
selector: 'stapps-date-series-list-item',
|
||||||
templateUrl: 'date-series-list-item.html',
|
templateUrl: 'date-series-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class DateSeriesListItem extends DataListItem {
|
export class DateSeriesListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCDateSeries;
|
@Input() item: SCDateSeries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCDish, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCDish, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-dish-detail-content',
|
selector: 'stapps-dish-detail-content',
|
||||||
templateUrl: 'dish-detail-content.html',
|
templateUrl: 'dish-detail-content.html',
|
||||||
})
|
})
|
||||||
export class DishDetailContentComponent {
|
export class DishDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCDish;
|
@Input() item: SCDish;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -17,12 +17,18 @@ import {SCDish} from '@openstapps/core';
|
|||||||
// import {SettingsProvider} from '../../../settings/settings.provider';
|
// import {SettingsProvider} from '../../../settings/settings.provider';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-dish-list-item',
|
selector: 'stapps-dish-list-item',
|
||||||
templateUrl: 'dish-list-item.html',
|
templateUrl: 'dish-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class DishListItem extends DataListItem {
|
export class DishListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCDish;
|
@Input() item: SCDish;
|
||||||
// settingsProvider: SettingsProvider;
|
// settingsProvider: SettingsProvider;
|
||||||
|
|
||||||
@@ -31,6 +37,10 @@ export class DishListItem extends DataListItem {
|
|||||||
// this.settingsProvider = settingsProvider;
|
// this.settingsProvider = settingsProvider;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation...
|
// TODO: translation...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCAcademicEvent, SCSportCourse, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCAcademicEvent, SCSportCourse, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-event-detail-content',
|
selector: 'stapps-event-detail-content',
|
||||||
templateUrl: 'event-detail-content.html',
|
templateUrl: 'event-detail-content.html',
|
||||||
})
|
})
|
||||||
export class EventDetailContentComponent {
|
export class EventDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCAcademicEvent | SCSportCourse;
|
@Input() item: SCAcademicEvent | SCSportCourse;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,23 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCAcademicEvent, SCSportCourse} from '@openstapps/core';
|
import {SCAcademicEvent, SCSportCourse} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-event-list-item',
|
selector: 'stapps-event-list-item',
|
||||||
templateUrl: 'event-list-item.html',
|
templateUrl: 'event-list-item.html',
|
||||||
})
|
})
|
||||||
export class EventListItemComponent extends DataListItem {
|
export class EventListItemComponent extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCAcademicEvent | SCSportCourse;
|
@Input() item: SCAcademicEvent | SCSportCourse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCFavorite, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCFavorite, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-favorite-detail-content',
|
selector: 'stapps-favorite-detail-content',
|
||||||
templateUrl: 'favorite-detail-content.html',
|
templateUrl: 'favorite-detail-content.html',
|
||||||
})
|
})
|
||||||
export class FavoriteDetailContentComponent {
|
export class FavoriteDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCFavorite;
|
@Input() item: SCFavorite;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCFavorite} from '@openstapps/core';
|
import {SCFavorite} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-favorite-list-item',
|
selector: 'stapps-favorite-list-item',
|
||||||
templateUrl: 'favorite-list-item.html',
|
templateUrl: 'favorite-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class FavoriteListItem extends DataListItem {
|
export class FavoriteListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCFavorite;
|
@Input() item: SCFavorite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,34 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCMessage, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCMessage, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-message-detail-content',
|
selector: 'stapps-message-detail-content',
|
||||||
templateUrl: 'message-detail-content.html',
|
templateUrl: 'message-detail-content.html',
|
||||||
})
|
})
|
||||||
export class MessageDetailContentComponent {
|
export class MessageDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCMessage;
|
@Input() item: SCMessage;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<stapps-simple-card [title]="'Content'" [content]="item.message"></stapps-simple-card>
|
<stapps-simple-card [title]="'Content'" [content]="item.messageBody"></stapps-simple-card>
|
||||||
<stapps-simple-card [title]="'Audiences'" [content]="item.audiences"></stapps-simple-card>
|
<stapps-simple-card [title]="'Audiences'" [content]="item.audiences"></stapps-simple-card>
|
||||||
<stapps-simple-card *ngIf="item.datePublished" [title]="'Published'" [content]="item.datePublished | amDateFormat:'DD. MMM YYYY'"></stapps-simple-card>
|
<stapps-simple-card *ngIf="item.datePublished" [title]="'Published'" [content]="item.datePublished | amDateFormat:'DD. MMM YYYY'"></stapps-simple-card>
|
||||||
<stapps-simple-card *ngIf="item.authors" [title]="'Author(s)'" [content]="item.authors"></stapps-simple-card>
|
<stapps-simple-card *ngIf="item.authors" [title]="'Author(s)'" [content]="item.authors"></stapps-simple-card>
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCMessage} from '@openstapps/core';
|
import {SCMessage} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-message-list-item',
|
selector: 'stapps-message-list-item',
|
||||||
templateUrl: 'message-list-item.html',
|
templateUrl: 'message-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class MessageListItem extends DataListItem {
|
export class MessageListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCMessage;
|
@Input() item: SCMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<h2 class="name">{{item.name}}</h2>
|
<h2 class="name">{{item.name}}</h2>
|
||||||
<p *ngIf="item.message">
|
<p *ngIf="item.messageBody">
|
||||||
<stapps-long-inline-text [text]="item.message" [size]="80"></stapps-long-inline-text>
|
<stapps-long-inline-text [text]="item.messageBody" [size]="80"></stapps-long-inline-text>
|
||||||
</p>
|
</p>
|
||||||
<ion-note>{{item.type}}</ion-note>
|
<ion-note>{{item.type}}</ion-note>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
|
|||||||
@@ -16,16 +16,35 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCOrganization, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCOrganization, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-organization-detail-content',
|
selector: 'stapps-organization-detail-content',
|
||||||
templateUrl: 'organization-detail-content.html',
|
templateUrl: 'organization-detail-content.html',
|
||||||
})
|
})
|
||||||
export class OrganizationDetailContentComponent {
|
export class OrganizationDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCOrganization;
|
@Input() item: SCOrganization;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCOrganization} from '@openstapps/core';
|
import {SCOrganization} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-organization-list-item',
|
selector: 'stapps-organization-list-item',
|
||||||
templateUrl: 'organization-list-item.html',
|
templateUrl: 'organization-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class OrganizationListItem extends DataListItem {
|
export class OrganizationListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCOrganization;
|
@Input() item: SCOrganization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,35 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCPerson, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCPerson, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-person-detail-content',
|
selector: 'stapps-person-detail-content',
|
||||||
templateUrl: 'person-detail-content.html',
|
templateUrl: 'person-detail-content.html',
|
||||||
})
|
})
|
||||||
export class PersonDetailContentComponent {
|
export class PersonDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCPerson;
|
@Input() item: SCPerson;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCPerson} from '@openstapps/core';
|
import {SCPerson} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-person-list-item',
|
selector: 'stapps-person-list-item',
|
||||||
templateUrl: 'person-list-item.html',
|
templateUrl: 'person-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class PersonListItem extends DataListItem {
|
export class PersonListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCPerson;
|
@Input() item: SCPerson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,35 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-place-detail-content',
|
selector: 'stapps-place-detail-content',
|
||||||
templateUrl: 'place-detail-content.html',
|
templateUrl: 'place-detail-content.html',
|
||||||
})
|
})
|
||||||
export class PlaceDetailContentComponent {
|
export class PlaceDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
|
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,24 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom} from '@openstapps/core';
|
import {SCBuilding, SCFloor, SCPointOfInterest, SCRoom} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-place-list-item',
|
selector: 'stapps-place-list-item',
|
||||||
templateUrl: 'place-list-item.html',
|
templateUrl: 'place-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class PlaceListItem extends DataListItem {
|
export class PlaceListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
|
@Input() item: SCBuilding | SCRoom | SCPointOfInterest | SCFloor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,35 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCSemester, SCThing, SCTranslations} from '@openstapps/core';
|
import {SCSemester, SCThing, SCTranslations} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-semester-detail-content',
|
selector: 'stapps-semester-detail-content',
|
||||||
templateUrl: 'semester-detail-content.html',
|
templateUrl: 'semester-detail-content.html',
|
||||||
})
|
})
|
||||||
export class SemesterDetailContentComponent {
|
export class SemesterDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCSemester;
|
@Input() item: SCSemester;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,23 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCSemester} from '@openstapps/core';
|
import {SCSemester} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-semester-list-item',
|
selector: 'stapps-semester-list-item',
|
||||||
templateUrl: 'semester-list-item.html',
|
templateUrl: 'semester-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class SemesterListItem extends DataListItem {
|
export class SemesterListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCSemester;
|
@Input() item: SCSemester;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,35 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCThing, SCTranslations, SCVideo} from '@openstapps/core';
|
import {SCThing, SCTranslations, SCVideo} from '@openstapps/core';
|
||||||
import {SCThingTranslator} from '@openstapps/core';
|
import {SCThingTranslator} from '@openstapps/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-video-detail-content',
|
selector: 'stapps-video-detail-content',
|
||||||
templateUrl: 'video-detail-content.html',
|
templateUrl: 'video-detail-content.html',
|
||||||
})
|
})
|
||||||
export class VideoDetailContentComponent {
|
export class VideoDetailContentComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCVideo;
|
@Input() item: SCVideo;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() language: keyof SCTranslations<SCThing>;
|
@Input() language: keyof SCTranslations<SCThing>;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,23 @@ import {Component, Input} from '@angular/core';
|
|||||||
import {SCVideo} from '@openstapps/core';
|
import {SCVideo} from '@openstapps/core';
|
||||||
import {DataListItem} from '../../list/data-list-item.component';
|
import {DataListItem} from '../../list/data-list-item.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-video-list-item',
|
selector: 'stapps-video-list-item',
|
||||||
templateUrl: 'video-list-item.html',
|
templateUrl: 'video-list-item.html',
|
||||||
})
|
})
|
||||||
|
|
||||||
export class VideoListItem extends DataListItem {
|
export class VideoListItem extends DataListItem {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() item: SCVideo;
|
@Input() item: SCVideo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// TODO: translation
|
// TODO: translation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -18,20 +18,23 @@ import {RouterModule} from '@angular/router';
|
|||||||
import {IonicModule} from '@ionic/angular';
|
import {IonicModule} from '@ionic/angular';
|
||||||
import {NavigationComponent} from './navigation/navigation.component';
|
import {NavigationComponent} from './navigation/navigation.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
NavigationComponent,
|
NavigationComponent,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
NavigationComponent
|
NavigationComponent,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
NavigationComponent
|
NavigationComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
IonicModule.forRoot(),
|
IonicModule.forRoot(),
|
||||||
CommonModule,
|
CommonModule,
|
||||||
RouterModule
|
RouterModule,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class MenuModule {}
|
export class MenuModule {}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -26,6 +26,9 @@ import {Component} from '@angular/core';
|
|||||||
templateUrl: 'navigation.html',
|
templateUrl: 'navigation.html',
|
||||||
})
|
})
|
||||||
export class NavigationComponent {
|
export class NavigationComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
public pages = [
|
public pages = [
|
||||||
{title: 'Search', url: '/search', icon: 'search'},
|
{title: 'Search', url: '/search', icon: 'search'},
|
||||||
{title: 'Settings', url: '/settings', icon: 'settings'},
|
{title: 'Settings', url: '/settings', icon: 'settings'},
|
||||||
@@ -35,6 +38,10 @@ export class NavigationComponent {
|
|||||||
// Nothing yet.
|
// Nothing yet.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
ionViewDidLoad() {
|
ionViewDidLoad() {
|
||||||
// console.log('ionViewDidLoad MenuPage');
|
// console.log('ionViewDidLoad MenuPage');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,34 +17,56 @@ import {AlertController} from '@ionic/angular';
|
|||||||
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
||||||
import {
|
import {
|
||||||
SCSetting,
|
SCSetting,
|
||||||
|
SCSettingValue,
|
||||||
|
SCSettingValues,
|
||||||
SCThingTranslator,
|
SCThingTranslator,
|
||||||
SCTranslations,
|
SCTranslations,
|
||||||
} from '@openstapps/core';
|
} from '@openstapps/core';
|
||||||
import {Logger} from '@openstapps/logger';
|
|
||||||
import {SettingsProvider} from '../settings.provider';
|
import {SettingsProvider} from '../settings.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-settings-item',
|
selector: 'stapps-settings-item',
|
||||||
templateUrl: 'settings-item.html',
|
templateUrl: 'settings-item.html',
|
||||||
})
|
})
|
||||||
export class SettingsItemComponent {
|
export class SettingsItemComponent {
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
isVisible = true;
|
isVisible = true;
|
||||||
// limit to languages that are available in StApps Core
|
/**
|
||||||
|
* TODO
|
||||||
|
*
|
||||||
|
* limit to languages that are available in StApps Core
|
||||||
|
*/
|
||||||
language: keyof SCTranslations<any>;
|
language: keyof SCTranslations<any>;
|
||||||
logger = new Logger();
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Input() setting: SCSetting;
|
@Input() setting: SCSetting;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
constructor(private alertCtrl: AlertController,
|
/**
|
||||||
private translateService: TranslateService,
|
*
|
||||||
private settingsProvider: SettingsProvider) {
|
* @param alertCtrl TODO
|
||||||
|
* @param translateService TODO
|
||||||
|
* @param settingsProvider TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly alertCtrl: AlertController,
|
||||||
|
private readonly translateService: TranslateService,
|
||||||
|
private readonly settingsProvider: SettingsProvider) {
|
||||||
this.language = translateService.currentLang as keyof SCTranslations<any>;
|
this.language = translateService.currentLang as keyof SCTranslations<any>;
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
|
|
||||||
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||||
this.isVisible = false;
|
this.isVisible = false;
|
||||||
this.language = event.lang as keyof SCTranslations<any>;
|
this.language = event.lang as keyof SCTranslations<any>;
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
// TODO: Issue #53 check workaround for selected 'select option' not updating translation
|
// TODO: Issue #53 check workaround for selected 'select option' not updating translation
|
||||||
setTimeout(() => this.isVisible = true);
|
setTimeout(() => this.isVisible = true);
|
||||||
});
|
});
|
||||||
@@ -58,7 +80,7 @@ export class SettingsItemComponent {
|
|||||||
const permissionGranted = await this.settingsProvider.checkGeoLocationPermission();
|
const permissionGranted = await this.settingsProvider.checkGeoLocationPermission();
|
||||||
if (!permissionGranted) {
|
if (!permissionGranted) {
|
||||||
// revert setting value
|
// revert setting value
|
||||||
this.setting.input.value = false;
|
this.setting.value = false;
|
||||||
await this.presentGeoLocationAlert();
|
await this.presentGeoLocationAlert();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,8 +89,10 @@ export class SettingsItemComponent {
|
|||||||
* Shows alert with error message on denied user permission or disabled location services
|
* Shows alert with error message on denied user permission or disabled location services
|
||||||
*/
|
*/
|
||||||
private async presentGeoLocationAlert() {
|
private async presentGeoLocationAlert() {
|
||||||
const title = await this.translateService.get('settings.geoLocation.permission_denied_title').toPromise();
|
const title = await this.translateService.get('settings.geoLocation.permission_denied_title')
|
||||||
const message = await this.translateService.get('settings.geoLocation.permission_denied_message').toPromise();
|
.toPromise();
|
||||||
|
const message = await this.translateService.get('settings.geoLocation.permission_denied_message')
|
||||||
|
.toPromise();
|
||||||
await this.presentAlert(title, message);
|
await this.presentAlert(title, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,29 +115,34 @@ export class SettingsItemComponent {
|
|||||||
* Handles value changes of the setting
|
* Handles value changes of the setting
|
||||||
*/
|
*/
|
||||||
async settingChanged(): Promise<void> {
|
async settingChanged(): Promise<void> {
|
||||||
if (typeof this.setting.input.value !== 'undefined'
|
if (typeof this.setting.value !== 'undefined'
|
||||||
&& SettingsProvider.validateValue(this.setting, this.setting.input.value)) {
|
&& SettingsProvider.validateValue(this.setting, this.setting.value)) {
|
||||||
// handle general settings, with special actions
|
// handle general settings, with special actions
|
||||||
switch (this.setting.name) {
|
switch (this.setting.name) {
|
||||||
case 'language':
|
case 'language':
|
||||||
this.translateService.use(this.setting.input.value.toString());
|
this.translateService.use(this.setting.value.toString());
|
||||||
break;
|
break;
|
||||||
case 'geoLocation':
|
case 'geoLocation':
|
||||||
if (this.setting.input.value) {
|
if (this.setting.value) {
|
||||||
await this.checkGeoLocationPermission();
|
await this.checkGeoLocationPermission();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
await this.settingsProvider
|
await this.settingsProvider
|
||||||
.setSettingValue(this.setting.categories[0], this.setting.name, this.setting.input.value);
|
.setSettingValue(this.setting.categories[0], this.setting.name, this.setting.value);
|
||||||
} else {
|
} else {
|
||||||
// reset setting
|
// reset setting
|
||||||
this.setting.input.value =
|
this.setting.value =
|
||||||
await this.settingsProvider.getValue(this.setting.categories[0], this.setting.name);
|
await this.settingsProvider
|
||||||
|
.getValue(this.setting.categories[0], this.setting.name) as (SCSettingValue | SCSettingValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
|
// tslint:disable-next-line:prefer-function-over-method
|
||||||
typeOf(val: any) {
|
typeOf(val: any) {
|
||||||
return typeof (val);
|
return typeof (val);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,27 +5,27 @@
|
|||||||
<ion-card-content>
|
<ion-card-content>
|
||||||
<ion-note>{{ translator.translate(setting).description() }}</ion-note>
|
<ion-note>{{ translator.translate(setting).description() }}</ion-note>
|
||||||
|
|
||||||
<div [ngSwitch]="setting.input.inputType" *ngIf="isVisible" >
|
<div [ngSwitch]="setting.inputType" *ngIf="isVisible" >
|
||||||
<ion-item *ngSwitchCase="'number'">
|
<ion-item *ngSwitchCase="'number'">
|
||||||
<ion-label></ion-label>
|
<ion-label></ion-label>
|
||||||
<ion-input type='number' [(ngModel)]="setting.input.value" value={{setting.input.value}} (ionChange)="settingChanged()"></ion-input>
|
<ion-input type='number' [(ngModel)]="setting.value" value={{setting.value}} (ionChange)="settingChanged()"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item *ngSwitchCase="'text'">
|
<ion-item *ngSwitchCase="'text'">
|
||||||
<ion-label></ion-label>
|
<ion-label></ion-label>
|
||||||
<ion-input type="text" [(ngModel)]="setting.input.value" value={{setting.input.value}} (ionChange)="settingChanged()"></ion-input>
|
<ion-input type="text" [(ngModel)]="setting.value" value={{setting.value}} (ionChange)="settingChanged()"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item *ngSwitchCase="'password'">
|
<ion-item *ngSwitchCase="'password'">
|
||||||
<ion-label></ion-label>
|
<ion-label></ion-label>
|
||||||
<ion-input type="password" [(ngModel)]="setting.input.value" value={{setting.input.value}} (ionChange)="settingChanged()"></ion-input>
|
<ion-input type="password" [(ngModel)]="setting.value" value={{setting.value}} (ionChange)="settingChanged()"></ion-input>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item *ngSwitchCase="'singleChoice'">
|
<ion-item *ngSwitchCase="'singleChoice'">
|
||||||
<ion-label></ion-label>
|
<ion-label></ion-label>
|
||||||
<ion-toggle *ngIf="typeOf(setting.input.defaultValue) === 'boolean'" [(ngModel)]="setting.input.value" (ionChange)="settingChanged()"></ion-toggle>
|
<ion-toggle *ngIf="typeOf(setting.defaultValue) === 'boolean'" [(ngModel)]="setting.value" (ionChange)="settingChanged()"></ion-toggle>
|
||||||
<ion-select *ngIf="typeOf(setting.input.defaultValue) !== 'boolean'" interface="popover" [(ngModel)]="setting.input.value" (ionChange)="settingChanged()">
|
<ion-select *ngIf="typeOf(setting.defaultValue) !== 'boolean'" interface="popover" [(ngModel)]="setting.value" (ionChange)="settingChanged()">
|
||||||
<ion-select-option *ngFor="let val of setting.input.values" [value]="val">
|
<ion-select-option *ngFor="let val of setting.values" [value]="val">
|
||||||
<div *ngIf="typeOf(val) !== 'number'">{{ val }}</div>
|
<div *ngIf="typeOf(val) !== 'number'">{{ val }}</div>
|
||||||
<div *ngIf="typeOf(val) === 'number'">{{ val }}</div>
|
<div *ngIf="typeOf(val) === 'number'">{{ val }}</div>
|
||||||
</ion-select-option>
|
</ion-select-option>
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
<ion-item *ngSwitchCase="'multipleChoice'">
|
<ion-item *ngSwitchCase="'multipleChoice'">
|
||||||
<ion-label></ion-label>
|
<ion-label></ion-label>
|
||||||
<ion-select [(ngModel)]="setting.input.value" multiple="true" (ionChange)="settingChanged()">
|
<ion-select [(ngModel)]="setting.value" multiple="true" (ionChange)="settingChanged()">
|
||||||
<ion-select-option *ngFor="let val of setting.input.values" [value]="val">
|
<ion-select-option *ngFor="let val of setting.values" [value]="val">
|
||||||
<div *ngIf="typeOf(val) !== 'number'">{{ val }}</div>
|
<div *ngIf="typeOf(val) !== 'number'">{{ val }}</div>
|
||||||
<div *ngIf="typeOf(val) === 'number'">{{ val }}</div>
|
<div *ngIf="typeOf(val) === 'number'">{{ val }}</div>
|
||||||
</ion-select-option>
|
</ion-select-option>
|
||||||
|
|||||||
@@ -18,29 +18,58 @@ import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
|
|||||||
import {SCSettingMeta, SCThingTranslator, SCTranslations} from '@openstapps/core';
|
import {SCSettingMeta, SCThingTranslator, SCTranslations} from '@openstapps/core';
|
||||||
import {SettingsCache, SettingsProvider} from '../settings.provider';
|
import {SettingsCache, SettingsProvider} from '../settings.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stapps-settings-page',
|
selector: 'stapps-settings-page',
|
||||||
templateUrl: 'settings-page.html',
|
templateUrl: 'settings-page.html',
|
||||||
})
|
})
|
||||||
export class SettingsPageComponent {
|
export class SettingsPageComponent {
|
||||||
|
/**
|
||||||
|
* Order of the categories
|
||||||
|
*/
|
||||||
categoriesOrder: string[];
|
categoriesOrder: string[];
|
||||||
// limit to languages that are available in StApps Core
|
/**
|
||||||
|
* Possible languages to be used for translation
|
||||||
|
*
|
||||||
|
* limit to languages that are available in StApps Core
|
||||||
|
*/
|
||||||
language: keyof SCTranslations<any>;
|
language: keyof SCTranslations<any>;
|
||||||
|
/**
|
||||||
|
* Meta information about settings
|
||||||
|
*/
|
||||||
meta = SCSettingMeta;
|
meta = SCSettingMeta;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
objectKeys = Object.keys;
|
objectKeys = Object.keys;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
settingsCache: SettingsCache;
|
settingsCache: SettingsCache;
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
translator: SCThingTranslator;
|
translator: SCThingTranslator;
|
||||||
|
|
||||||
constructor(private alertController: AlertController,
|
/**
|
||||||
private settingsProvider: SettingsProvider,
|
*
|
||||||
private toastController: ToastController,
|
* @param alertController TODO
|
||||||
private translateService: TranslateService) {
|
* @param settingsProvider TODO
|
||||||
|
* @param toastController TODO
|
||||||
|
* @param translateService TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly alertController: AlertController,
|
||||||
|
private readonly settingsProvider: SettingsProvider,
|
||||||
|
private readonly toastController: ToastController,
|
||||||
|
private readonly translateService: TranslateService) {
|
||||||
this.language = translateService.currentLang as keyof SCTranslations<any>;
|
this.language = translateService.currentLang as keyof SCTranslations<any>;
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
|
|
||||||
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||||
this.language = event.lang as keyof SCTranslations<any>;
|
this.language = event.lang as keyof SCTranslations<any>;
|
||||||
this.translator = new SCThingTranslator(this.language, 'de');
|
this.translator = new SCThingTranslator(this.language);
|
||||||
});
|
});
|
||||||
this.settingsCache = {};
|
this.settingsCache = {};
|
||||||
this.categoriesOrder = settingsProvider.getCategoriesOrder();
|
this.categoriesOrder = settingsProvider.getCategoriesOrder();
|
||||||
@@ -66,6 +95,9 @@ export class SettingsPageComponent {
|
|||||||
this.settingsCache = await this.settingsProvider.getCache();
|
this.settingsCache = await this.settingsProvider.getCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component initialize method
|
||||||
|
*/
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
}
|
}
|
||||||
@@ -74,10 +106,14 @@ export class SettingsPageComponent {
|
|||||||
* Presents an alert to the user to reset settings to default values
|
* Presents an alert to the user to reset settings to default values
|
||||||
*/
|
*/
|
||||||
async presentResetAlert() {
|
async presentResetAlert() {
|
||||||
const cancelText = await this.translateService.get('settings.resetAlert.buttonCancel').toPromise();
|
const cancelText = await this.translateService.get('settings.resetAlert.buttonCancel')
|
||||||
const yesText = await this.translateService.get('settings.resetAlert.buttonYes').toPromise();
|
.toPromise();
|
||||||
const title = await this.translateService.get('settings.resetAlert.title').toPromise();
|
const yesText = await this.translateService.get('settings.resetAlert.buttonYes')
|
||||||
const message = await this.translateService.get('settings.resetAlert.message').toPromise();
|
.toPromise();
|
||||||
|
const title = await this.translateService.get('settings.resetAlert.title')
|
||||||
|
.toPromise();
|
||||||
|
const message = await this.translateService.get('settings.resetAlert.message')
|
||||||
|
.toPromise();
|
||||||
|
|
||||||
const alert = await this.alertController.create({
|
const alert = await this.alertController.create({
|
||||||
buttons: [
|
buttons: [
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<ion-list *ngFor="let categoryKey of categoriesOrder ">
|
<ion-list *ngFor="let categoryKey of categoriesOrder ">
|
||||||
<div *ngIf="objectKeys(settingsCache).includes(categoryKey)">
|
<div *ngIf="objectKeys(settingsCache).includes(categoryKey)">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<h5>{{translator.translate(settingsCache[categoryKey].settings[objectKeys(settingsCache[categoryKey].settings)[0]]).categories()[0]}}
|
<h5>{{ settingsCache[categoryKey].settings[objectKeys(settingsCache[categoryKey].settings)[0]].translations[language].categories[0]}}
|
||||||
</h5>
|
</h5>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<stapps-settings-item *ngFor="let settingKeys of objectKeys(settingsCache[categoryKey].settings)" [setting]="settingsCache[categoryKey].settings[settingKeys]"></stapps-settings-item>
|
<stapps-settings-item *ngFor="let settingKeys of objectKeys(settingsCache[categoryKey].settings)" [setting]="settingsCache[categoryKey].settings[settingKeys]"></stapps-settings-item>
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ const settingsRoutes: Routes = [
|
|||||||
{path: 'settings', component: SettingsPageComponent},
|
{path: 'settings', component: SettingsPageComponent},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings Module
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
SettingsPageComponent,
|
SettingsPageComponent,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {SCSetting, SCThingOriginType, SCThingType} from '@openstapps/core';
|
import {SCSetting, SCThingOriginType, SCThingType, SCSettingInputType} from '@openstapps/core';
|
||||||
import {ConfigProvider} from '../config/config.provider';
|
import {ConfigProvider} from '../config/config.provider';
|
||||||
import {StorageProvider} from '../storage/storage.provider';
|
import {StorageProvider} from '../storage/storage.provider';
|
||||||
import {SettingsProvider, SettingValuesContainer, STORAGE_KEY_SETTING_VALUES} from './settings.provider';
|
import {SettingsProvider, SettingValuesContainer, STORAGE_KEY_SETTING_VALUES} from './settings.provider';
|
||||||
@@ -53,14 +53,14 @@ describe('SettingsProvider', () => {
|
|||||||
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
||||||
const setting: SCSetting = await settingsProvider
|
const setting: SCSetting = await settingsProvider
|
||||||
.getSetting(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
.getSetting(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
||||||
await expect(setting.input.value).toBeDefined();
|
await expect(setting.value).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should provide and get settings value', async () => {
|
it('should provide and get settings value', async () => {
|
||||||
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
||||||
const value = await settingsProvider
|
const value = await settingsProvider
|
||||||
.getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
.getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
||||||
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].input.defaultValue);
|
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get persisted setting value', async () => {
|
it('should get persisted setting value', async () => {
|
||||||
@@ -79,7 +79,7 @@ describe('SettingsProvider', () => {
|
|||||||
storageProviderSpy.get.and.returnValue(Promise.resolve([]));
|
storageProviderSpy.get.and.returnValue(Promise.resolve([]));
|
||||||
const value = await settingsProvider
|
const value = await settingsProvider
|
||||||
.getValue(CONFIG_SETTINGS_MOCK[3].categories[0], CONFIG_SETTINGS_MOCK[3].name);
|
.getValue(CONFIG_SETTINGS_MOCK[3].categories[0], CONFIG_SETTINGS_MOCK[3].name);
|
||||||
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[3].input.defaultValue);
|
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[3].defaultValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep persisted setting values from settings that are not contained in loaded config', async () => {
|
it('should keep persisted setting values from settings that are not contained in loaded config', async () => {
|
||||||
@@ -108,10 +108,10 @@ describe('SettingsProvider', () => {
|
|||||||
const name = CONFIG_SETTINGS_MOCK[0].name;
|
const name = CONFIG_SETTINGS_MOCK[0].name;
|
||||||
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
await settingsProvider.provideSetting(JSON.parse(JSON.stringify(CONFIG_SETTINGS_MOCK[0])));
|
||||||
const settings = await settingsProvider.getCache();
|
const settings = await settingsProvider.getCache();
|
||||||
settings[category].settings[name].input.value = 'testValue';
|
settings[category].settings[name].value = 'testValue';
|
||||||
// cached setting value should still be defaultValue
|
// cached setting value should still be defaultValue
|
||||||
await expect((await settingsProvider.getValue(category, name)))
|
await expect((await settingsProvider.getValue(category, name)))
|
||||||
.toEqual(CONFIG_SETTINGS_MOCK[0].input.defaultValue);
|
.toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call storage put on setSettingValue', async () => {
|
it('should call storage put on setSettingValue', async () => {
|
||||||
@@ -134,7 +134,7 @@ describe('SettingsProvider', () => {
|
|||||||
await settingsProvider.resetDefault();
|
await settingsProvider.resetDefault();
|
||||||
const value = await settingsProvider
|
const value = await settingsProvider
|
||||||
.getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
.getValue(CONFIG_SETTINGS_MOCK[0].categories[0], CONFIG_SETTINGS_MOCK[0].name);
|
||||||
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].input.defaultValue);
|
await expect(value).toEqual(CONFIG_SETTINGS_MOCK[0].defaultValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should validate wrong values for inputType text', async () => {
|
it('should validate wrong values for inputType text', async () => {
|
||||||
@@ -172,7 +172,7 @@ describe('SettingsProvider', () => {
|
|||||||
await testValue(CONFIG_SETTINGS_MOCK[6], '');
|
await testValue(CONFIG_SETTINGS_MOCK[6], '');
|
||||||
await testValue(CONFIG_SETTINGS_MOCK[6], 123456);
|
await testValue(CONFIG_SETTINGS_MOCK[6], 123456);
|
||||||
await testValue(CONFIG_SETTINGS_MOCK[6], false);
|
await testValue(CONFIG_SETTINGS_MOCK[6], false);
|
||||||
await testValue(CONFIG_SETTINGS_MOCK[6], [1, 2, 3, 4]);
|
await testValue(CONFIG_SETTINGS_MOCK[6], [1, 9]);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function testValue(setting: SCSetting, value: any) {
|
async function testValue(setting: SCSetting, value: any) {
|
||||||
@@ -192,10 +192,8 @@ describe('SettingsProvider', () => {
|
|||||||
const CONFIG_SETTINGS_MOCK: SCSetting[] = [
|
const CONFIG_SETTINGS_MOCK: SCSetting[] = [
|
||||||
{
|
{
|
||||||
categories: ['credentials'],
|
categories: ['credentials'],
|
||||||
input: {
|
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
inputType: 'text',
|
inputType: SCSettingInputType.Text,
|
||||||
},
|
|
||||||
name: 'username',
|
name: 'username',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -219,10 +217,8 @@ describe('SettingsProvider', () => {
|
|||||||
{
|
{
|
||||||
categories: ['credentials'],
|
categories: ['credentials'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
inputType: 'password',
|
inputType: SCSettingInputType.Password,
|
||||||
},
|
|
||||||
name: 'password',
|
name: 'password',
|
||||||
order: 1,
|
order: 1,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -246,10 +242,8 @@ describe('SettingsProvider', () => {
|
|||||||
{
|
{
|
||||||
categories: ['profile'],
|
categories: ['profile'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: 0,
|
defaultValue: 0,
|
||||||
inputType: 'number',
|
inputType: SCSettingInputType.Number,
|
||||||
},
|
|
||||||
name: 'age',
|
name: 'age',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -273,11 +267,8 @@ describe('SettingsProvider', () => {
|
|||||||
{
|
{
|
||||||
categories: ['profile'],
|
categories: ['profile'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: 'student',
|
defaultValue: 'student',
|
||||||
inputType: 'singleChoice',
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
values: ['student', 'employee', 'guest'],
|
|
||||||
},
|
|
||||||
name: 'group',
|
name: 'group',
|
||||||
order: 1,
|
order: 1,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -301,15 +292,13 @@ describe('SettingsProvider', () => {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: ['student', 'employee', 'guest'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
categories: ['profile'],
|
categories: ['profile'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: 'en',
|
defaultValue: 'en',
|
||||||
inputType: 'singleChoice',
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
values: ['en', 'de'],
|
|
||||||
},
|
|
||||||
name: 'language',
|
name: 'language',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -331,15 +320,13 @@ describe('SettingsProvider', () => {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: ['en', 'de'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
categories: ['privacy'],
|
categories: ['privacy'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
inputType: 'singleChoice',
|
inputType: SCSettingInputType.SingleChoice,
|
||||||
values: [true, false],
|
|
||||||
},
|
|
||||||
name: 'geoLocation',
|
name: 'geoLocation',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -363,15 +350,13 @@ describe('SettingsProvider', () => {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: [true, false],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
categories: ['others'],
|
categories: ['others'],
|
||||||
description: '',
|
description: '',
|
||||||
input: {
|
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
inputType: 'multipleChoice',
|
inputType: SCSettingInputType.MultipleChoice,
|
||||||
values: [1, 2, 3, 4, 5, 6, 7, 8],
|
|
||||||
},
|
|
||||||
name: 'numbers',
|
name: 'numbers',
|
||||||
order: 0,
|
order: 0,
|
||||||
origin: {
|
origin: {
|
||||||
@@ -393,6 +378,7 @@ describe('SettingsProvider', () => {
|
|||||||
},
|
},
|
||||||
type: SCThingType.Setting,
|
type: SCThingType.Setting,
|
||||||
uid: '',
|
uid: '',
|
||||||
|
values: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,25 +16,29 @@ import {Injectable} from '@angular/core';
|
|||||||
import {Geolocation} from '@ionic-native/geolocation/ngx';
|
import {Geolocation} from '@ionic-native/geolocation/ngx';
|
||||||
import {
|
import {
|
||||||
SCSetting,
|
SCSetting,
|
||||||
SCSettingMultipleChoice,
|
|
||||||
SCSettingSingleChoice,
|
|
||||||
SCSettingValue,
|
SCSettingValue,
|
||||||
|
SCSettingValues,
|
||||||
} from '@openstapps/core';
|
} from '@openstapps/core';
|
||||||
import {Logger} from '@openstapps/logger';
|
|
||||||
import * as deepMerge from 'deepmerge';
|
import * as deepMerge from 'deepmerge';
|
||||||
import {ConfigProvider} from '../config/config.provider';
|
import {ConfigProvider} from '../config/config.provider';
|
||||||
import {StorageProvider} from '../storage/storage.provider';
|
import {StorageProvider} from '../storage/storage.provider';
|
||||||
|
|
||||||
export const STORAGE_KEY_SETTINGS = 'settings';
|
export const STORAGE_KEY_SETTINGS = 'settings';
|
||||||
export const STORAGE_KEY_SETTINGS_SEPARATOR = '.';
|
export const STORAGE_KEY_SETTINGS_SEPARATOR = '.';
|
||||||
export const STORAGE_KEY_SETTING_VALUES = STORAGE_KEY_SETTINGS + STORAGE_KEY_SETTINGS_SEPARATOR + 'values';
|
export const STORAGE_KEY_SETTING_VALUES = `${STORAGE_KEY_SETTINGS}${STORAGE_KEY_SETTINGS_SEPARATOR}values`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category structure of settings cache
|
* Category structure of settings cache
|
||||||
*/
|
*/
|
||||||
export interface CategoryWithSettings {
|
export interface CategoryWithSettings {
|
||||||
|
/**
|
||||||
|
* Category name
|
||||||
|
*/
|
||||||
category: string;
|
category: string;
|
||||||
settings: { [key: string]: SCSetting };
|
/**
|
||||||
|
* Settings that belong in this category
|
||||||
|
*/
|
||||||
|
settings: { [key: string]: SCSetting; };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,36 +64,61 @@ export interface SettingValueContainer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider for app settings
|
* Provider for app settings
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SettingsProvider {
|
export class SettingsProvider {
|
||||||
|
/**
|
||||||
|
* Order of the setting categories
|
||||||
|
*/
|
||||||
categoriesOrder: string[];
|
categoriesOrder: string[];
|
||||||
|
/**
|
||||||
|
* Is provider initialized
|
||||||
|
*/
|
||||||
initialized = false;
|
initialized = false;
|
||||||
logger = new Logger();
|
/**
|
||||||
|
* Cache for the imported settings
|
||||||
|
*/
|
||||||
settingsCache: SettingsCache;
|
settingsCache: SettingsCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if all given values are valid to possible values in given settingInput
|
* Return true if all given values are valid to possible values in given settingInput
|
||||||
* @param settingInput
|
* @param possibleValues Possible values
|
||||||
* @param values
|
* @param enteredValues Entered value
|
||||||
*/
|
*/
|
||||||
public static checkMultipleChoiceValue(settingInput: SCSettingMultipleChoice, values: SCSettingValue[]): boolean {
|
public static checkMultipleChoiceValue(
|
||||||
for (const value of values) {
|
possibleValues: SCSettingValues | undefined,
|
||||||
if (!settingInput.values.includes(value)) {
|
enteredValues: SCSettingValues,
|
||||||
|
): boolean {
|
||||||
|
if ( typeof possibleValues === 'undefined' ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of enteredValues) {
|
||||||
|
if (!possibleValues.includes(value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if given value is valid to possible values in given settingInput
|
* Returns true if given value is valid to possible values in given settingInput
|
||||||
* @param settingInput
|
* @param possibleValues Possible values
|
||||||
* @param value
|
* @param enteredValue Entered value
|
||||||
*/
|
*/
|
||||||
public static checkSingleChoiceValue(settingInput: SCSettingSingleChoice, value: SCSettingValue): boolean {
|
public static checkSingleChoiceValue(
|
||||||
return settingInput.values !== undefined
|
possibleValues: SCSettingValues | undefined,
|
||||||
&& settingInput.values.includes(value);
|
enteredValue: SCSettingValue,
|
||||||
|
): boolean {
|
||||||
|
if ( typeof possibleValues === 'undefined' ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleValues !== undefined
|
||||||
|
&& (Array.isArray(possibleValues)
|
||||||
|
&& possibleValues.includes(enteredValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,19 +126,19 @@ export class SettingsProvider {
|
|||||||
* @param setting setting to check value against
|
* @param setting setting to check value against
|
||||||
* @param value value to validate
|
* @param value value to validate
|
||||||
*/
|
*/
|
||||||
public static validateValue(setting: SCSetting, value: any): boolean {
|
public static validateValue(setting: SCSetting, value: SCSettingValue | SCSettingValues): boolean {
|
||||||
let isValueValid: boolean = false;
|
let isValueValid = false;
|
||||||
switch (setting.input.inputType) {
|
switch (setting.inputType) {
|
||||||
case 'number':
|
case 'number':
|
||||||
if (typeof value === 'number') {
|
if (typeof value === 'number') {
|
||||||
isValueValid = true;
|
isValueValid = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'multipleChoice':
|
case 'multiple choice':
|
||||||
if (!value.isArray) {
|
if (!Array.isArray(value)) {
|
||||||
isValueValid = false;
|
isValueValid = false;
|
||||||
} else {
|
} else {
|
||||||
isValueValid = SettingsProvider.checkMultipleChoiceValue(setting.input, value);
|
isValueValid = SettingsProvider.checkMultipleChoiceValue(setting.values, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'password':
|
case 'password':
|
||||||
@@ -118,32 +147,43 @@ export class SettingsProvider {
|
|||||||
isValueValid = true;
|
isValueValid = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'singleChoice':
|
case 'single choice':
|
||||||
isValueValid = SettingsProvider.checkSingleChoiceValue(setting.input, value);
|
if (Array.isArray(value)) {
|
||||||
|
isValueValid = false;
|
||||||
|
} else {
|
||||||
|
isValueValid = SettingsProvider.checkSingleChoiceValue(setting.values, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
return isValueValid;
|
return isValueValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private storage: StorageProvider,
|
/**
|
||||||
private configProvider: ConfigProvider,
|
*
|
||||||
private geoLocation: Geolocation) {
|
* @param storage TODO
|
||||||
|
* @param configProvider TODO
|
||||||
|
* @param geoLocation TODO
|
||||||
|
*/
|
||||||
|
constructor(private readonly storage: StorageProvider,
|
||||||
|
private readonly configProvider: ConfigProvider,
|
||||||
|
private readonly geoLocation: Geolocation) {
|
||||||
this.categoriesOrder = [];
|
this.categoriesOrder = [];
|
||||||
this.settingsCache = {};
|
this.settingsCache = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an Setting to the Cache if not exist and set undefined value to defaultValue
|
* Add an Setting to the Cache if not exist and set undefined value to defaultValue
|
||||||
* @param setting
|
* @param setting Setting with categories, defautlValue, name, input type and valid values
|
||||||
*/
|
*/
|
||||||
private async addSetting(setting: SCSetting): Promise<void> {
|
private async addSetting(setting: SCSetting): Promise<void> {
|
||||||
if (!this.categoryExists(setting.categories[0])) {
|
if (!this.categoryExists(setting.categories[0])) {
|
||||||
await this.provideCategory(setting.categories[0]);
|
await this.provideCategory(setting.categories[0]);
|
||||||
}
|
}
|
||||||
if (!this.settingExists(setting.categories[0], setting.name)) {
|
if (!this.settingExists(setting.categories[0], setting.name)) {
|
||||||
if (setting.input.value === undefined) {
|
if (setting.value === undefined) {
|
||||||
setting.input.value = setting.input.defaultValue;
|
setting.value = setting.defaultValue;
|
||||||
}
|
}
|
||||||
this.settingsCache[setting.categories[0]].settings[setting.name] = setting;
|
this.settingsCache[setting.categories[0]].settings[setting.name] = setting;
|
||||||
}
|
}
|
||||||
@@ -162,9 +202,10 @@ export class SettingsProvider {
|
|||||||
settingValuesContainer[categoryKey] = {};
|
settingValuesContainer[categoryKey] = {};
|
||||||
}
|
}
|
||||||
settingValuesContainer[categoryKey][settingKey] =
|
settingValuesContainer[categoryKey][settingKey] =
|
||||||
this.settingsCache[categoryKey].settings[settingKey].input.value;
|
this.settingsCache[categoryKey].settings[settingKey].value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return settingValuesContainer;
|
return settingValuesContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,11 +237,11 @@ export class SettingsProvider {
|
|||||||
// if saved setting value exists set it, otherwise set to default value
|
// if saved setting value exists set it, otherwise set to default value
|
||||||
if (typeof valuesContainer[categoryKey] !== 'undefined'
|
if (typeof valuesContainer[categoryKey] !== 'undefined'
|
||||||
&& typeof valuesContainer[categoryKey][settingKey] !== 'undefined') {
|
&& typeof valuesContainer[categoryKey][settingKey] !== 'undefined') {
|
||||||
this.settingsCache[categoryKey].settings[settingKey].input.value =
|
this.settingsCache[categoryKey].settings[settingKey].value =
|
||||||
valuesContainer[categoryKey][settingKey];
|
valuesContainer[categoryKey][settingKey];
|
||||||
} else {
|
} else {
|
||||||
this.settingsCache[categoryKey].settings[settingKey].input.value =
|
this.settingsCache[categoryKey].settings[settingKey].value =
|
||||||
this.settingsCache[categoryKey].settings[settingKey].input.defaultValue;
|
this.settingsCache[categoryKey].settings[settingKey].defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,7 +269,7 @@ export class SettingsProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if category exists
|
* Returns true if category exists
|
||||||
* @param category
|
* @param category Category key name
|
||||||
*/
|
*/
|
||||||
public categoryExists(category: string): boolean {
|
public categoryExists(category: string): boolean {
|
||||||
return this.settingsCache[category] !== undefined;
|
return this.settingsCache[category] !== undefined;
|
||||||
@@ -256,6 +297,7 @@ export class SettingsProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +306,7 @@ export class SettingsProvider {
|
|||||||
*/
|
*/
|
||||||
public async getCache(): Promise<SettingsCache> {
|
public async getCache(): Promise<SettingsCache> {
|
||||||
await this.init();
|
await this.init();
|
||||||
|
|
||||||
return JSON.parse(JSON.stringify(this.settingsCache));
|
return JSON.parse(JSON.stringify(this.settingsCache));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,14 +324,13 @@ export class SettingsProvider {
|
|||||||
*
|
*
|
||||||
* @throws Exception if setting is not provided
|
* @throws Exception if setting is not provided
|
||||||
*/
|
*/
|
||||||
public async getSetting(category: string, name: string): Promise<any> {
|
public async getSetting(category: string, name: string): Promise<SCSetting> {
|
||||||
await this.init();
|
await this.init();
|
||||||
if (this.settingExists(category, name)) {
|
if (this.settingExists(category, name)) {
|
||||||
// return a copy of the settings
|
// return a copy of the settings
|
||||||
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name]));
|
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name]));
|
||||||
} else {
|
|
||||||
throw new Error(`Setting "${name}" not provided`);
|
|
||||||
}
|
}
|
||||||
|
throw new Error(`Setting "${name}" not provided`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -302,10 +344,9 @@ export class SettingsProvider {
|
|||||||
await this.init();
|
await this.init();
|
||||||
if (this.settingExists(category, name)) {
|
if (this.settingExists(category, name)) {
|
||||||
// return a copy of the settings value
|
// return a copy of the settings value
|
||||||
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name].input.value));
|
return JSON.parse(JSON.stringify(this.settingsCache[category].settings[name].value));
|
||||||
} else {
|
|
||||||
throw new Error(`Setting "${name}" not provided`);
|
|
||||||
}
|
}
|
||||||
|
throw new Error(`Setting "${name}" not provided`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -340,7 +381,7 @@ export class SettingsProvider {
|
|||||||
async resetDefault(): Promise<void> {
|
async resetDefault(): Promise<void> {
|
||||||
for (const catKey of Object.keys(this.settingsCache)) {
|
for (const catKey of Object.keys(this.settingsCache)) {
|
||||||
for (const settingKey of Object.keys(this.settingsCache[catKey].settings)) {
|
for (const settingKey of Object.keys(this.settingsCache[catKey].settings)) {
|
||||||
const settingInput = this.settingsCache[catKey].settings[settingKey].input;
|
const settingInput = this.settingsCache[catKey].settings[settingKey];
|
||||||
settingInput.value = settingInput.defaultValue;
|
settingInput.value = settingInput.defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -373,24 +414,24 @@ export class SettingsProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a valid value of a setting and persists changes in storage
|
* Sets a valid value of a setting and persists changes in storage
|
||||||
* @param category
|
* @param category Category key name
|
||||||
* @param name
|
* @param name Setting key name
|
||||||
* @param value
|
* @param value Value to be set
|
||||||
*
|
*
|
||||||
* @throws Exception if setting is not provided or value not valid to the settings inputType
|
* @throws Exception if setting is not provided or value not valid to the settings inputType
|
||||||
*/
|
*/
|
||||||
public async setSettingValue(category: string, name: string,
|
public async setSettingValue(category: string, name: string,
|
||||||
value: any): Promise<void> {
|
value: SCSettingValue | SCSettingValues): Promise<void> {
|
||||||
await this.init();
|
await this.init();
|
||||||
if (this.settingExists(category, name)) {
|
if (this.settingExists(category, name)) {
|
||||||
const setting: SCSetting = this.settingsCache[category].settings[name];
|
const setting: SCSetting = this.settingsCache[category].settings[name];
|
||||||
const isValueValid = SettingsProvider.validateValue(setting, value);
|
const isValueValid = SettingsProvider.validateValue(setting, value);
|
||||||
if (isValueValid) {
|
if (isValueValid) {
|
||||||
this.settingsCache[category].settings[name].input.value = value;
|
this.settingsCache[category].settings[name].value = value;
|
||||||
await this.saveSettingValues();
|
await this.saveSettingValues();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Value "${value}" of type
|
throw new Error(`Value "${value}" of type
|
||||||
${typeof value} is not valid for ${setting.input.inputType}`);
|
${typeof value} is not valid for ${setting.inputType}`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`setting ${name} is not provided`);
|
throw new Error(`setting ${name} is not provided`);
|
||||||
@@ -399,8 +440,8 @@ export class SettingsProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if setting in category exists
|
* Returns true if setting in category exists
|
||||||
* @param category
|
* @param category Category key name
|
||||||
* @param setting
|
* @param setting Setting key name
|
||||||
*/
|
*/
|
||||||
public settingExists(category: string, setting: string): boolean {
|
public settingExists(category: string, setting: string): boolean {
|
||||||
return this.categoryExists(category) && this.settingsCache[category].settings[setting] !== undefined;
|
return this.categoryExists(category) && this.settingsCache[category].settings[setting] !== undefined;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -12,16 +12,19 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { NgModule } from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
import { IonicStorageModule } from '@ionic/storage';
|
import {IonicStorageModule} from '@ionic/storage';
|
||||||
import { StorageProvider } from './storage.provider';
|
import {StorageProvider} from './storage.provider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Angular storage provider module
|
||||||
|
*/
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
IonicStorageModule.forRoot()
|
IonicStorageModule.forRoot(),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
StorageProvider
|
StorageProvider,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
export class StorageModule {}
|
export class StorageModule {}
|
||||||
|
|||||||
@@ -20,24 +20,29 @@ import {Storage} from '@ionic/storage';
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StorageProvider {
|
export class StorageProvider {
|
||||||
constructor(private storage: Storage) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the storage (waits until it's ready)
|
|
||||||
*/
|
|
||||||
async init(): Promise<any> {
|
|
||||||
return this.storage.ready();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Puts a value of type T into the storage using provided key
|
|
||||||
*
|
*
|
||||||
* @param key Unique indentifier
|
* @param storage TODO
|
||||||
* @param value Resource to store under the key
|
|
||||||
*/
|
*/
|
||||||
async put<T>(key: string, value: T): Promise<T> {
|
constructor(private readonly storage: Storage) {
|
||||||
return this.storage.set(key, value);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes storage entries using keys used to save them
|
||||||
|
*
|
||||||
|
* @param keys Unique identifiers of the resources for deletion
|
||||||
|
*/
|
||||||
|
async delete(...keys: string[]): Promise<void> {
|
||||||
|
keys.forEach(async (key) => {
|
||||||
|
await this.storage.remove(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all the entries in the storage (empty the storage)
|
||||||
|
*/
|
||||||
|
async deleteAll(): Promise<void> {
|
||||||
|
return this.storage.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,68 +55,23 @@ export class StorageProvider {
|
|||||||
if (!entry) {
|
if (!entry) {
|
||||||
throw new Error('Value not found.');
|
throw new Error('Value not found.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable:no-any
|
||||||
/**
|
/**
|
||||||
* Gets values from the storage using the provided pattern
|
* Retrieves all the storage entries
|
||||||
*
|
|
||||||
* @param pattern Regular expression or text to test existing storage keys with
|
|
||||||
*/
|
*/
|
||||||
async search<T>(pattern: RegExp | string): Promise<Map<string, T>> {
|
async getAll(): Promise<Map<string, any>> {
|
||||||
const map: Map<string, any> = new Map();
|
const map: Map<string, any> = new Map();
|
||||||
const check = (input: RegExp | string) => {
|
|
||||||
if (input instanceof RegExp) {
|
|
||||||
return (p: any, k: string): boolean => {
|
|
||||||
return p.test(k);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return (p: any, k: string): boolean => {
|
|
||||||
return k.includes(p);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const checkIt = check(pattern);
|
|
||||||
await this.storage.forEach((value, key) => {
|
await this.storage.forEach((value, key) => {
|
||||||
if (checkIt(pattern, key)) {
|
|
||||||
map.set(key, value);
|
map.set(key, value);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes storage entries using keys used to save them
|
|
||||||
*
|
|
||||||
* @param keys Unique identifiers of the resources for deletion
|
|
||||||
*/
|
|
||||||
async delete(...keys: string[]): Promise<void> {
|
|
||||||
await keys.forEach((key) => {
|
|
||||||
this.storage.remove(key);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes all the entries in the storage (empty the storage)
|
|
||||||
*/
|
|
||||||
async deleteAll(): Promise<void> {
|
|
||||||
return this.storage.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves multiple entries into the storage
|
|
||||||
*
|
|
||||||
* @param entries Resources to be put into the storage
|
|
||||||
*/
|
|
||||||
async putMultiple(entries: Map<string, any>): Promise<Map<string, any>> {
|
|
||||||
const puts: Array<Promise<any>> = [];
|
|
||||||
entries.forEach(async (value, key) => {
|
|
||||||
puts.push(this.put(key, value));
|
|
||||||
});
|
|
||||||
await Promise.all(puts);
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves multiple entries from the storage using their keys
|
* Retrieves multiple entries from the storage using their keys
|
||||||
*
|
*
|
||||||
@@ -127,34 +87,10 @@ export class StorageProvider {
|
|||||||
gets.push(getToMap(key));
|
gets.push(getToMap(key));
|
||||||
});
|
});
|
||||||
await Promise.all(gets);
|
await Promise.all(gets);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves all the storage entries
|
|
||||||
*/
|
|
||||||
async getAll(): Promise<Map<string, any>> {
|
|
||||||
const map: Map<string, any> = new Map();
|
|
||||||
await this.storage.forEach((value, key) => {
|
|
||||||
map.set(key, value);
|
|
||||||
});
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a number of entries in the storage (number of keys)
|
|
||||||
*/
|
|
||||||
async length(): Promise<number> {
|
|
||||||
return this.storage.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides information if storage is empty or not
|
|
||||||
*/
|
|
||||||
async isEmpty(): Promise<boolean> {
|
|
||||||
return (await this.storage.length()) === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides information if storage has an entry with the given key
|
* Provides information if storage has an entry with the given key
|
||||||
*
|
*
|
||||||
@@ -163,4 +99,78 @@ export class StorageProvider {
|
|||||||
async has(key: string): Promise<boolean> {
|
async has(key: string): Promise<boolean> {
|
||||||
return (await this.storage.keys()).includes(key);
|
return (await this.storage.keys()).includes(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the storage (waits until it's ready)
|
||||||
|
*/
|
||||||
|
async init(): Promise<any> {
|
||||||
|
return this.storage.ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides information if storage is empty or not
|
||||||
|
*/
|
||||||
|
async isEmpty(): Promise<boolean> {
|
||||||
|
return (await this.storage.length()) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a number of entries in the storage (number of keys)
|
||||||
|
*/
|
||||||
|
async length(): Promise<number> {
|
||||||
|
return this.storage.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts a value of type T into the storage using provided key
|
||||||
|
*
|
||||||
|
* @param key Unique indentifier
|
||||||
|
* @param value Resource to store under the key
|
||||||
|
*/
|
||||||
|
async put<T>(key: string, value: T): Promise<T> {
|
||||||
|
return this.storage.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves multiple entries into the storage
|
||||||
|
*
|
||||||
|
* @param entries Resources to be put into the storage
|
||||||
|
*/
|
||||||
|
async putMultiple(entries: Map<string, any>): Promise<Map<string, any>> {
|
||||||
|
const puts: Array<Promise<any>> = [];
|
||||||
|
entries.forEach(async (value, key) => {
|
||||||
|
puts.push(this.put(key, value));
|
||||||
|
});
|
||||||
|
await Promise.all(puts);
|
||||||
|
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets values from the storage using the provided pattern
|
||||||
|
*
|
||||||
|
* @param pattern Regular expression or text to test existing storage keys with
|
||||||
|
*/
|
||||||
|
async search<T>(pattern: RegExp | string): Promise<Map<string, T>> {
|
||||||
|
const map: Map<string, any> = new Map();
|
||||||
|
const check = (input: RegExp | string) => {
|
||||||
|
if (input instanceof RegExp) {
|
||||||
|
return (p: any, k: string): boolean => {
|
||||||
|
return p.test(k);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (p: any, k: string): boolean => {
|
||||||
|
return k.includes(p);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const checkIt = check(pattern);
|
||||||
|
await this.storage.forEach((value, key) => {
|
||||||
|
if (checkIt(pattern, key)) {
|
||||||
|
map.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-8
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -12,15 +12,16 @@
|
|||||||
* You should have received a copy of the GNU General Public License along with
|
* You should have received a copy of the GNU General Public License along with
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { enableProdMode } from '@angular/core';
|
import {enableProdMode} from '@angular/core';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||||
|
import {Logger} from '@openstapps/logger';
|
||||||
import { AppModule } from './app/app.module';
|
import {AppModule} from './app/app.module';
|
||||||
import { environment } from './environments/environment';
|
import {environment} from './environments/environment';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
platformBrowserDynamic()
|
||||||
.catch(err => console.log(err));
|
.bootstrapModule(AppModule)
|
||||||
|
.catch(async (err) => await Logger.error(err));
|
||||||
|
|||||||
+8
-10
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -32,7 +32,9 @@
|
|||||||
* BROWSER POLYFILLS
|
* BROWSER POLYFILLS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
/*
|
||||||
|
* IE9, IE10 and IE11 requires all of the following polyfills.
|
||||||
|
*/
|
||||||
// import 'core-js/es6/symbol';
|
// import 'core-js/es6/symbol';
|
||||||
// import 'core-js/es6/object';
|
// import 'core-js/es6/object';
|
||||||
// import 'core-js/es6/function';
|
// import 'core-js/es6/function';
|
||||||
@@ -54,27 +56,23 @@
|
|||||||
/** IE10 and IE11 requires the following for the Reflect API. */
|
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||||
// import 'core-js/es6/reflect';
|
// import 'core-js/es6/reflect';
|
||||||
|
|
||||||
|
/*
|
||||||
/** Evergreen browsers require these. **/
|
* Evergreen browsers require these.
|
||||||
|
*/
|
||||||
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
||||||
import 'core-js/es7/reflect';
|
import 'core-js/es7/reflect';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Required to support Web Animations `@angular/platform-browser/animations`.
|
* Required to support Web Animations `@angular/platform-browser/animations`.
|
||||||
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
* Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
|
||||||
**/
|
*/
|
||||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Zone JS is required by Angular itself.
|
* Zone JS is required by Angular itself.
|
||||||
*/
|
*/
|
||||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* APPLICATION IMPORTS
|
* APPLICATION IMPORTS
|
||||||
*/
|
*/
|
||||||
|
|||||||
+10
-7
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 StApps
|
* Copyright (C) 2018, 2019 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.
|
||||||
@@ -14,21 +14,24 @@
|
|||||||
*/
|
*/
|
||||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
import { getTestBed } from '@angular/core/testing';
|
import {getTestBed} from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
platformBrowserDynamicTesting
|
platformBrowserDynamicTesting,
|
||||||
} from '@angular/platform-browser-dynamic/testing';
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
import 'zone.js/dist/zone-testing';
|
import 'zone.js/dist/zone-testing';
|
||||||
|
|
||||||
|
// tslint:disable-next-line:no-any
|
||||||
declare const require: any;
|
declare const require: any;
|
||||||
|
|
||||||
// First, initialize the Angular testing environment.
|
// First, initialize the Angular testing environment.
|
||||||
getTestBed().initTestEnvironment(
|
getTestBed()
|
||||||
|
.initTestEnvironment(
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
platformBrowserDynamicTesting()
|
platformBrowserDynamicTesting(),
|
||||||
);
|
);
|
||||||
// Then we find all the tests.
|
// Then we find all the tests.
|
||||||
const context = require.context('./', true, /\.spec\.ts$/);
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
// And load the modules.
|
// And load the modules.
|
||||||
context.keys().map(context);
|
context.keys()
|
||||||
|
.map(context);
|
||||||
|
|||||||
Reference in New Issue
Block a user