diff --git a/package-lock.json b/package-lock.json
index 1d93ba58..1d45f7ca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3345,9 +3345,9 @@
"dev": true
},
"@hapi/hoek": {
- "version": "9.2.0",
- "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz",
- "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug=="
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz",
+ "integrity": "sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw=="
},
"@hapi/topo": {
"version": "5.1.0",
@@ -3668,9 +3668,9 @@
}
},
"@krlwlfrt/async-pool": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.5.0.tgz",
- "integrity": "sha512-ZwdRzVEQ89zKVsXFyM6mPwJ5NwaPwvGB5rN5VyJ7SFKBPtjZhzY2VBHLszdKC7f1lFvCXISDace6SE+O/M+4eg=="
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.7.0.tgz",
+ "integrity": "sha512-qQp9fJdPuSxhJ0aMWCJ8ZavG67GeB1ZoYfYsIooyipeXTWZ9U67uEm93Udvd6C6v1Wa6mvD8X5PBNTtth1x0LQ=="
},
"@netflix/nerror": {
"version": "1.1.3",
@@ -3876,24 +3876,24 @@
}
},
"@openstapps/api": {
- "version": "0.32.0",
- "resolved": "https://registry.npmjs.org/@openstapps/api/-/api-0.32.0.tgz",
- "integrity": "sha512-udgKVJKqv6sAZLB0BBZZXx4fM3fxy/2fCqLEfo+bVFwnZHYlhwL12boUFku0NhcSXWyKOpJgAK/kSrGP7IC1tQ==",
+ "version": "0.35.0",
+ "resolved": "https://registry.npmjs.org/@openstapps/api/-/api-0.35.0.tgz",
+ "integrity": "sha512-mZGYTN+MJouVld9gIVJD5/hLDkB9hLRamKPZywcu195kngmayIPz4AbliHd1A8Xbrp0xtyE/i/Xse/+FkQ7i/g==",
"requires": {
- "@krlwlfrt/async-pool": "0.5.0",
- "@openstapps/core": "0.50.0",
+ "@krlwlfrt/async-pool": "0.7.0",
+ "@openstapps/core": "0.53.0",
"@openstapps/core-tools": "0.25.0",
"@openstapps/logger": "0.7.0",
"@types/cli-progress": "3.9.2",
"@types/express": "4.17.13",
"@types/morgan": "1.9.3",
- "@types/node": "14.17.14",
+ "@types/node": "14.17.27",
"@types/traverse": "0.6.32",
"@types/uuid": "8.3.1",
"@types/wait-on": "5.3.1",
"body-parser": "1.19.0",
- "cli-progress": "3.9.0",
- "commander": "7.2.0",
+ "cli-progress": "3.9.1",
+ "commander": "8.2.0",
"express": "4.17.1",
"fast-clone": "1.5.13",
"got": "11.8.2",
@@ -3902,43 +3902,18 @@
"morgan": "1.10.0",
"traverse": "0.6.6",
"uuid": "8.3.2",
- "wait-on": "5.3.0"
+ "wait-on": "6.0.0"
},
"dependencies": {
- "@openstapps/core": {
- "version": "0.50.0",
- "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.50.0.tgz",
- "integrity": "sha512-0g2YQF6j9j9Mhqsc6HkD+EbkGvjoXI9Q3+1U+B3FdSxE23ubA6Fp/DM17uN5/OvXrygjNXnU6oehwW80iKXVJw==",
- "requires": {
- "@openstapps/core-tools": "0.25.0",
- "@types/geojson": "1.0.6",
- "@types/json-patch": "0.0.30",
- "@types/json-schema": "7.0.9",
- "@types/node": "14.17.9",
- "fast-clone": "1.5.13",
- "fast-deep-equal": "3.1.3",
- "http-status-codes": "2.1.4",
- "json-patch": "0.7.0",
- "json-schema": "0.3.0",
- "ts-optchain": "0.1.8"
- },
- "dependencies": {
- "@types/node": {
- "version": "14.17.9",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz",
- "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g=="
- }
- }
- },
- "@types/json-schema": {
- "version": "7.0.9",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
- "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
- },
"@types/node": {
- "version": "14.17.14",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.14.tgz",
- "integrity": "sha512-rsAj2u8Xkqfc332iXV12SqIsjVi07H479bOP4q94NAcjzmAvapumEhuVIt53koEf7JFrpjgNKjBga5Pnn/GL8A=="
+ "version": "14.17.27",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz",
+ "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw=="
+ },
+ "commander": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.2.0.tgz",
+ "integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA=="
}
}
},
@@ -4066,9 +4041,9 @@
}
},
"@openstapps/core": {
- "version": "0.51.0",
- "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.51.0.tgz",
- "integrity": "sha512-OzO5zsUY3zLnk6X4G9K/6lkoi0z/AdNZBRVhP6nLiVKeB4Y15nMan0XQJqYa3qnTCDpCYvEMi6id7osfCXmlUg==",
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.53.0.tgz",
+ "integrity": "sha512-UglbAFLAh25uNIS3ZVJI3d9HaYJxfq41G1Rok2C0uk/bJU9V9KclK8iw+DegPlqgd9heLYD++oubA0xX38gvQw==",
"requires": {
"@openstapps/core-tools": "0.25.0",
"@types/geojson": "1.0.6",
@@ -6035,9 +6010,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"core-js": {
- "version": "3.17.3",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.3.tgz",
- "integrity": "sha512-lyvajs+wd8N1hXfzob1LdOCCHFU4bGMbqqmLn1Q4QlCpDqWPpGf+p0nj+LNrvDDG33j0hZXw2nsvvVpHysxyNw=="
+ "version": "3.18.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz",
+ "integrity": "sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw=="
},
"has-flag": {
"version": "3.0.0",
@@ -6680,9 +6655,9 @@
}
},
"cli-progress": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.9.0.tgz",
- "integrity": "sha512-g7rLWfhAo/7pF+a/STFH/xPyosaL1zgADhI0OM83hl3c7S43iGvJWEAV2QuDOnQ8i6EMBj/u4+NTd0d5L+4JfA==",
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.9.1.tgz",
+ "integrity": "sha512-AXxiCe2a0Lm0VN+9L0jzmfQSkcZm5EYspfqXKaSIQKqIk+0hnkZ3/v1E9B39mkD6vYhKih3c/RPsJBSwq9O99Q==",
"requires": {
"colors": "^1.1.2",
"string-width": "^4.2.0"
@@ -6894,7 +6869,8 @@
"commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "dev": true
},
"comment-parser": {
"version": "1.2.4",
@@ -20511,9 +20487,9 @@
"integrity": "sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA=="
},
"glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -20522,11 +20498,6 @@
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
- },
- "typescript": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
- "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
}
}
},
@@ -20670,8 +20641,7 @@
"typescript": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
- "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
- "dev": true
+ "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
},
"ua-parser-js": {
"version": "0.7.28",
@@ -20990,15 +20960,30 @@
"dev": true
},
"wait-on": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-5.3.0.tgz",
- "integrity": "sha512-DwrHrnTK+/0QFaB9a8Ol5Lna3k7WvUR4jzSKmz0YaPBpuN2sACyiPVKVfj6ejnjcajAcvn3wlbTyMIn9AZouOg==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz",
+ "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==",
"requires": {
"axios": "^0.21.1",
- "joi": "^17.3.0",
+ "joi": "^17.4.0",
"lodash": "^4.17.21",
"minimist": "^1.2.5",
- "rxjs": "^6.6.3"
+ "rxjs": "^7.1.0"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz",
+ "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==",
+ "requires": {
+ "tslib": "~2.1.0"
+ }
+ },
+ "tslib": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz",
+ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A=="
+ }
}
},
"watchpack": {
diff --git a/package.json b/package.json
index 8ed61df0..e2c029f0 100644
--- a/package.json
+++ b/package.json
@@ -62,9 +62,9 @@
"@ionic/storage-angular": "3.0.6",
"@ngx-translate/core": "13.0.0",
"@ngx-translate/http-loader": "6.0.0",
- "@openstapps/api": "0.32.0",
+ "@openstapps/api": "0.35.0",
"@openstapps/configuration": "0.28.1",
- "@openstapps/core": "0.51.0",
+ "@openstapps/core": "0.53.0",
"cordova-android": "9.0.0",
"cordova-browser": "6.0.0",
"cordova-ios": "6.2.0",
diff --git a/src/app/_helpers/fake-backend.interceptor.ts b/src/app/_helpers/fake-backend.interceptor.ts
index 23258ebc..43d35595 100644
--- a/src/app/_helpers/fake-backend.interceptor.ts
+++ b/src/app/_helpers/fake-backend.interceptor.ts
@@ -38,6 +38,7 @@ import {SampleThings} from './data/sample-things';
/* eslint-disable */
export const sampleIndexResponse: SCIndexResponse = {
app: {
+ aboutPages: {},
campusPolygon: {
coordinates: [
[
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 2f6b856c..1edb2ea0 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -56,6 +56,8 @@ import {UtilModule} from './util/util.module';
import {initLogger} from './_helpers/ts-logger';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {FavoritesModule} from './modules/favorites/favorites.module';
+import {FeedbackModule} from './modules/feedback/feedback.module';
+import {DebugDataCollectorService} from './modules/data/debug-data-collector.service';
registerLocaleData(localeDe);
@@ -144,6 +146,7 @@ const providers: Provider[] = [
DataModule,
IonicModule.forRoot(),
FavoritesModule,
+ FeedbackModule,
MapModule,
MenuModule,
NewsModule,
@@ -171,4 +174,6 @@ const providers: Provider[] = [
? [providers, fakeBackendProvider]
: providers,
})
-export class AppModule {}
+export class AppModule {
+ constructor(public debugDataCollectorService: DebugDataCollectorService) {}
+}
diff --git a/src/app/modules/config/config.provider.spec.ts b/src/app/modules/config/config.provider.spec.ts
index c008b5b1..4be37638 100644
--- a/src/app/modules/config/config.provider.spec.ts
+++ b/src/app/modules/config/config.provider.spec.ts
@@ -220,6 +220,7 @@ const scVersion = packageJson.dependencies['@openstapps/core'];
const sampleIndexResponse: SCIndexResponse = {
app: {
+ aboutPages: {},
campusPolygon: {
coordinates: [[[1, 2]], [[1, 2]]],
type: 'Polygon',
diff --git a/src/app/modules/data/data.provider.ts b/src/app/modules/data/data.provider.ts
index 73268dc8..5e802930 100644
--- a/src/app/modules/data/data.provider.ts
+++ b/src/app/modules/data/data.provider.ts
@@ -28,6 +28,7 @@ import {
SCThingsField,
SCThingType,
SCSaveableThing,
+ SCFeedbackRequest,
} from '@openstapps/core';
import {chunk, fromPairs, toPairs} from 'lodash-es';
import {environment} from '../../../environments/environment';
@@ -292,6 +293,15 @@ export class DataProvider {
);
}
+ /**
+ * Send a feedback message (request)
+ *
+ * @param feedback Feedback message to be sent to the backend
+ */
+ async sendFeedback(feedback: SCFeedbackRequest) {
+ return this.client.feedback(feedback);
+ }
+
/**
* Searches the backend using the provided query and returns response
*
diff --git a/src/app/modules/data/debug-data-collector.service.ts b/src/app/modules/data/debug-data-collector.service.ts
new file mode 100644
index 00000000..9a40acff
--- /dev/null
+++ b/src/app/modules/data/debug-data-collector.service.ts
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2021 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 .
+ */
+import {Injectable} from '@angular/core';
+import {SCFeedbackRequestMetaData} from '@openstapps/core';
+import {Platform} from '@ionic/angular';
+import {DataProvider} from './data.provider';
+import {NavigationEnd, Router} from '@angular/router';
+import {SettingsProvider} from '../settings/settings.provider';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DebugDataCollectorService {
+ /**
+ * Previously visited route
+ */
+ previousRoute: string;
+
+ /**
+ * Current route
+ */
+ currentRoute: string;
+
+ constructor(
+ private platform: Platform,
+ private dataProvider: DataProvider,
+ private router: Router,
+ private settingsProvider: SettingsProvider,
+ ) {
+ this.currentRoute = this.router.url;
+ router.events.subscribe(event => {
+ if (event instanceof NavigationEnd) {
+ this.previousRoute = this.currentRoute;
+ this.currentRoute = event.url;
+ }
+ });
+ }
+
+ /**
+ * Provides meta data for a feedback
+ */
+ async getFeedbackMetaData(): Promise {
+ return {
+ debug: false,
+ platform: this.platform.platforms().join(','),
+ scope: {},
+ state: {
+ route: this.previousRoute,
+ settings: await this.settingsProvider.getCache(),
+ },
+ userAgent: window.navigator.userAgent,
+ version: this.dataProvider.appVersion,
+ sendable: true,
+ };
+ }
+}
diff --git a/src/app/modules/feedback/feedback-page.component.ts b/src/app/modules/feedback/feedback-page.component.ts
new file mode 100644
index 00000000..eedcc054
--- /dev/null
+++ b/src/app/modules/feedback/feedback-page.component.ts
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 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 .
+ */
+import {Component} from '@angular/core';
+import {
+ SCFeedbackRequest,
+ SCFeedbackRequestMetaData,
+ SCMessage,
+ SCPersonWithoutReferences,
+ SCThingOriginType,
+ SCThingType,
+} from '@openstapps/core';
+import {DataProvider} from '../data/data.provider';
+import {DebugDataCollectorService} from '../data/debug-data-collector.service';
+import {AlertController, ToastController} from '@ionic/angular';
+import {TranslateService} from '@ngx-translate/core';
+
+@Component({
+ templateUrl: './feedback-page.html',
+ styleUrls: ['./feedback-page.scss'],
+})
+export class FeedbackPageComponent {
+ constructor(
+ private readonly dataProvider: DataProvider,
+ private readonly debugDataCollector: DebugDataCollectorService,
+ private readonly toastController: ToastController,
+ private readonly alertController: AlertController,
+ private readonly translateService: TranslateService,
+ ) {}
+
+ /**
+ * Sender of the feedback message
+ */
+ author: SCPersonWithoutReferences = {
+ uid: '0f53f16a-e618-5ae0-a1b6-336e34f0d4d1',
+ name: '',
+ type: SCThingType.Person,
+ };
+
+ /**
+ * The message to be sent
+ */
+ message: SCMessage = {
+ uid: '0f53f16a-e618-5ae0-a1b6-336e34f0d4d1',
+ name: 'Bug',
+ type: SCThingType.Message,
+ audiences: [],
+ categories: [],
+ origin: {
+ type: SCThingOriginType.User,
+ created: new Date().toISOString(),
+ },
+ messageBody: '',
+ };
+
+ /**
+ * Terms of feedback accepted or not
+ */
+ termsAgree = false;
+
+ /**
+ * Show meta data or not
+ */
+ showMetaData = false;
+
+ /**
+ * Feedback successfully sent
+ */
+ submitSuccess = false;
+
+ /**
+ * Terms of feedback accepted or not
+ */
+ metaData: SCFeedbackRequestMetaData;
+
+ async ionViewDidEnter() {
+ this.metaData = await this.debugDataCollector.getFeedbackMetaData();
+ }
+
+ /**
+ * Assemble and send the feedback
+ */
+ async onSubmit() {
+ if (this.author.name !== '') {
+ this.message.authors = [this.author];
+ }
+
+ const feedbackRequest: SCFeedbackRequest = {
+ ...this.message,
+ metaData: this.metaData,
+ };
+
+ try {
+ await this.dataProvider.sendFeedback(feedbackRequest);
+ void this.onSuccess();
+ } catch {
+ void this.onError();
+ }
+ }
+
+ /**
+ * Show/hide the meta data
+ */
+ toggleShowMetaData() {
+ this.showMetaData = !this.showMetaData;
+ }
+
+ async onSuccess() {
+ this.submitSuccess = true;
+ const toast = await this.toastController.create({
+ message: this.translateService.instant(
+ 'feedback.system_messages.success',
+ ),
+ duration: 2000,
+ });
+ await toast.present();
+ }
+
+ async onError() {
+ const alert: HTMLIonAlertElement = await this.alertController.create({
+ buttons: [this.translateService.instant('app.ui.CLOSE')],
+ header: this.translateService.instant('app.ui.ERROR'),
+ message: this.translateService.instant('app.errors.UNKNOWN'),
+ });
+
+ await alert.present();
+ }
+}
diff --git a/src/app/modules/feedback/feedback-page.html b/src/app/modules/feedback/feedback-page.html
new file mode 100644
index 00000000..2c20cdd5
--- /dev/null
+++ b/src/app/modules/feedback/feedback-page.html
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+ {{ 'feedback.page.TITLE' | translate }}
+
+
+
+
+
diff --git a/src/app/modules/feedback/feedback-page.scss b/src/app/modules/feedback/feedback-page.scss
new file mode 100644
index 00000000..1050af59
--- /dev/null
+++ b/src/app/modules/feedback/feedback-page.scss
@@ -0,0 +1,6 @@
+pre {
+ white-space: pre-wrap;
+}
+ion-button {
+ margin: 10px;
+}
diff --git a/src/app/modules/feedback/feedback.module.ts b/src/app/modules/feedback/feedback.module.ts
new file mode 100644
index 00000000..044accaf
--- /dev/null
+++ b/src/app/modules/feedback/feedback.module.ts
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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 .
+ */
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {FormsModule} from '@angular/forms';
+import {IonicModule} from '@ionic/angular';
+import {FeedbackPageComponent} from './feedback-page.component';
+import {RouterModule, Routes} from '@angular/router';
+import {TranslateModule} from '@ngx-translate/core';
+import {MarkdownModule} from 'ngx-markdown';
+
+const feedbackRoutes: Routes = [
+ {
+ path: 'feedback',
+ component: FeedbackPageComponent,
+ },
+];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ IonicModule,
+ RouterModule.forChild(feedbackRoutes),
+ TranslateModule,
+ MarkdownModule,
+ ],
+ declarations: [FeedbackPageComponent],
+})
+export class FeedbackModule {}
diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json
index d5f55698..4b6492e7 100644
--- a/src/assets/i18n/de.json
+++ b/src/assets/i18n/de.json
@@ -3,10 +3,11 @@
"abort": "abbrechen",
"app": {
"ui": {
- "CLOSE": "Schließen"
+ "CLOSE": "Schließen",
+ "ERROR": "Fehler"
},
"errors": {
- "UNKNOWN": "Unbekannter Fehler"
+ "UNKNOWN": "Unbekannter Fehler."
}
},
"common": {
@@ -84,6 +85,41 @@
"TITLE": "Favoriten"
}
},
+ "feedback": {
+ "page": {
+ "TITLE": "Feedback"
+ },
+ "form": {
+ "name": {
+ "label": "Name",
+ "placeholder": "Dein Name"
+ },
+ "type": {
+ "label": "Feedback-Art",
+ "values": {
+ "bug": "Fehler",
+ "comment": "Kommentar"
+ }
+ },
+ "email": {
+ "label": "E-Mail",
+ "placeholder": "deine@mailadresse.de"
+ },
+ "message": {
+ "label": "Nachricht",
+ "placeholder": "Deine Nachricht an uns..."
+ },
+ "termsAgree": "Ich bin damit einverstanden, dass Protokolldaten zur Nachverfolgbarkeit von Fehlern mitversandt werden. Es erfolgt keine Weitergabe dieser Daten an Dritte.",
+ "submit": "Absenden",
+ "protocolData": {
+ "show": "Protokolldaten einblenden",
+ "hide": "Protokolldaten ausblenden"
+ }
+ },
+ "system_messages": {
+ "success": "Danke für Dein Feedback."
+ }
+ },
"map": {
"page": {
"TITLE": "Karte",
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index fd0e0129..92394903 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -3,10 +3,11 @@
"abort": "abort",
"app": {
"ui": {
- "CLOSE": "Close"
+ "CLOSE": "Close",
+ "ERROR": "Error"
},
"errors": {
- "UNKNOWN": "Unknown problem"
+ "UNKNOWN": "Unknown problem."
}
},
"common": {
@@ -84,6 +85,41 @@
"TITLE": "Favorites"
}
},
+ "feedback": {
+ "page": {
+ "TITLE": "Feedback"
+ },
+ "form": {
+ "name": {
+ "label": "Name",
+ "placeholder": "Your name"
+ },
+ "type": {
+ "label": "Type of feedback",
+ "values": {
+ "bug": "Bug",
+ "comment": "Comment"
+ }
+ },
+ "email": {
+ "label": "Mail",
+ "placeholder": "your@mailaddress.com"
+ },
+ "message": {
+ "label": "Message",
+ "placeholder": "Your message for us..."
+ },
+ "termsAgree": "I agree to provide the protocol data for easier traceability of errors. The data will not be forwarded to any third parties.",
+ "submit": "Submit",
+ "protocolData": {
+ "show": "Show protocol data",
+ "hide": "Hide protocol data"
+ }
+ },
+ "system_messages": {
+ "success": "Thank you for your feedback."
+ }
+ },
"map": {
"page": {
"TITLE": "Map",